summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--release_docs/RELEASE.txt2
-rw-r--r--src/H5FO.c52
-rw-r--r--src/H5FOprivate.h3
-rw-r--r--src/H5Gent.c4
-rw-r--r--src/H5Gnode.c14
-rw-r--r--src/H5O.c16
-rw-r--r--test/unlink.c86
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
diff --git a/src/H5FO.c b/src/H5FO.c
index 7cb5508..32b3706 100644
--- a/src/H5FO.c
+++ b/src/H5FO.c
@@ -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);
}
diff --git a/src/H5O.c b/src/H5O.c
index 2b1eb15..f1b4a23 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -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;
}
-