diff options
-rw-r--r-- | src/H5O.c | 224 | ||||
-rw-r--r-- | src/H5Olayout.c | 58 | ||||
-rw-r--r-- | src/H5Opkg.h | 5 | ||||
-rw-r--r-- | src/H5Ostab.c | 39 |
4 files changed, 308 insertions, 18 deletions
@@ -48,10 +48,6 @@ /* PRIVATE PROTOTYPES */ static herr_t H5O_init(H5F_t *f, hid_t dxpl_id, size_t size_hint, H5G_entry_t *ent/*out*/, haddr_t header); -static H5O_t *H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_udata1, - void *_udata2); -static herr_t H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5O_t *oh); -static herr_t H5O_dest(H5F_t *f, H5O_t *oh); static herr_t H5O_reset_real(const H5O_class_t *type, void *native); static void * H5O_free_real(const H5O_class_t *type, void *mesg); static void * H5O_copy_real(const H5O_class_t *type, const void *mesg, @@ -79,6 +75,14 @@ static unsigned H5O_alloc(H5F_t *f, H5O_t *oh, const H5O_class_t *type, size_t size); static unsigned H5O_alloc_extend_chunk(H5O_t *oh, unsigned chunkno, size_t size); static unsigned H5O_alloc_new_chunk(H5F_t *f, H5O_t *oh, size_t size); +static herr_t H5O_delete_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh); + +/* Metadata cache callbacks */ +static H5O_t *H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_udata1, + void *_udata2); +static herr_t H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5O_t *oh); +static herr_t H5O_dest(H5F_t *f, H5O_t *oh); +static herr_t H5O_clear(H5O_t *oh); /* H5O inherits cache-like properties from H5AC */ static const H5AC_class_t H5AC_OHDR[1] = {{ @@ -86,6 +90,7 @@ static const H5AC_class_t H5AC_OHDR[1] = {{ (H5AC_load_func_t)H5O_load, (H5AC_flush_func_t)H5O_flush, (H5AC_dest_func_t)H5O_dest, + (H5AC_clear_func_t)H5O_clear, }}; /* Interface initialization */ @@ -503,7 +508,7 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1, UINT32DECODE(p, oh->nlink); /* decode first chunk info */ - chunk_addr = addr + (hsize_t)H5O_SIZEOF_HDR(f); + chunk_addr = addr + (hsize_t)hdr_size; UINT32DECODE(p, chunk_size); /* build the message array */ @@ -840,7 +845,47 @@ H5O_dest(H5F_t UNUSED *f, H5O_t *oh) H5FL_FREE(H5O_t,oh); FUNC_LEAVE_NOAPI(SUCCEED); -} +} /* end H5O_dest() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_clear + * + * Purpose: Mark a object header in memory as non-dirty. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 20 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_clear(H5O_t *oh) +{ + unsigned u; /* Local index variable */ + + FUNC_ENTER_NOINIT(H5O_clear); + + /* check args */ + assert(oh); + + /* Mark chunks as clean */ + for (u = 0; u < oh->nchunks; u++) + oh->chunk[u].dirty=FALSE; + + /* Mark messages as clean */ + for (u = 0; u < oh->nmesgs; u++) + oh->mesg[u].dirty=FALSE; + + /* Mark whole header as clean */ + oh->cache_info.dirty=FALSE; + + FUNC_LEAVE_NOAPI(SUCCEED); +} /* end H5O_clear() */ /*------------------------------------------------------------------------- @@ -1114,6 +1159,7 @@ int H5O_link(H5G_entry_t *ent, int adjust, hid_t dxpl_id) { H5O_t *oh = NULL; + hbool_t deleted=FALSE; /* Whether the object was deleted as a result of this action */ int ret_value = FAIL; FUNC_ENTER_NOAPI(H5O_link, FAIL); @@ -1136,6 +1182,24 @@ H5O_link(H5G_entry_t *ent, int adjust, hid_t dxpl_id) HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "link count would be negative"); oh->nlink += adjust; oh->cache_info.dirty = TRUE; + + /* Check if the object should be deleted */ + if(oh->nlink==0) { + /* Check if the object is still open by the user */ + if(H5FO_opened(ent->file,ent->header)>=0) { + /* Flag the object to be deleted when it's closed */ + if(H5FO_mark(ent->file,ent->header)<0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't mark object for deletion"); + } /* end if */ + else { + /* Delete object right now */ + if(H5O_delete_oh(ent->file,dxpl_id,oh)<0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't delete object from file"); + + /* Mark the object header as deleted */ + deleted=TRUE; + } /* end else */ + } /* end if */ } else if (adjust>0) { oh->nlink += adjust; oh->cache_info.dirty = TRUE; @@ -1145,7 +1209,7 @@ H5O_link(H5G_entry_t *ent, int adjust, hid_t dxpl_id) ret_value = oh->nlink; done: - if (oh && H5AC_unprotect(ent->file, dxpl_id, H5AC_OHDR, ent->header, oh) < 0 && ret_value>=0) + if (oh && H5AC_unprotect(ent->file, dxpl_id, H5AC_OHDR, ent->header, oh, deleted) < 0 && ret_value>=0) HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header"); FUNC_LEAVE_NOAPI(ret_value); @@ -1505,7 +1569,7 @@ H5O_read_real(H5G_entry_t *ent, const H5O_class_t *type, int sequence, void *mes } done: - if (oh && H5AC_unprotect(ent->file, dxpl_id, H5AC_OHDR, ent->header, oh) < 0 && ret_value!=NULL) + if (oh && H5AC_unprotect(ent->file, dxpl_id, H5AC_OHDR, ent->header, oh, FALSE) < 0 && ret_value!=NULL) HDONE_ERROR(H5E_OHDR, H5E_PROTECT, NULL, "unable to release object header"); FUNC_LEAVE_NOAPI(ret_value); @@ -1834,7 +1898,7 @@ H5O_modify_real(H5G_entry_t *ent, const H5O_class_t *type, int overwrite, ret_value = sequence; done: - if (oh && H5AC_unprotect(ent->file, dxpl_id, H5AC_OHDR, ent->header, oh) < 0 && ret_value!=FAIL) + if (oh && H5AC_unprotect(ent->file, dxpl_id, H5AC_OHDR, ent->header, oh, FALSE) < 0 && ret_value!=FAIL) HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header"); FUNC_LEAVE_NOAPI(ret_value); @@ -1916,7 +1980,7 @@ H5O_unprotect(H5G_entry_t *ent, H5O_t *oh, hid_t dxpl_id) assert(H5F_addr_defined(ent->header)); assert(oh); - if (H5AC_unprotect(ent->file, dxpl_id, H5AC_OHDR, ent->header, oh) < 0) + if (H5AC_unprotect(ent->file, dxpl_id, H5AC_OHDR, ent->header, oh, FALSE) < 0) HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header"); done: @@ -2206,7 +2270,7 @@ H5O_touch(H5G_entry_t *ent, hbool_t force, hid_t dxpl_id) HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to update object modificaton time"); done: - if (oh && H5AC_unprotect(ent->file, dxpl_id, H5AC_OHDR, ent->header, oh)<0 && ret_value>=0) + if (oh && H5AC_unprotect(ent->file, dxpl_id, H5AC_OHDR, ent->header, oh, FALSE)<0 && ret_value>=0) HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header"); FUNC_LEAVE_NOAPI(ret_value); @@ -2310,7 +2374,7 @@ H5O_bogus(H5G_entry_t *ent, hid_t dxpl_id) HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to update object 'bogus' message"); done: - if (oh && H5AC_unprotect(ent->file, dxpl_id, H5AC_OHDR, ent->header, oh)<0) + if (oh && H5AC_unprotect(ent->file, dxpl_id, H5AC_OHDR, ent->header, oh, FALSE)<0) HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header"); FUNC_LEAVE(ret_value); @@ -2466,7 +2530,7 @@ H5O_remove_real(H5G_entry_t *ent, const H5O_class_t *type, int sequence, hid_t d HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to remove constant message(s)"); done: - if (oh && H5AC_unprotect(ent->file, dxpl_id, H5AC_OHDR, ent->header, oh) < 0 && ret_value>=0) + if (oh && H5AC_unprotect(ent->file, dxpl_id, H5AC_OHDR, ent->header, oh, FALSE) < 0 && ret_value>=0) HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header"); FUNC_LEAVE_NOAPI(ret_value); @@ -3018,6 +3082,138 @@ done: /*------------------------------------------------------------------------- + * Function: H5O_delete + * + * Purpose: Delete an object header from a file. This frees the file + * space used for the object header (and it's continuation blocks) + * and also walks through each header message and asks it to + * remove all the pieces of the file referenced by the header. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 19 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr) +{ + H5O_t *oh=NULL; /* Object header information */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_delete,FAIL); + + /* Check args */ + assert (f); + assert(H5F_addr_defined(addr)); + + /* Get the object header information */ + if (NULL == (oh = H5AC_protect(f, dxpl_id, H5AC_OHDR, addr, NULL, NULL))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header"); + + /* Delete object */ + if(H5O_delete_oh(f,dxpl_id,oh)<0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't delete object from file"); + +done: + if (oh && H5AC_unprotect(f, dxpl_id, H5AC_OHDR, addr, oh, TRUE)<0 && ret_value>=0) + HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header"); + + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5O_delete() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_delete_oh + * + * Purpose: Internal function to: + * Delete an object header from a file. This frees the file + * space used for the object header (and it's continuation blocks) + * and also walks through each header message and asks it to + * remove all the pieces of the file referenced by the header. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 19 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_delete_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh) +{ + H5O_mesg_t *curr_msg; /* Pointer to current message being operated on */ + H5O_chunk_t *curr_chk; /* Pointer to current chunk being operated on */ + unsigned u; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOINIT(H5O_delete_oh); + + /* Check args */ + assert (f); + assert (oh); + + /* Walk through the list of object header messages, asking each on to + * delete any file space used + */ + for (u = 0, curr_msg=&oh->mesg[0]; u < oh->nmesgs; u++,curr_msg++) { + const H5O_class_t *type = NULL; + + /* Don't handle shared messages yet */ + assert(!(curr_msg->flags & H5O_FLAG_SHARED)); + + /* Get the message's type */ + type = curr_msg->type; + + /* Check if there is a file space deletion callback for this type of message */ + if(type->delete) { + /* + * Decode the message if necessary. + */ + if (NULL == curr_msg->native) { + assert(type->decode); + curr_msg->native = (type->decode) (f, dxpl_id, curr_msg->raw, NULL); + if (NULL == curr_msg->native) + HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "unable to decode message"); + } /* end if */ + + if ((type->delete)(f, dxpl_id, curr_msg->native)<0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete file space for object header message"); + } /* end if */ + } /* end for */ + + /* Free all the chunks for the object header */ + for (u = 0, curr_chk=&oh->chunk[0]; u < oh->nchunks; u++,curr_chk++) { + haddr_t chk_addr; /* Actual address of chunk */ + hsize_t chk_size; /* Actual size of chunk */ + + if(u==0) { + chk_addr = curr_chk->addr - H5O_SIZEOF_HDR(f); + chk_size = curr_chk->size + H5O_SIZEOF_HDR(f); + } /* end if */ + else { + chk_addr = curr_chk->addr; + chk_size = curr_chk->size; + } /* end else */ + + /* Free the file space for the chunk */ + if (H5MF_xfree(f, H5FD_MEM_OHDR, dxpl_id, chk_addr, chk_size)<0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free object header"); + } /* end for */ + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5O_delete_oh() */ + + +/*------------------------------------------------------------------------- * Function: H5O_debug_id * * Purpose: Act as a proxy for calling the 'debug' method for a @@ -3238,7 +3434,7 @@ H5O_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int f HDfprintf(stream, "*** TOTAL SIZE DOES NOT MATCH ALLOCATED SIZE!\n"); done: - if (oh && H5AC_unprotect(f, dxpl_id, H5AC_OHDR, addr, oh) < 0 && ret_value>=0) + if (oh && H5AC_unprotect(f, dxpl_id, H5AC_OHDR, addr, oh, FALSE) < 0 && ret_value>=0) HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header"); FUNC_LEAVE_NOAPI(ret_value); diff --git a/src/H5Olayout.c b/src/H5Olayout.c index 43d1df7..fc1eeae 100644 --- a/src/H5Olayout.c +++ b/src/H5Olayout.c @@ -24,6 +24,7 @@ #include "H5Dprivate.h" #include "H5Eprivate.h" #include "H5FLprivate.h" /*Free Lists */ +#include "H5MFprivate.h" /* File space management */ #include "H5MMprivate.h" #include "H5Opkg.h" /* Object header functions */ @@ -34,6 +35,7 @@ static void *H5O_layout_copy(const void *_mesg, void *_dest); static size_t H5O_layout_size(H5F_t *f, const void *_mesg); static herr_t H5O_layout_reset (void *_mesg); static herr_t H5O_layout_free (void *_mesg); +static herr_t H5O_layout_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg); static herr_t H5O_layout_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); @@ -47,7 +49,8 @@ const H5O_class_t H5O_LAYOUT[1] = {{ H5O_layout_copy, /*copy the native value */ H5O_layout_size, /*size of message on disk */ H5O_layout_reset, /*reset method */ - H5O_layout_free, /*free the struct */ + H5O_layout_free, /*free the struct */ + H5O_layout_delete, /* file delete method */ NULL, /*get share method */ NULL, /*set share method */ H5O_layout_debug, /*debug the message */ @@ -444,6 +447,59 @@ done: /*------------------------------------------------------------------------- + * Function: H5O_layout_delete + * + * Purpose: Free file space referenced by message + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Wednesday, March 19, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_layout_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg) +{ + const H5O_layout_t *mesg = (const H5O_layout_t *) _mesg; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_layout_delete, FAIL); + + /* check args */ + assert(f); + assert(mesg); + + /* Perform different actions, depending on the type of storage */ + switch(mesg->type) { + case H5D_COMPACT: /* Compact data storage */ + /* Nothing required */ + break; + + case H5D_CONTIGUOUS: /* Contiguous block on disk */ + /* Free the file space for the raw data */ + if (H5F_contig_delete(f, dxpl_id, mesg)<0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free raw data"); + break; + + case H5D_CHUNKED: /* Chunked blocks on disk */ + /* Free the file space for the raw data */ + if (H5F_istore_delete(f, dxpl_id, mesg)<0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free raw data"); + break; + + default: + HGOTO_ERROR (H5E_OHDR, H5E_BADTYPE, FAIL, "not valid storage type"); + } /* end switch */ + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5O_layout_delete() */ + + +/*------------------------------------------------------------------------- * Function: H5O_layout_debug * * Purpose: Prints debugging info for a message. diff --git a/src/H5Opkg.h b/src/H5Opkg.h index 2ca5a96..ceb4ae3 100644 --- a/src/H5Opkg.h +++ b/src/H5Opkg.h @@ -66,8 +66,9 @@ typedef struct H5O_class_t { size_t (*raw_size)(H5F_t*, const void*);/*sizeof raw val */ herr_t (*reset)(void *); /*free nested data structs */ herr_t (*free)(void *); /*free main data struct */ - herr_t (*get_share)(H5F_t*, const void*, struct H5O_shared_t*); - herr_t (*set_share)(H5F_t*, void*, const struct H5O_shared_t*); + herr_t (*delete)(H5F_t *, hid_t, const void *); /* Delete space in file referenced by this message */ + herr_t (*get_share)(H5F_t*, const void*, struct H5O_shared_t*); /* Get shared information */ + herr_t (*set_share)(H5F_t*, void*, const struct H5O_shared_t*); /* Set shared information */ herr_t (*debug)(H5F_t*, hid_t, const void*, FILE*, int, int); } H5O_class_t; diff --git a/src/H5Ostab.c b/src/H5Ostab.c index 3258964..17986c1 100644 --- a/src/H5Ostab.c +++ b/src/H5Ostab.c @@ -42,6 +42,7 @@ static herr_t H5O_stab_encode(H5F_t *f, uint8_t *p, const void *_mesg); static void *H5O_stab_copy(const void *_mesg, void *_dest); static size_t H5O_stab_size(H5F_t *f, const void *_mesg); static herr_t H5O_stab_free (void *_mesg); +static herr_t H5O_stab_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg); static herr_t H5O_stab_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); @@ -55,7 +56,8 @@ const H5O_class_t H5O_STAB[1] = {{ H5O_stab_copy, /*copy the native value */ H5O_stab_size, /*size of symbol table entry */ NULL, /*default reset method */ - H5O_stab_free, /* free method */ + H5O_stab_free, /* free method */ + H5O_stab_delete, /* file delete method */ NULL, /*get share method */ NULL, /*set share method */ H5O_stab_debug, /*debug the message */ @@ -313,6 +315,41 @@ done: /*------------------------------------------------------------------------- + * Function: H5O_stab_delete + * + * Purpose: Free file space referenced by message + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Thursday, March 20, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_stab_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg) +{ + const H5O_stab_t *stab = (const H5O_stab_t *) _mesg; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_stab_delete, FAIL); + + /* check args */ + assert(f); + assert(stab); + + /* Free the file space for the symbol table */ + if (H5G_stab_delete(f, dxpl_id, stab->btree_addr, stab->heap_addr)<0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free symbol table"); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5O_stab_delete() */ + + +/*------------------------------------------------------------------------- * Function: H5O_stab_debug * * Purpose: Prints debugging info for a symbol table message. |