From f0fe9b0114591c13051ccc92a2fca81b1ec3ca95 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Wed, 14 Jul 2004 14:08:37 -0500 Subject: [svn-r8875] Purpose: Bug fix Description: Correct problems with "resurrecting" a dataset in a file. (This occurs when a dataset which is open gets unlinked from the group hierarchy (making it "dead" and marked for deletion in the file) and then is re-linked to the group hierarchy). Note that the current solution applies only to datasets, further work will fix this for groups and named datatypes also. Also, fix the "debug" routines to be a little more helpful in certain situations. Additionally, fix a locking bug in the symbol table node splitting routine which could be [one of] the cause[s] of the file corruption in flexible parallel operation. Platforms tested: FreeBSD 4.10 (sleipnir) w/parallel h5committested --- release_docs/RELEASE.txt | 2 + src/H5FO.c | 103 ++++++++++++++++++++++-------- src/H5FOprivate.h | 9 +-- src/H5Gent.c | 9 ++- src/H5Gnode.c | 18 ++++-- src/H5O.c | 163 +++++++++++++++++++++++++++-------------------- 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 diff --git a/src/H5FO.c b/src/H5FO.c index efb5f65..7f34556 100644 --- a/src/H5FO.c +++ b/src/H5FO.c @@ -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); } diff --git a/src/H5O.c b/src/H5O.c index 42a97a6..b7ef425 100644 --- a/src/H5O.c +++ b/src/H5O.c @@ -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 #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; unmesgs; u++) { + /* Loop over all messages, counting the ones of the type looked for */ + for (u=acc=0; unmesgs; 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; } - -- cgit v0.12