From e804b4c75b06a0d28793a197d6511de2e781e0e5 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Fri, 11 Apr 2003 11:37:18 -0500 Subject: [svn-r6632] Purpose: Bug fix Description: This fixes a bug in the low-level metadata caching code in the library which could possibly lose metadata during file I/O when a lot of objects are inserted into a group. This also fixes a couple of (similar) fencepost bugs in the B-tree deletion code. Solution: For the metadata bug - call the low-level driver's 'write' routine instead of H5FD_write. For the B-tree bug - include the correct number of keys. Platforms tested: FreeBSD 4.8 (sleipnir) w/C++ Linux 2.4 (burrwhite) w/FORTRAN Solaris 2.7 (arabica) w/FORTRAN IRIX64 6.5 (modi4) w/FORTRAN & parallel (h5committest is still not working for me on burrwhite) Misc. update: --- release_docs/RELEASE.txt | 6 +++ src/H5B.c | 4 +- src/H5FD.c | 3 +- test/h5test.h | 2 +- test/unlink.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 118 insertions(+), 6 deletions(-) diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index d60fa03..aa05b33 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -35,6 +35,12 @@ Bug Fixes since HDF5-1.4.0 Library ------- + * Fixed error in B-tree deletion routine which could cause groups to be + corrupted when objects are removed from them. + QAK - 2003/04/11 + * Fixed error in file space freeing code which could cause metadata to + fail to be written to the file. + QAK - 2003/04/11 * -O caused errors in AIX 5.x platforms. Removed it from --enable-production mode. AKC - 2003/03/31 * Corrected metadata caching bug in parallel I/O which could cause hangs diff --git a/src/H5B.c b/src/H5B.c index d298bc8..d761084 100644 --- a/src/H5B.c +++ b/src/H5B.c @@ -1738,7 +1738,7 @@ H5B_remove_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type HDmemmove(bt->child, bt->child+1, bt->nchildren * sizeof(haddr_t)); - for (i=0; inchildren; i++) { + for (i=0; i<=bt->nchildren; i++) { bt->key[i].dirty = bt->key[i+1].dirty; if (bt->key[i+1].nkey) { bt->key[i].nkey = bt->native + i*type->sizeof_nkey; @@ -1787,7 +1787,7 @@ H5B_remove_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type HDmemmove(bt->child+idx, bt->child+idx+1, (bt->nchildren-idx) * sizeof(haddr_t)); - for (i=idx; inchildren; i++) { + for (i=idx; i<=bt->nchildren; i++) { bt->key[i].dirty = bt->key[i+1].dirty; if (bt->key[i+1].nkey) { bt->key[i].nkey = bt->native + i*type->sizeof_nkey; diff --git a/src/H5FD.c b/src/H5FD.c index 36749bb..08c241c 100644 --- a/src/H5FD.c +++ b/src/H5FD.c @@ -2154,7 +2154,8 @@ H5FD_free(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t si H5_ASSIGN_OVERFLOW(tail_size,(file->accum_loc+file->accum_size)-tail_addr,haddr_t,size_t); /* Write out the part of the accumulator after the block to free */ - if (H5FD_write(file, H5FD_MEM_DEFAULT, dxpl_id, tail_addr, tail_size, file->meta_accum+(tail_addr-file->accum_loc))<0) + /* (Use the driver's write call directly - to avoid looping back and writing to metadata accumulator) */ + if ((file->cls->write)(file, H5FD_MEM_DEFAULT, dxpl_id, tail_addr, tail_size, file->meta_accum+(tail_addr-file->accum_loc))<0) HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "file write request failed"); } /* end if */ diff --git a/test/h5test.h b/test/h5test.h index f3ad742..aa5ded3 100644 --- a/test/h5test.h +++ b/test/h5test.h @@ -50,7 +50,7 @@ extern MPI_Info h5_io_info_g; /* MPI INFO object for IO */ * spaces. If the h5_errors() is used for automatic error handling then * the H5_FAILED() macro is invoked automatically when an API function fails. */ -#define TESTING(WHAT) {printf("%-70s", "Testing " WHAT); fflush(stdout);} +#define TESTING(WHAT) {printf("Testing %-62s",WHAT); fflush(stdout);} #define PASSED() {puts(" PASSED");fflush(stdout);} #define H5_FAILED() {puts("*FAILED*");fflush(stdout);} #define SKIPPED() {puts(" -SKIP-");fflush(stdout);} diff --git a/test/unlink.c b/test/unlink.c index f73c4cf..72b64a13 100644 --- a/test/unlink.c +++ b/test/unlink.c @@ -24,11 +24,16 @@ const char *FILENAME[] = { "unlink", "new_move_a", "new_move_b", + "lunlink", NULL }; #define THE_OBJECT "/foo" +/* Macros for test_create_unlink() */ +#define GROUPNAME "Group" +#define NGROUPS 1000 + /*------------------------------------------------------------------------- * Function: test_one @@ -453,6 +458,83 @@ check_new_move(void) /*------------------------------------------------------------------------- + * Function: test_create_unlink + * + * Purpose: Creates and then unlinks a large number of objects + * + * Return: Success: 0 + * Failure: number of errors + * + * Programmer: Quincey Koziol + * Friday, April 11, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int test_create_unlink(const char *msg, hid_t fapl) +{ + hid_t file, group; + unsigned u; + char groupname[1024]; + char filename[1024]; + + TESTING(msg); + + /* Create file */ + h5_fixname(FILENAME[3], fapl, filename, sizeof filename); + if ((file=H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) + { + H5_FAILED(); + puts(" Creating file failed"); + goto error; + } + + /* Create a many groups to remove */ + for(u=0; u