diff options
-rw-r--r-- | release_docs/RELEASE.txt | 2 | ||||
-rw-r--r-- | src/H5FO.c | 103 | ||||
-rw-r--r-- | src/H5FOprivate.h | 9 | ||||
-rw-r--r-- | src/H5Gent.c | 9 | ||||
-rw-r--r-- | src/H5Gnode.c | 18 | ||||
-rw-r--r-- | src/H5O.c | 163 | ||||
-rw-r--r-- | test/unlink.c | 88 |
7 files changed, 274 insertions, 118 deletions
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index a7f2c81..070007c 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -82,6 +82,8 @@ Bug Fixes since HDF5-1.6.2 release Library ------- + - Fixed bug where "resurrecting" a dataset was failing. + QAK - 2004/07/14 - Fixed bug where incorrect data could be read from a chunked dataset after it was extended. QAK - 2004/07/12 - After compound datatype with variable-length string in the fields @@ -22,14 +22,16 @@ #define H5F_PACKAGE /*suppress error about including H5Fpkg */ +/* Pablo information */ +/* (Put before include files to avoid problems with inline functions) */ +#define PABLO_MASK H5FO_mask + #include "H5Eprivate.h" /* Error handling */ #include "H5Fpkg.h" /* File access */ #include "H5FLprivate.h" /* Free lists */ #include "H5FOprivate.h" /* File objects */ #include "H5Oprivate.h" /* Object headers */ -#define PABLO_MASK H5FO_mask - /* Interface initialization */ static int interface_initialize_g = 0; #define INTERFACE_INIT NULL @@ -67,11 +69,11 @@ H5FL_DEFINE_STATIC(H5FO_open_obj_t); REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5FO_create(H5F_t *f) +H5FO_create(const H5F_t *f) { herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5FO_create,FAIL); + FUNC_ENTER_NOAPI(H5FO_create,FAIL) /* Sanity check */ assert(f); @@ -79,10 +81,10 @@ H5FO_create(H5F_t *f) /* Create TBBT used to store open object info */ if((f->shared->open_objs=H5TB_fast_dmake(H5TB_FAST_HADDR_COMPARE))==NULL) - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to create open object TBBT"); + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to create open object TBBT") done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5FO_create() */ @@ -113,7 +115,7 @@ H5FO_opened(const H5F_t *f, haddr_t addr) H5FO_open_obj_t *open_obj; /* Information about open object */ hid_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5FO_opened,FAIL); + FUNC_ENTER_NOAPI(H5FO_opened,FAIL) /* Sanity check */ assert(f); @@ -132,7 +134,7 @@ H5FO_opened(const H5F_t *f, haddr_t addr) ret_value=FAIL; done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5FO_opened() */ @@ -158,12 +160,12 @@ done: REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5FO_insert(H5F_t *f, haddr_t addr, hid_t id) +H5FO_insert(const H5F_t *f, haddr_t addr, hid_t id) { H5FO_open_obj_t *open_obj; /* Information about open object */ herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5FO_insert,FAIL); + FUNC_ENTER_NOAPI(H5FO_insert,FAIL) /* Sanity check */ assert(f); @@ -174,7 +176,7 @@ H5FO_insert(H5F_t *f, haddr_t addr, hid_t id) /* Allocate new opened object information structure */ if((open_obj=H5FL_MALLOC(H5FO_open_obj_t))==NULL) - HGOTO_ERROR(H5E_CACHE,H5E_NOSPACE,FAIL,"memory allocation failed"); + HGOTO_ERROR(H5E_CACHE,H5E_NOSPACE,FAIL,"memory allocation failed") /* Assign information */ open_obj->addr=addr; @@ -183,10 +185,10 @@ H5FO_insert(H5F_t *f, haddr_t addr, hid_t id) /* Insert into TBBT */ if(H5TB_dins(f->shared->open_objs,open_obj,open_obj)==NULL) - HGOTO_ERROR(H5E_CACHE,H5E_CANTINSERT,FAIL,"can't insert object into TBBT"); + HGOTO_ERROR(H5E_CACHE,H5E_CANTINSERT,FAIL,"can't insert object into TBBT") done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5FO_insert() */ @@ -216,7 +218,7 @@ H5FO_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr) H5FO_open_obj_t *open_obj; /* Information about open object */ herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5FO_delete,FAIL); + FUNC_ENTER_NOAPI(H5FO_delete,FAIL) /* Sanity check */ assert(f); @@ -226,23 +228,23 @@ H5FO_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr) /* Get the object node from the TBBT */ if((obj_node=H5TB_dfind(f->shared->open_objs,&addr,NULL))==NULL) - HGOTO_ERROR(H5E_CACHE,H5E_NOTFOUND,FAIL,"can't locate object in TBBT"); + HGOTO_ERROR(H5E_CACHE,H5E_NOTFOUND,FAIL,"can't locate object in TBBT") /* Remove from TBBT */ if((open_obj=H5TB_rem(&f->shared->open_objs->root,obj_node,NULL))==NULL) - HGOTO_ERROR(H5E_CACHE,H5E_CANTRELEASE,FAIL,"can't remove object from TBBT"); + HGOTO_ERROR(H5E_CACHE,H5E_CANTRELEASE,FAIL,"can't remove object from TBBT") /* Check if the object was deleted from the file */ if(open_obj->deleted) { if(H5O_delete(f, dxpl_id, addr)<0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't delete object from file"); + HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't delete object from file") } /* end if */ /* Release the object information */ H5FL_FREE(H5FO_open_obj_t,open_obj); done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5FO_delete() */ @@ -262,19 +264,17 @@ done: Mark an opened object for deletion from the file when it is closed. GLOBAL VARIABLES COMMENTS, BUGS, ASSUMPTIONS - There is currently no way to "undelete" an opened object that is marked - for deletion. EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5FO_mark(const H5F_t *f, haddr_t addr) +H5FO_mark(const H5F_t *f, haddr_t addr, hbool_t deleted) { H5TB_NODE *obj_node; /* TBBT node holding open object */ H5FO_open_obj_t *open_obj; /* Information about open object */ herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5FO_mark,FAIL); + FUNC_ENTER_NOAPI(H5FO_mark,FAIL) /* Sanity check */ assert(f); @@ -286,18 +286,65 @@ H5FO_mark(const H5F_t *f, haddr_t addr) if((obj_node=H5TB_dfind(f->shared->open_objs,&addr,NULL))!=NULL) { open_obj=H5TB_NODE_DATA(obj_node); assert(open_obj); - open_obj->deleted=1; + open_obj->deleted=deleted; } /* end if */ else ret_value=FAIL; done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5FO_mark() */ /*-------------------------------------------------------------------------- NAME + H5FO_marked + PURPOSE + Check if an object is marked to be deleted when it is closed + USAGE + htri_t H5FO_mark(f,addr) + const H5F_t *f; IN: File opened object is in + haddr_t addr; IN: Address of object to delete + + RETURNS + Returns a TRUE/FALSE on success, negative on failure + DESCRIPTION + Checks if the object is currently in the "opened objects" tree and + whether its marks for deletion from the file when it is closed. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +htri_t +H5FO_marked(const H5F_t *f, haddr_t addr) +{ + H5TB_NODE *obj_node; /* TBBT node holding open object */ + H5FO_open_obj_t *open_obj; /* Information about open object */ + htri_t ret_value=FAIL; /* Return value */ + + FUNC_ENTER_NOAPI(H5FO_marked,FAIL) + + /* Sanity check */ + assert(f); + assert(f->shared); + assert(f->shared->open_objs); + assert(H5F_addr_defined(addr)); + + /* Get the object node from the TBBT */ + if((obj_node=H5TB_dfind(f->shared->open_objs,&addr,NULL))!=NULL) { + open_obj=H5TB_NODE_DATA(obj_node); + assert(open_obj); + ret_value=open_obj->deleted; + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FO_marked() */ + + +/*-------------------------------------------------------------------------- + NAME H5FO_dest PURPOSE Destroy an open object info set @@ -315,11 +362,11 @@ done: REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5FO_dest(H5F_t *f) +H5FO_dest(const H5F_t *f) { herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5FO_dest,FAIL); + FUNC_ENTER_NOAPI(H5FO_dest,FAIL) /* Sanity check */ assert(f); @@ -328,12 +375,12 @@ H5FO_dest(H5F_t *f) /* Check if the object info set is empty */ if(H5TB_count(f->shared->open_objs)!=0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTRELEASE, FAIL, "objects still in open object info set"); + HGOTO_ERROR(H5E_CACHE, H5E_CANTRELEASE, FAIL, "objects still in open object info set") /* Release the open object info set TBBT */ f->shared->open_objs=H5TB_dfree(f->shared->open_objs,NULL,NULL); done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5FO_dest() */ diff --git a/src/H5FOprivate.h b/src/H5FOprivate.h index f9780ae..7220b75 100644 --- a/src/H5FOprivate.h +++ b/src/H5FOprivate.h @@ -34,12 +34,13 @@ typedef H5TB_TREE H5FO_t; /* Currently, all open objects are stored in TBB /* Macros */ /* Private routines */ -H5_DLL herr_t H5FO_create(H5F_t *f); +H5_DLL herr_t H5FO_create(const H5F_t *f); H5_DLL hid_t H5FO_opened(const H5F_t *f, haddr_t addr); -H5_DLL herr_t H5FO_insert(H5F_t *f, haddr_t addr, hid_t id); +H5_DLL herr_t H5FO_insert(const H5F_t *f, haddr_t addr, hid_t id); H5_DLL herr_t H5FO_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr); -H5_DLL herr_t H5FO_mark(const H5F_t *f, haddr_t addr); -H5_DLL herr_t H5FO_dest(H5F_t *f); +H5_DLL herr_t H5FO_mark(const H5F_t *f, haddr_t addr, hbool_t deleted); +H5_DLL htri_t H5FO_marked(const H5F_t *f, haddr_t addr); +H5_DLL herr_t H5FO_dest(const H5F_t *f); #endif /* _H5FOprivate_H */ diff --git a/src/H5Gent.c b/src/H5Gent.c index 9596eb0..b050453 100644 --- a/src/H5Gent.c +++ b/src/H5Gent.c @@ -19,6 +19,10 @@ #define H5G_PACKAGE #define H5F_PACKAGE /*suppress error about including H5Fpkg */ +/* Pablo information */ +/* (Put before include files to avoid problems with inline functions) */ +#define PABLO_MASK H5G_ent_mask + #include "H5private.h" /* Generic Functions */ #include "H5Eprivate.h" /* Error handling */ #include "H5Fpkg.h" /* File access */ @@ -26,7 +30,6 @@ #include "H5HLprivate.h" /* Local Heaps */ #include "H5MMprivate.h" /* Memory management */ -#define PABLO_MASK H5G_ent_mask static int interface_initialize_g = 0; #define INTERFACE_INIT NULL @@ -497,12 +500,14 @@ H5G_ent_debug(H5F_t UNUSED *f, hid_t dxpl_id, const H5G_entry_t *ent, FILE * str HDfprintf (stream, "%*s%-*s %lu\n", nested_indent, "", nested_fwidth, "Link value offset:", (unsigned long)(ent->cache.slink.lval_offset)); - if (H5F_addr_defined(heap)) { + if (heap>0 && H5F_addr_defined(heap)) { lval = H5HL_peek (ent->file, dxpl_id, heap, ent->cache.slink.lval_offset); HDfprintf (stream, "%*s%-*s %s\n", nested_indent, "", nested_fwidth, "Link value:", lval); } + else + HDfprintf(stream, "%*s%-*s\n", nested_indent, "", nested_fwidth, "Warning: Invalid heap address given, name not displayed!"); break; default: diff --git a/src/H5Gnode.c b/src/H5Gnode.c index 5009b2c..851de13 100644 --- a/src/H5Gnode.c +++ b/src/H5Gnode.c @@ -1048,7 +1048,8 @@ H5G_node_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, void UNUSED *_lt_key, if (H5G_node_create(f, dxpl_id, H5B_INS_FIRST, NULL, NULL, NULL, new_node_p/*out*/)<0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, H5B_INS_ERROR, "unable to split symbol table node"); - if (NULL==(snrt=H5AC_find(f, dxpl_id, H5AC_SNODE, *new_node_p, NULL, NULL))) + + if (NULL == (snrt = H5AC_protect(f, dxpl_id, H5AC_SNODE, *new_node_p, NULL, NULL))) HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR, "unable to split symbol table node"); HDmemcpy(snrt->entry, sn->entry + H5F_SYM_LEAF_K(f), @@ -1078,7 +1079,6 @@ H5G_node_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, void UNUSED *_lt_key, *rt_key_changed = TRUE; } } - } else { /* Where to insert the new entry? */ ret_value = H5B_INS_NOOP; @@ -1099,7 +1099,9 @@ H5G_node_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, void UNUSED *_lt_key, insert_into->nsyms += 1; done: - if (sn && H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, FALSE) < 0 && ret_value!=H5B_INS_ERROR) + if (snrt && H5AC_unprotect(f, dxpl_id, H5AC_SNODE, *new_node_p, snrt, FALSE) < 0) + HDONE_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to release symbol table node"); + if (sn && H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, FALSE) < 0) HDONE_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to release symbol table node"); FUNC_LEAVE_NOAPI(ret_value); @@ -1729,17 +1731,21 @@ H5G_node_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent, fwidth = MAX(0, fwidth - 3); for (i = 0; i < sn->nsyms; i++) { fprintf(stream, "%*sSymbol %d:\n", indent - 3, "", i); - if (H5F_addr_defined(heap) && + if (heap>0 && H5F_addr_defined(heap) && (s = H5HL_peek(f, dxpl_id, heap, sn->entry[i].name_off))) { fprintf(stream, "%*s%-*s `%s'\n", indent, "", fwidth, "Name:", s); } + else + fprintf(stream, "%*s%-*s\n", indent, "", fwidth, "Warning: Invalid heap address given, name not displayed!"); + H5G_ent_debug(f, dxpl_id, sn->entry + i, stream, indent, fwidth, heap); } - H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, FALSE); - done: + if (sn && H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, FALSE) < 0) + HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to release symbol table node"); + FUNC_LEAVE_NOAPI(ret_value); } @@ -28,23 +28,25 @@ #define H5F_PACKAGE /*suppress error about including H5Fpkg */ #define H5O_PACKAGE /*suppress error about including H5Opkg */ -#include "H5private.h" -#include "H5ACprivate.h" -#include "H5Eprivate.h" -#include "H5Fpkg.h" -#include "H5FLprivate.h" /*Free Lists */ -#include "H5Iprivate.h" -#include "H5MFprivate.h" -#include "H5MMprivate.h" -#include "H5Opkg.h" /* Object header functions */ -#include "H5Pprivate.h" +/* Pablo information */ +/* (Put before include files to avoid problems with inline functions) */ +#define PABLO_MASK H5O_mask + +#include "H5private.h" /* Generic Functions */ +#include "H5ACprivate.h" /* Metadata cache */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Fpkg.h" /* File access */ +#include "H5FLprivate.h" /* Free lists */ +#include "H5Iprivate.h" /* IDs */ +#include "H5MFprivate.h" /* File memory management */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5Opkg.h" /* Object headers */ +#include "H5Pprivate.h" /* Property lists */ #ifdef H5_HAVE_GETTIMEOFDAY #include <sys/time.h> #endif /* H5_HAVE_GETTIMEOFDAY */ -#define PABLO_MASK H5O_mask - /* 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); @@ -60,10 +62,10 @@ static herr_t H5O_share(H5F_t *f, hid_t dxpl_id, const H5O_class_t *type, const H5HG_t *hobj/*out*/); #endif /* NOT_YET */ static unsigned H5O_find_in_ohdr(H5F_t *f, hid_t dxpl_id, H5O_t *oh, - const H5O_class_t **type_p, int sequence); + const H5O_class_t **type_p, int sequence); static int H5O_modify_real(H5G_entry_t *ent, const H5O_class_t *type, int overwrite, unsigned flags, unsigned update_time, const void *mesg, -hid_t dxpl_id); + hid_t dxpl_id); static int H5O_append_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_class_t *type, unsigned flags, const void *mesg); static herr_t H5O_remove_real(H5G_entry_t *ent, const H5O_class_t *type, @@ -140,13 +142,13 @@ static void *(*H5O_fast_g[H5G_NCACHED]) (const H5G_cache_t *, /* Declare a free list to manage the H5O_t struct */ H5FL_DEFINE_STATIC(H5O_t); -/* Declare a PQ free list to manage the H5O_mesg_t array information */ +/* Declare a free list to manage the H5O_mesg_t sequence information */ H5FL_SEQ_DEFINE_STATIC(H5O_mesg_t); -/* Declare a PQ free list to manage the H5O_chunk_t array information */ +/* Declare a free list to manage the H5O_chunk_t sequence information */ H5FL_SEQ_DEFINE_STATIC(H5O_chunk_t); -/* Declare a PQ free list to manage the chunk image information */ +/* Declare a free list to manage the chunk image information */ H5FL_BLK_DEFINE_STATIC(chunk_image); /* Declare external the free list for time_t's */ @@ -231,7 +233,7 @@ H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, H5G_entry_t *ent/*out*/) /* initialize the object header */ if (H5O_init(f, dxpl_id, size_hint, ent, header) != SUCCEED) - HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to initialize object header"); + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to initialize object header"); done: FUNC_LEAVE_NOAPI(ret_value); @@ -474,7 +476,6 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1, unsigned chunkno; haddr_t chunk_addr; size_t chunk_size; - H5O_cont_t *cont = NULL; uint8_t flags; FUNC_ENTER_NOAPI(H5O_load, NULL); @@ -521,7 +522,6 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1, /* read each chunk from disk */ while (H5F_addr_defined(chunk_addr)) { - /* increase chunk array size */ if (oh->nchunks >= oh->alloc_nchunks) { unsigned na = oh->alloc_nchunks + H5O_NCHUNKS; @@ -545,9 +545,7 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1, HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header data"); /* load messages from this chunk */ - for (p = oh->chunk[chunkno].image; - p < oh->chunk[chunkno].image + chunk_size; - p += mesg_size) { + for (p = oh->chunk[chunkno].image; p < oh->chunk[chunkno].image + chunk_size; p += mesg_size) { UINT16DECODE(p, id); UINT16DECODE(p, mesg_size); assert (mesg_size==H5O_ALIGN (mesg_size)); @@ -583,22 +581,21 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1, oh->mesg[mesgno].chunkno = chunkno; } } - assert(p == oh->chunk[chunkno].image + chunk_size); - - /* decode next object header continuation message */ - for (chunk_addr=HADDR_UNDEF; - !H5F_addr_defined(chunk_addr) && curmesg < oh->nmesgs; - curmesg++) { - if (H5O_CONT_ID == oh->mesg[curmesg].type->id) { - uint8_t *p2 = oh->mesg[curmesg].raw; - - cont = (H5O_CONT->decode) (f, dxpl_id, p2, NULL); - oh->mesg[curmesg].native = cont; - chunk_addr = cont->addr; - chunk_size = cont->size; - cont->chunkno = oh->nchunks; /*the next chunk to allocate */ - } - } + + assert(p == oh->chunk[chunkno].image + chunk_size); + + /* decode next object header continuation message */ + for (chunk_addr = HADDR_UNDEF; !H5F_addr_defined(chunk_addr) && curmesg < oh->nmesgs; ++curmesg) { + if (H5O_CONT_ID == oh->mesg[curmesg].type->id) { + H5O_cont_t *cont; + + cont = (H5O_CONT->decode) (f, dxpl_id, oh->mesg[curmesg].raw, NULL); + oh->mesg[curmesg].native = cont; + chunk_addr = cont->addr; + chunk_size = cont->size; + cont->chunkno = oh->nchunks; /*the next chunk to allocate */ + } + } } /* Set return value */ @@ -1190,7 +1187,7 @@ H5O_link(const H5G_entry_t *ent, int adjust, hid_t dxpl_id) /* 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) + if(H5FO_mark(ent->file,ent->header,TRUE)<0) HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't mark object for deletion"); } /* end if */ else { @@ -1203,6 +1200,16 @@ H5O_link(const H5G_entry_t *ent, int adjust, hid_t dxpl_id) } /* end else */ } /* end if */ } else if (adjust>0) { + /* A new object, or one that will be deleted */ + if(oh->nlink==0) { + /* Check if the object is current open, but marked for deletion */ + if(H5FO_marked(ent->file,ent->header)>0) { + /* Remove "delete me" flag on the object */ + if(H5FO_mark(ent->file,ent->header,FALSE)<0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't mark object for deletion"); + } /* end if */ + } /* end if */ + oh->nlink += adjust; oh->cache_info.dirty = TRUE; } @@ -1211,7 +1218,7 @@ H5O_link(const 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, deleted) < 0 && ret_value>=0) + if (oh && H5AC_unprotect(ent->file, dxpl_id, H5AC_OHDR, ent->header, oh, deleted) < 0) HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header"); FUNC_LEAVE_NOAPI(ret_value); @@ -1298,18 +1305,21 @@ H5O_count_real (H5G_entry_t *ent, const H5O_class_t *type, hid_t dxpl_id) assert (type); /* Load the object header */ - if (NULL==(oh=H5AC_find(ent->file, dxpl_id, H5AC_OHDR, ent->header, NULL, NULL))) + if (NULL == (oh = H5AC_protect(ent->file, dxpl_id, H5AC_OHDR, ent->header, NULL, NULL))) HGOTO_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header"); - for (u=acc=0; u<oh->nmesgs; u++) { + /* Loop over all messages, counting the ones of the type looked for */ + for (u=acc=0; u<oh->nmesgs; u++) if (oh->mesg[u].type==type) acc++; - } /* Set return value */ ret_value=acc; done: + if (oh && H5AC_unprotect(ent->file, dxpl_id, H5AC_OHDR, ent->header, oh, FALSE) != SUCCEED) + HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header"); + FUNC_LEAVE_NOAPI(ret_value); } /* end H5O_count_real() */ @@ -1397,7 +1407,7 @@ H5O_exists_real(H5G_entry_t *ent, const H5O_class_t *type, int sequence, hid_t d assert(sequence>=0); /* Load the object header */ - if (NULL==(oh=H5AC_find(ent->file, dxpl_id, H5AC_OHDR, ent->header, NULL, NULL))) + if (NULL == (oh = H5AC_protect(ent->file, dxpl_id, H5AC_OHDR, ent->header, NULL, NULL))) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header"); /* Scan through the messages looking for the right one */ @@ -1412,6 +1422,9 @@ H5O_exists_real(H5G_entry_t *ent, const H5O_class_t *type, int sequence, hid_t d ret_value=(sequence<0); done: + if (oh && H5AC_unprotect(ent->file, dxpl_id, H5AC_OHDR, ent->header, oh, FALSE) != SUCCEED) + HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header"); + FUNC_LEAVE_NOAPI(ret_value); } /* end H5O_exists_real() */ @@ -1493,17 +1506,22 @@ done: * Aug 6 1997 * * Modifications: - * + * Bill Wendling, 2003-09-30 + * Protect the object header and pass it into the H5O_find_in_ohdr + * function. This is done because the H5O_find_in_ohdr used to + * protect the ohdr, find the message, and then unprotect it. This + * saves time and also helps the FPHDF5 stuff, where unprotecting + * actually destroys the object in the cache. *------------------------------------------------------------------------- */ void * H5O_read_real(H5G_entry_t *ent, const H5O_class_t *type, int sequence, void *mesg, hid_t dxpl_id) { - H5O_t *oh = NULL; - int idx; - H5G_cache_t *cache = NULL; - H5G_type_t cache_type; - void *ret_value = NULL; + H5O_t *oh = NULL; + int idx; + H5G_cache_t *cache = NULL; + H5G_type_t cache_type; + void *ret_value = NULL; FUNC_ENTER_NOAPI_NOINIT(H5O_read_real); @@ -1516,6 +1534,7 @@ H5O_read_real(H5G_entry_t *ent, const H5O_class_t *type, int sequence, void *mes /* can we get it from the symbol table entry? */ cache = H5G_ent_cache(ent, &cache_type); + if (H5O_fast_g[cache_type]) { ret_value = (H5O_fast_g[cache_type]) (cache, type, mesg); if (ret_value) @@ -1553,7 +1572,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, FALSE) < 0 && ret_value!=NULL) + if (oh && H5AC_unprotect(ent->file, dxpl_id, H5AC_OHDR, ent->header, oh, FALSE) < 0) HDONE_ERROR(H5E_OHDR, H5E_PROTECT, NULL, "unable to release object header"); FUNC_LEAVE_NOAPI(ret_value); @@ -1563,25 +1582,27 @@ done: /*------------------------------------------------------------------------- * Function: H5O_find_in_ohdr * - * Purpose: Find a message in the object header without consulting - * a symbol table entry. + * Purpose: Find a message in the object header without consulting + * a symbol table entry. * - * Return: Success: Index number of message. + * Return: Success: Index number of message. + * Failure: Negative * - * Failure: Negative - * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Aug 6 1997 + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 6 1997 * * Modifications: - * Robb Matzke, 1999-07-28 - * The ADDR argument is passed by value. + * Robb Matzke, 1999-07-28 + * The ADDR argument is passed by value. + * + * Bill Wendling, 2003-09-30 + * Modified so that the object header needs to be AC_protected + * before calling this function. *------------------------------------------------------------------------- */ static unsigned -H5O_find_in_ohdr(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_class_t **type_p, - int sequence) +H5O_find_in_ohdr(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_class_t **type_p, int sequence) { unsigned u; const H5O_class_t *type = NULL; @@ -1601,6 +1622,7 @@ H5O_find_in_ohdr(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_class_t **type_p, if (--sequence < 0) break; } + if (sequence >= 0) HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, UFAIL, "unable to find object header message"); @@ -1613,6 +1635,7 @@ H5O_find_in_ohdr(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_class_t **type_p, } else { type = oh->mesg[u].type; } + if (NULL == oh->mesg[u].native) { assert(type->decode); oh->mesg[u].native = (type->decode) (f, dxpl_id, oh->mesg[u].raw, NULL); @@ -1820,7 +1843,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, FALSE) < 0 && ret_value!=FAIL) + 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_NOAPI(ret_value); @@ -1903,7 +1926,7 @@ H5O_unprotect(H5G_entry_t *ent, H5O_t *oh, hid_t dxpl_id) assert(oh); 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"); + HGOTO_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header"); done: FUNC_LEAVE_NOAPI(ret_value); @@ -2243,7 +2266,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, FALSE)<0 && ret_value>=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_NOAPI(ret_value); @@ -2495,7 +2518,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, FALSE) < 0 && ret_value>=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_NOAPI(ret_value); @@ -3135,7 +3158,7 @@ H5O_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr) 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) + if (oh && H5AC_unprotect(f, dxpl_id, H5AC_OHDR, addr, oh, TRUE)<0) HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header"); FUNC_LEAVE_NOAPI(ret_value); @@ -3546,7 +3569,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, FALSE) < 0 && ret_value>=0) + if (oh && H5AC_unprotect(f, dxpl_id, H5AC_OHDR, addr, oh, FALSE) < 0) HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header"); FUNC_LEAVE_NOAPI(ret_value); diff --git a/test/unlink.c b/test/unlink.c index cf9b5c8..123847a 100644 --- a/test/unlink.c +++ b/test/unlink.c @@ -29,6 +29,7 @@ const char *FILENAME[] = { "lunlink", "filespace", "slashes", + "resurrect", NULL }; @@ -1303,7 +1304,7 @@ static int test_create_unlink(const char *msg, hid_t fapl) return 0; error: - return -1; + return 1; } /* end test_create_unlink() */ @@ -1373,7 +1374,7 @@ test_link_slashes(void) return 0; error: - return -1; + return 1; } /* end test_link_slashes() */ @@ -1443,7 +1444,7 @@ test_unlink_slashes(void) return 0; error: - return -1; + return 1; } /* end test_unlink_slashes() */ /* @@ -1532,7 +1533,7 @@ test_unlink_rightleaf(hid_t fid) return 0; error: - return -1; + return 1; } /* end test_unlink_rightleaf() */ @@ -1593,7 +1594,7 @@ test_unlink_rightnode(hid_t fid) return 0; error: - return -1; + return 1; } /* end test_unlink_rightnode() */ @@ -1797,11 +1798,80 @@ test_unlink_middlenode(hid_t fid) return 0; error: - return -1; + return 1; } /* end test_unlink_middlenode() */ /*------------------------------------------------------------------------- + * Function: test_resurrect_dataset + * + * Purpose: Tests deleting a dataset while its still open and then + * "resurrecting" it by creating a link to it again. + * + * Return: Success: 0 + * Failure: number of errors + * + * Programmer: Quincey Koziol + * Wednesday, July 14, 2004 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +test_resurrect_dataset(void) +{ + hid_t f, s, d, fapl; + char filename[1024]; + + TESTING("Resurrecting dataset after deletion"); + + /* Create file */ + fapl = h5_fileaccess(); + h5_fixname(FILENAME[6], fapl, filename, sizeof filename); + + /* Create the file */ + if((f = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; + + /* Create a dataset in the file */ + if((s = H5Screate(H5S_SCALAR))<0) TEST_ERROR; + if((d = H5Dcreate(f, DATASETNAME, H5T_NATIVE_INT, s, H5P_DEFAULT))<0) TEST_ERROR; + if(H5Sclose(s)<0) TEST_ERROR; + + /* Unlink the dataset while it's open (will mark it for deletion when closed) */ + if(H5Gunlink(f, DATASETNAME)<0) TEST_ERROR; + + /* Re-link the dataset to the group hierarchy (shouldn't get deleted now) */ + if(H5Glink2(d, ".", H5G_LINK_HARD, f, DATASET2NAME)<0) TEST_ERROR; + + /* Close things */ + if(H5Dclose(d)<0) TEST_ERROR; + if(H5Fclose(f)<0) TEST_ERROR; + + /* Re-open the file */ + if((f=H5Fopen(filename, H5F_ACC_RDONLY, fapl))<0) TEST_ERROR; + + /* Attempt to open the dataset under the new name */ + if((d=H5Dopen(f,DATASET2NAME))<0) TEST_ERROR; + + /* Close things */ + if(H5Dclose(d)<0) TEST_ERROR; + if(H5Fclose(f)<0) TEST_ERROR; + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Sclose(s); + H5Dclose(d); + H5Fclose(f); + } H5E_END_TRY; + return 1; +} /* end test_resurrect_dataset() */ + + +/*------------------------------------------------------------------------- * Function: main * * Purpose: Test H5Gunlink() @@ -1872,11 +1942,14 @@ main(void) nerrors += test_link_slashes(); nerrors += test_unlink_slashes(); - + /* Test specific B-tree removal issues */ nerrors += test_unlink_rightleaf(file); nerrors += test_unlink_rightnode(file); nerrors += test_unlink_middlenode(file); + + /* Test "resurrecting" objects */ + nerrors += test_resurrect_dataset(); /* Close */ if (H5Fclose(file)<0) TEST_ERROR; @@ -1890,4 +1963,3 @@ main(void) error: return 1; } - |