From 67c80b8e8d8224adfeb67d5c116f35834d56d62c Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Wed, 1 Jun 2005 16:20:24 -0500 Subject: [svn-r10838] Purpose: Bug fix/new feature Description: Setting "SEMI" or "STRONG" file close degrees causes problems when multiple file IDs exist for the same file on disk. Solution: Make the "SEMI" and "STRONG" settings only apply to the file ID that is being closed. Also, add an "H5F_OBJ_LOCAL" flag for the H5Fget_obj_count() & H5Fget_obj_ids() calls, so that applications can query about objects opened with a particular file ID instead of all the objects opened in the file on disk. Platforms tested: FreeBSD 4.11 (sleipnir) h5committest --- release_docs/RELEASE.txt | 7 ++++ src/H5F.c | 94 +++++++++++++++++------------------------ src/H5Fpublic.h | 13 +++--- src/H5G.c | 5 +++ test/mount.c | 34 +++++++-------- test/tfile.c | 106 +++++++++++++++++++++++++++++++++++++++++++---- 6 files changed, 172 insertions(+), 87 deletions(-) diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index 2b91dd0..a17226c 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -41,6 +41,10 @@ New Features Library: -------- + - Added H5F_OBJ_LOCAL flag to H5Fget_obj_count() & H5Fget_obj_ids(), to + allow querying for objects in file that were opened with a particular + file ID, instead of all objects opened in file with any file ID. + QAK - 2005/06/01 Parallel Library: ----------------- @@ -68,6 +72,9 @@ Bug Fixes since HDF5-1.6.4 release Library ------- + - "SEMI" and "STRONG" file close degree settings now apply only to the + particular file ID being closed, instead of operating on all open + file IDs for a given file. QAK - 2005/06/01 - Fixed error in opening object in group that was opened in mounted file which has been unmounted. QAK - 2005/03/17 diff --git a/src/H5F.c b/src/H5F.c index dd6485e..5ab03db 100644 --- a/src/H5F.c +++ b/src/H5F.c @@ -50,7 +50,13 @@ typedef struct H5F_olist_t { H5I_type_t obj_type; /* Type of object to look for */ hid_t *obj_id_list; /* Pointer to the list of open IDs to return */ unsigned *obj_id_count; /* Number of open IDs */ - H5F_file_t *shared; /* Pointer to file to look inside */ + struct { + hbool_t local; /* Set flag for "local" file searches */ + union { + H5F_file_t *shared; /* Pointer to shared file to look inside */ + const H5F_t *file; /* Pointer to file to look inside */ + } ptr; + } file_info; unsigned list_index; /* Current index in open ID array */ int max_index; /* Maximum # of IDs to put into array */ } H5F_olist_t; @@ -1004,12 +1010,16 @@ H5F_get_objects(const H5F_t *f, unsigned types, int max_index, hid_t *obj_id_lis olist.obj_id_count = &obj_id_count; olist.list_index = 0; olist.max_index = max_index; - /* Shared file structure is used to verify if file IDs refer to the same - * file. */ - if(f != NULL) - olist.shared = f->shared; - else - olist.shared = NULL; + + /* Determine if we are searching for local or global objects */ + if(types&H5F_OBJ_LOCAL) { + olist.file_info.local = TRUE; + olist.file_info.ptr.file = f; + } /* end if */ + else { + olist.file_info.local = FALSE; + olist.file_info.ptr.shared = f ? f->shared : NULL; + } /* end else */ /* Search through file IDs to count the number, and put their * IDs on the object list */ @@ -1083,7 +1093,10 @@ H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key) /* Count file IDs */ if(olist->obj_type == H5I_FILE) { - if( !olist->shared || (olist->shared && ((H5F_t*)obj_ptr)->shared == olist->shared) ) { + if((olist->file_info.local && + (!olist->file_info.ptr.file || (olist->file_info.ptr.file && (H5F_t*)obj_ptr == olist->file_info.ptr.file) )) + || (!olist->file_info.local && + ( !olist->file_info.ptr.shared || (olist->file_info.ptr.shared && ((H5F_t*)obj_ptr)->shared == olist->file_info.ptr.shared) ))) { /* Add the object's ID to the ID list, if appropriate */ if(olist->obj_id_list) { olist->obj_id_list[olist->list_index] = obj_id; @@ -1121,9 +1134,14 @@ H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "unknown data object") } - if( (!olist->shared && olist->obj_type==H5I_DATATYPE && H5T_is_immutable((H5T_t*)obj_ptr)==FALSE) - || (!olist->shared && olist->obj_type!=H5I_DATATYPE) - || (ent && ent->file && ent->file->shared == olist->shared) ) { + if((olist->file_info.local && + ( (!olist->file_info.ptr.file && olist->obj_type==H5I_DATATYPE && H5T_is_immutable((H5T_t*)obj_ptr)==FALSE) + || (!olist->file_info.ptr.file && olist->obj_type!=H5I_DATATYPE) + || (ent && ent->file == olist->file_info.ptr.file) )) + || (!olist->file_info.local && + ((!olist->file_info.ptr.shared && olist->obj_type==H5I_DATATYPE && H5T_is_immutable((H5T_t*)obj_ptr)==FALSE) + || (!olist->file_info.ptr.shared && olist->obj_type!=H5I_DATATYPE) + || (ent && ent->file && ent->file->shared == olist->file_info.ptr.shared) ))) { /* Add the object's ID to the ID list, if appropriate */ if(olist->obj_id_list) { olist->obj_id_list[olist->list_index] = obj_id; @@ -2896,8 +2914,6 @@ done: static herr_t H5F_close(H5F_t *f) { - H5F_close_degree_t fc_degree; /* What action to take when closing the last file ID for a file */ - unsigned closing=0; /* Indicate that the file will be closed */ unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ @@ -2919,12 +2935,9 @@ H5F_close(H5F_t *f) /* Double-check that this file should be closed */ assert(1==f->nrefs); - /* Get the close degree from the file */ - fc_degree = f->shared->fc_degree; - /* if close degree if "semi" and there are objects left open and we are * holding open the file with this file ID, fail now */ - if(fc_degree==H5F_CLOSE_SEMI && f->nopen_objs>0 && f->shared->nrefs==1) + if(f->shared->fc_degree==H5F_CLOSE_SEMI && f->nopen_objs>0) HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, there are objects still open") /* @@ -2950,7 +2963,7 @@ H5F_close(H5F_t *f) * H5F_CLOSE_STRONG: if there are still objects open, close them * first, then close file. */ - switch(fc_degree) { + switch(f->shared->fc_degree) { case H5F_CLOSE_WEAK: /* * If object headers are still open then delay deletion of @@ -2987,39 +3000,11 @@ H5F_close(H5F_t *f) fprintf(H5DEBUG(F), "H5F: H5F_close: operation completing\n"); #endif } /* end if */ - - /* Indicate that the file will be closing */ - closing=1; } /* end else */ break; case H5F_CLOSE_SEMI: - if (f->nopen_objs>0) { -#ifdef H5F_DEBUG - if (H5DEBUG(F)) { - fprintf(H5DEBUG(F), "H5F: H5F_close(%s): %u object header%s still " - "open (file close will complete when %s closed)\n", - f->name, - f->nopen_objs, - 1 == f->nopen_objs?" is":"s are", - 1 == f->nopen_objs?"that header is":"those headers are"); - } -#endif - /* Register an ID for closing the file later */ - if (!f->closing) - f->closing = H5I_register(H5I_FILE_CLOSING, f); - - /* Invalidate file ID */ - f->file_id = -1; - - HGOTO_DONE(SUCCEED) - } else { - if (!f->closing && f->shared->nrefs>1) - HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, there are objects still open") - - /* Indicate that the file will be closing */ - closing=1; - } /* end else */ + /* If we've gotten this far (ie. there are no open objects in the file), fall through to flush & close */ break; case H5F_CLOSE_STRONG: @@ -3030,7 +3015,7 @@ H5F_close(H5F_t *f) int i; /* Local index variable */ /* Get the list of IDs of open dataset objects */ - while((obj_count=H5F_get_obj_ids(f, H5F_OBJ_DATASET, (int)(sizeof(objs)/sizeof(objs[0])), objs))!=0) { + while((obj_count=H5F_get_obj_ids(f, H5F_OBJ_LOCAL|H5F_OBJ_DATASET, (int)(sizeof(objs)/sizeof(objs[0])), objs))!=0) { /* Try to close all the open objects */ for(i=0; ifile_id = -1; - /* Only flush at this point if the file will be closed */ - assert(closing); + /* Flush at this point since the file will be closed */ + /* Dump debugging info */ #if H5AC_DUMP_STATS_ON_CLOSE H5AC_stats(f); diff --git a/src/H5Fpublic.h b/src/H5Fpublic.h index 4718aa3..0b4204d 100644 --- a/src/H5Fpublic.h +++ b/src/H5Fpublic.h @@ -50,12 +50,15 @@ #define H5F_ACC_DEBUG (H5CHECK 0x0008u) /*print debug info */ #define H5F_ACC_CREAT (H5CHECK 0x0010u) /*create non-existing files */ -#define H5F_OBJ_FILE (0x0001u) -#define H5F_OBJ_DATASET (0x0002u) -#define H5F_OBJ_GROUP (0x0004u) -#define H5F_OBJ_DATATYPE (0x0008u) -#define H5F_OBJ_ATTR (0x0010u) +/* Flags for H5Fget_obj_count() & H5Fget_obj_ids() calls */ +#define H5F_OBJ_FILE (0x0001u) /* File objects */ +#define H5F_OBJ_DATASET (0x0002u) /* Dataset objects */ +#define H5F_OBJ_GROUP (0x0004u) /* Group objects */ +#define H5F_OBJ_DATATYPE (0x0008u) /* Named datatype objects */ +#define H5F_OBJ_ATTR (0x0010u) /* Attribute objects */ #define H5F_OBJ_ALL (H5F_OBJ_FILE|H5F_OBJ_DATASET|H5F_OBJ_GROUP|H5F_OBJ_DATATYPE|H5F_OBJ_ATTR) +#define H5F_OBJ_LOCAL (0x0020u) /* Restrict search to objects opened through current file ID */ + /* (as opposed to objects opened through any file ID accessing this file) */ #ifdef H5_HAVE_PARALLEL /* diff --git a/src/H5G.c b/src/H5G.c index 44e23a4..3f88b00 100644 --- a/src/H5G.c +++ b/src/H5G.c @@ -2427,6 +2427,11 @@ H5G_loc (hid_t loc_id) HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, NULL, "invalid file ID"); if (NULL==(ret_value=H5G_entof(H5G_rootof(f)))) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "unable to get symbol table entry for root group"); + + /* Patch up root group's symbol table entry to reflect this file */ + /* (but only for non-mounted files) */ + if(!f->mtab.parent) + ret_value->file = f; break; case H5I_GENPROP_CLS: diff --git a/test/mount.c b/test/mount.c index 8600262..9bdc799 100644 --- a/test/mount.c +++ b/test/mount.c @@ -714,7 +714,7 @@ test_unlink(hid_t fapl) } H5E_END_TRY; if (status>=0) { H5_FAILED(); - puts(" Unmount by name should not have been allowed!"); + printf(" %d: Unmount by name should not have been allowed!\n",__LINE__); goto error; } H5E_BEGIN_TRY { @@ -722,7 +722,7 @@ test_unlink(hid_t fapl) } H5E_END_TRY; if (status>=0) { H5_FAILED(); - puts(" Unmount by name should not have been allowed!"); + printf(" %d: Unmount by name should not have been allowed!\n",__LINE__); goto error; } if (H5Funmount(mnt, ".")<0) goto error; @@ -918,27 +918,27 @@ test_uniformity(hid_t fapl) /* Build the virtual file */ if ((file1=H5Fopen(filename1, H5F_ACC_RDWR, fapl))<0 || (file2=H5Fopen(filename2, H5F_ACC_RDWR, fapl))<0) - goto error; - if (H5Fmount(file1, "/mnt1", file2, H5P_DEFAULT)<0) goto error; + TEST_ERROR; + if (H5Fmount(file1, "/mnt1", file2, H5P_DEFAULT)<0) TEST_ERROR; /* Access some things from the file1 handle */ - if (H5Gget_objinfo(file1, "/", TRUE, NULL)<0) goto error; - if (H5Gget_objinfo(file1, "/mnt1", TRUE, NULL)<0) goto error; - if (H5Gget_objinfo(file1, "mnt1", TRUE, NULL)<0) goto error; - if (H5Gget_objinfo(file1, "/mnt1/file2", TRUE, NULL)<0) goto error; - if (H5Gget_objinfo(file1, "mnt1/file2", TRUE, NULL)<0) goto error; + if (H5Gget_objinfo(file1, "/", TRUE, NULL)<0) TEST_ERROR; + if (H5Gget_objinfo(file1, "/mnt1", TRUE, NULL)<0) TEST_ERROR; + if (H5Gget_objinfo(file1, "mnt1", TRUE, NULL)<0) TEST_ERROR; + if (H5Gget_objinfo(file1, "/mnt1/file2", TRUE, NULL)<0) TEST_ERROR; + if (H5Gget_objinfo(file1, "mnt1/file2", TRUE, NULL)<0) TEST_ERROR; /* Access the same things from the file2 handle */ - if (H5Gget_objinfo(file2, "/", TRUE, NULL)<0) goto error; - if (H5Gget_objinfo(file2, "/mnt1", TRUE, NULL)<0) goto error; - if (H5Gget_objinfo(file2, "mnt1", TRUE, NULL)<0) goto error; - if (H5Gget_objinfo(file2, "/mnt1/file2", TRUE, NULL)<0) goto error; - if (H5Gget_objinfo(file2, "mnt1/file2", TRUE, NULL)<0) goto error; + if (H5Gget_objinfo(file2, "/", TRUE, NULL)<0) TEST_ERROR; + if (H5Gget_objinfo(file2, "/mnt1", TRUE, NULL)<0) TEST_ERROR; + if (H5Gget_objinfo(file2, "mnt1", TRUE, NULL)<0) TEST_ERROR; + if (H5Gget_objinfo(file2, "/mnt1/file2", TRUE, NULL)<0) TEST_ERROR; + if (H5Gget_objinfo(file2, "mnt1/file2", TRUE, NULL)<0) TEST_ERROR; /* Shut down */ - if (H5Funmount(file1, "/mnt1")<0) goto error; - if (H5Fclose(file1)<0) goto error; - if (H5Fclose(file2)<0) goto error; + if (H5Funmount(file1, "/mnt1")<0) TEST_ERROR; + if (H5Fclose(file1)<0) TEST_ERROR; + if (H5Fclose(file2)<0) TEST_ERROR; PASSED(); return 0; diff --git a/test/tfile.c b/test/tfile.c index b78b4ec..dbe974b 100644 --- a/test/tfile.c +++ b/test/tfile.c @@ -65,6 +65,10 @@ #define OBJ_ID_COUNT_6 6 #define OBJ_ID_COUNT_8 8 +#define GROUP1 "Group1" +#define DSET1 "Dataset1" +#define DSET2 "/Group1/Dataset2" + static void create_objects(hid_t, hid_t, hid_t *, hid_t *, hid_t *, hid_t *); static void @@ -180,7 +184,7 @@ test_file_create(void) ret = H5Pset_userblock(tmpl1, F2_USERBLOCK_SIZE); CHECK(ret, FAIL, "H5Pset_userblock"); - ret = H5Pset_sizes(tmpl1, F2_OFFSET_SIZE, F2_LENGTH_SIZE); + ret = H5Pset_sizes(tmpl1, (size_t)F2_OFFSET_SIZE, (size_t)F2_LENGTH_SIZE); CHECK(ret, FAIL, "H5Pset_sizes"); ret = H5Pset_sym_k(tmpl1, F2_SYM_INTERN_K, F2_SYM_LEAF_K); @@ -543,9 +547,10 @@ test_file_close(void) /* Create a dataset and a group in each file open respectively */ create_objects(fid1, fid2, &dataset_id, &group_id1, &group_id2, &group_id3); - /* Close first open */ + /* Close first open, should fail since it is SEMI and objects are + * still open. */ ret = H5Fclose(fid1); - CHECK(ret, FAIL, "H5Fclose"); + VERIFY(ret, FAIL, "H5Fclose"); /* Close second open, should fail since it is SEMI and objects are * still open. */ @@ -555,6 +560,10 @@ test_file_close(void) ret = H5Dclose(dataset_id); CHECK(ret, FAIL, "H5Dclose"); + /* Close first open */ + ret = H5Fclose(fid1); + CHECK(ret, FAIL, "H5Fclose"); + ret = H5Gclose(group_id1); CHECK(ret, FAIL, "H5Gclose"); @@ -782,7 +791,7 @@ create_objects(hid_t fid1, hid_t fid2, hid_t *ret_did, hid_t *ret_gid1, /* Create a group in the second file open */ { hid_t gid1, gid2, gid3; - gid1 = H5Gcreate(fid2, "/group", 0); + gid1 = H5Gcreate(fid2, "/group", (size_t)0); CHECK(gid1, FAIL, "H5Gcreate"); if(ret_gid1 != NULL) *ret_gid1 = gid1; @@ -845,7 +854,7 @@ test_get_file_id(void) /* Create a group in the file. Make a duplicated file ID from the group. * And close this duplicated ID */ - group_id = H5Gcreate(fid, GRP_NAME, 0); + group_id = H5Gcreate(fid, GRP_NAME, (size_t)0); CHECK(group_id, FAIL, "H5Gcreate"); /* Test H5Iget_file_id() */ @@ -1288,7 +1297,7 @@ test_file_ishdf5(void) buf[u]=(unsigned char)u; /* Write some information */ - nbytes = HDwrite(fd, buf, 1024); + nbytes = HDwrite(fd, buf, (size_t)1024); VERIFY(nbytes, 1024, "HDwrite"); /* Close the file */ @@ -1326,7 +1335,7 @@ test_file_open_dot(void) CHECK(fid, FAIL, "H5Fcreate"); /* Create a group in the HDF5 file */ - gid = H5Gcreate(fid, GRP_NAME, 0); + gid = H5Gcreate(fid, GRP_NAME, (size_t)0); CHECK(gid, FAIL, "H5Gcreate"); /* Create a dataspace for creating datasets */ @@ -1387,13 +1396,13 @@ test_file_open_dot(void) /* Create a group with no name using the file ID */ H5E_BEGIN_TRY { - gid2 = H5Gcreate(fid, ".", 0); + gid2 = H5Gcreate(fid, ".", (size_t)0); } H5E_END_TRY; VERIFY(gid2, FAIL, "H5Gcreate"); /* Create a group with no name using the group ID */ H5E_BEGIN_TRY { - gid2 = H5Gcreate(gid, ".", 0); + gid2 = H5Gcreate(gid, ".", (size_t)0); } H5E_END_TRY; VERIFY(gid2, FAIL, "H5Gcreate"); @@ -1426,6 +1435,84 @@ test_file_open_dot(void) /**************************************************************** ** +** test_file_open_overlap(): low-level file test routine. +** This test checks whether opening files in an overlapping way +** (as opposed to a nested manner) works correctly. +** +*****************************************************************/ +static void +test_file_open_overlap(void) +{ + hid_t fid1, fid2; + hid_t did1, did2; + hid_t gid; + hid_t sid; + int nobjs; /* # of open objects */ + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(5, ("Testing opening overlapping file opens\n")); + + /* Create file */ + fid1 = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + assert(fid1 > 0); + + /* Open file also */ + fid2 = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT); + assert(fid2 > 0); + + /* Create a group in file */ + gid = H5Gcreate(fid1, GROUP1, (size_t)0); + assert(gid > 0); + + /* Create dataspace for dataset */ + sid = H5Screate(H5S_SCALAR); + assert(sid > 0); + + /* Create dataset in group w/first file ID */ + did1 = H5Dcreate(gid, DSET1, H5T_NATIVE_INT, sid, H5P_DEFAULT); + assert(did1 > 0); + + /* Check number of objects opened in first file */ + nobjs = H5Fget_obj_count(fid1, H5F_OBJ_LOCAL|H5F_OBJ_ALL); + assert(nobjs == 3); /* 3 == file, dataset & group */ + + /* Close dataset */ + ret = H5Dclose(did1); + assert(ret >= 0); + + /* Close group */ + ret = H5Gclose(gid); + assert(ret >= 0); + + /* Close first file ID */ + ret = H5Fclose(fid1); + assert(ret >= 0); + + + /* Create dataset with second file ID */ + did2 = H5Dcreate(fid2, DSET2, H5T_NATIVE_INT, sid, H5P_DEFAULT); + assert(did2 > 0); + + /* Check number of objects opened in first file */ + nobjs = H5Fget_obj_count(fid2, H5F_OBJ_ALL); + assert(nobjs == 2); /* 2 == file & dataset */ + + /* Close dataspace */ + ret = H5Sclose(sid); + assert(ret >= 0); + + /* Close second dataset */ + ret = H5Dclose(did2); + assert(ret >= 0); + + /* Close second file */ + ret = H5Fclose(fid2); + assert(ret >= 0); +} /* end test_file_open_overlap() */ + +/**************************************************************** +** ** test_file(): Main low-level file I/O test routine. ** ****************************************************************/ @@ -1445,6 +1532,7 @@ test_file(void) test_file_freespace(); /* Test file free space information */ test_file_ishdf5(); /* Test detecting HDF5 files correctly */ test_file_open_dot(); /* Test opening objects with "." for a name */ + test_file_open_overlap(); /* Test opening files in an overlapping manner */ } /* test_file() */ -- cgit v0.12