diff options
-rw-r--r-- | release_docs/RELEASE.txt | 2 | ||||
-rw-r--r-- | src/H5FO.c | 52 | ||||
-rw-r--r-- | src/H5FOprivate.h | 3 | ||||
-rw-r--r-- | src/H5Gent.c | 4 | ||||
-rw-r--r-- | src/H5Gnode.c | 14 | ||||
-rw-r--r-- | src/H5O.c | 16 | ||||
-rw-r--r-- | test/unlink.c | 86 |
7 files changed, 151 insertions, 26 deletions
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index 1cd9edc..a0bbcd8 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -142,6 +142,8 @@ Bug Fixes since HDF5-1.6.0 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 - Fixed failure to read data back from file of compound type with @@ -259,13 +259,11 @@ 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 */ @@ -283,7 +281,7 @@ 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; @@ -294,6 +292,52 @@ H5FO_mark(const H5F_t *f, haddr_t addr) /*-------------------------------------------------------------------------- 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_NOFUNC(H5FO_marked) + + /* 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 */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FO_marked() */ + + +/*-------------------------------------------------------------------------- + NAME H5FO_dest PURPOSE Destroy an open object info set diff --git a/src/H5FOprivate.h b/src/H5FOprivate.h index 389f7ad..7220b75 100644 --- a/src/H5FOprivate.h +++ b/src/H5FOprivate.h @@ -38,7 +38,8 @@ 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(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_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 6f206dd..4aaaf70 100644 --- a/src/H5Gent.c +++ b/src/H5Gent.c @@ -490,7 +490,7 @@ 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)) { const H5HL_t *heap_ptr; heap_ptr = H5HL_protect(ent->file, dxpl_id, heap); @@ -500,6 +500,8 @@ H5G_ent_debug(H5F_t UNUSED *f, hid_t dxpl_id, const H5G_entry_t *ent, FILE * str lval); H5HL_unprotect(ent->file, dxpl_id, heap_ptr, heap); } + 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 279d9da..6743c7e 100644 --- a/src/H5Gnode.c +++ b/src/H5Gnode.c @@ -1163,13 +1163,6 @@ H5G_node_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, void UNUSED *_lt_key, *rt_key_changed = TRUE; } } - - if (H5AC_unprotect(f, dxpl_id, H5AC_SNODE, *new_node_p, snrt, FALSE) != SUCCEED) { - snrt = NULL; - HGOTO_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to release symbol table node"); - } - - snrt=NULL; /* Make certain future references will be caught */ } else { /* Where to insert the new entry? */ ret_value = H5B_INS_NOOP; @@ -1190,6 +1183,8 @@ H5G_node_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, void UNUSED *_lt_key, insert_into->nsyms += 1; done: + 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"); @@ -1903,8 +1898,7 @@ H5G_node_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent, 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)) { if (NULL == (heap_ptr = H5HL_protect(f, dxpl_id, heap))) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to protect symbol name"); @@ -1917,6 +1911,8 @@ H5G_node_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent, HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol name"); heap_ptr=NULL; s=NULL; } + 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); } @@ -1243,7 +1243,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 { @@ -1256,6 +1256,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.is_dirty = TRUE; } @@ -1974,8 +1984,6 @@ H5O_unprotect(H5G_entry_t *ent, H5O_t *oh, hid_t dxpl_id) if (H5AC_unprotect(ent->file, dxpl_id, H5AC_OHDR, ent->header, oh, FALSE) < 0) HGOTO_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header"); - oh = NULL; - done: FUNC_LEAVE_NOAPI(ret_value); } /* end H5O_unprotect() */ @@ -2624,7 +2632,7 @@ H5O_alloc_extend_chunk(H5O_t *oh, unsigned chunkno, size_t size) /* try to extend a null message */ for (idx=0; idx<oh->nmesgs; idx++) { if (oh->mesg[idx].chunkno==chunkno) { - if ( H5O_NULL_ID == oh->mesg[idx].type->id && + if (H5O_NULL_ID == oh->mesg[idx].type->id && (oh->mesg[idx].raw + oh->mesg[idx].raw_size == oh->chunk[chunkno].image + oh->chunk[chunkno].size)) { diff --git a/test/unlink.c b/test/unlink.c index 80ccd59..9f8e5b2 100644 --- a/test/unlink.c +++ b/test/unlink.c @@ -29,6 +29,7 @@ const char *FILENAME[] = { "lunlink", "filespace", "slashes", + "resurrect", NULL }; @@ -1298,7 +1299,7 @@ static int test_create_unlink(const char *msg, hid_t fapl) return 0; error: - return -1; + return 1; } /* end test_create_unlink() */ @@ -1368,7 +1369,7 @@ test_link_slashes(void) return 0; error: - return -1; + return 1; } /* end test_link_slashes() */ @@ -1438,7 +1439,7 @@ test_unlink_slashes(void) return 0; error: - return -1; + return 1; } /* end test_unlink_slashes() */ /* @@ -1527,7 +1528,7 @@ test_unlink_rightleaf(hid_t fid) return 0; error: - return -1; + return 1; } /* end test_unlink_rightleaf() */ @@ -1588,7 +1589,7 @@ test_unlink_rightnode(hid_t fid) return 0; error: - return -1; + return 1; } /* end test_unlink_rightnode() */ @@ -1792,11 +1793,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() @@ -1868,6 +1938,9 @@ main(void) 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; @@ -1881,4 +1954,3 @@ main(void) error: return 1; } - |