diff options
-rw-r--r-- | MANIFEST | 1 | ||||
-rw-r--r-- | src/H5Aprivate.h | 3 | ||||
-rw-r--r-- | src/H5Apublic.h | 1 | ||||
-rw-r--r-- | src/H5D.c | 54 | ||||
-rw-r--r-- | src/H5F.c | 74 | ||||
-rw-r--r-- | src/H5Fprivate.h | 4 | ||||
-rw-r--r-- | src/H5G.c | 1143 | ||||
-rw-r--r-- | src/H5Gent.c | 68 | ||||
-rw-r--r-- | src/H5Gnode.c | 181 | ||||
-rw-r--r-- | src/H5Gpkg.h | 91 | ||||
-rw-r--r-- | src/H5Gprivate.h | 43 | ||||
-rw-r--r-- | src/H5Gpublic.h | 9 | ||||
-rw-r--r-- | src/H5Gshad.c | 810 | ||||
-rw-r--r-- | src/H5Gstab.c | 157 | ||||
-rw-r--r-- | src/H5O.c | 179 | ||||
-rw-r--r-- | src/H5Oprivate.h | 18 | ||||
-rw-r--r-- | src/H5P.c | 4 | ||||
-rw-r--r-- | src/H5private.h | 2 | ||||
-rw-r--r-- | src/Makefile.in | 7 | ||||
-rw-r--r-- | test/istore.c | 67 | ||||
-rw-r--r-- | test/testhdf5.c | 4 | ||||
-rw-r--r-- | test/tohdr.c | 47 | ||||
-rw-r--r-- | test/tstab.c | 128 |
23 files changed, 1052 insertions, 2043 deletions
@@ -63,7 +63,6 @@ ./src/H5Gpkg.h ./src/H5Gprivate.h ./src/H5Gpublic.h -./src/H5Gshad.c ./src/H5Gstab.c ./src/H5H.c ./src/H5Hprivate.h diff --git a/src/H5Aprivate.h b/src/H5Aprivate.h index 501c0f9..916ed89 100644 --- a/src/H5Aprivate.h +++ b/src/H5Aprivate.h @@ -63,7 +63,8 @@ #define H5A_DATATYPEID_HASHSIZE 64 #define H5A_DATASPACEID_HASHSIZE 64 #define H5A_DATASETID_HASHSIZE 64 -#define H5A_OID_HASHSIZE 64 +#define H5A_OID_HASHSIZE 64 +#define H5A_GROUPID_HASHSIZE 64 /* Atom information structure used */ typedef struct atom_info_struct_tag { diff --git a/src/H5Apublic.h b/src/H5Apublic.h index 7c0d1c1..60c4d40 100644 --- a/src/H5Apublic.h +++ b/src/H5Apublic.h @@ -38,6 +38,7 @@ typedef enum { #ifndef NDEBUG H5_TEMPLATE_MAX, /* Not really a group ID */ #endif + H5_GROUP, /* Group ID for Group objects */ H5_DATATYPE, /* Group ID for Datatype objects */ H5_DATASPACE, /* Group ID for Dataspace objects */ H5_DATASET, /* Group ID for Dataset objects */ @@ -37,7 +37,7 @@ static char RcsId[] = "@(#)$Revision$"; */ struct H5D_t { H5F_t *file; /*file store for this object */ - H5G_entry_t *ent; /*cached object header stuff */ + H5G_entry_t ent; /*cached object header stuff */ H5T_t *type; /*datatype of this dataset */ H5P_t *space; /*dataspace of this dataset */ H5D_create_t create_parms; /*creation parameters */ @@ -53,7 +53,7 @@ const H5D_create_t H5D_create_dflt = { 1, /* Chunk dimensions */ {1, 1, 1, 1, 1, 1, 1, 1, /* Chunk size. These default values....*/ 1, 1, 1, 1, 1, 1, 1, 1, /*...are quite useless. Larger chunks..*/ - 1, 1, 1, 1, 1, 1, 1, 1, /*...produces fewer, but larger I/O.....*/ + 1, 1, 1, 1, 1, 1, 1, 1, /*...produce fewer, but larger I/O......*/ 1, 1, 1, 1, 1, 1, 1, 1}, /*...requests. */ }; @@ -576,26 +576,22 @@ H5D_create (H5F_t *f, const char *name, const H5T_t *type, const H5P_t *space, /* Initialize the dataset object */ new_dset = H5MM_xcalloc (1, sizeof(H5D_t)); new_dset->file = f; + H5F_addr_undef (&(new_dset->ent.header)); new_dset->type = H5T_copy (type); new_dset->space = H5P_copy (space); new_dset->create_parms = *create_parms; /* - * Open (and create) a new file object and update the object header - * immediately with the new information so when others access the dataset - * they see the most current info. This `write through the dataset' - * policy is used throughout this package, and because the object header - * is cached it shouldn't cause any disk activity. + * Create (open for write access) an object header. */ - if (NULL==(new_dset->ent = H5G_create (f, name, H5D_MINHDR_SIZE))) { + if (H5O_create (f, 0, &(new_dset->ent))<0) { HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, NULL, - "problem with the dataset name"); + "unable to create dataset object header"); } /* Update the type and space header messages */ - if (H5O_modify (f, NO_ADDR, new_dset->ent, H5O_DTYPE, 0, - new_dset->type)<0 || - H5P_modify (f, new_dset->ent, new_dset->space)<0) { + if (H5O_modify (f, &(new_dset->ent), H5O_DTYPE, 0, new_dset->type)<0 || + H5P_modify (f, &(new_dset->ent), new_dset->space)<0) { HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, NULL, "can't update type or space header messages"); } @@ -612,7 +608,7 @@ H5D_create (H5F_t *f, const char *name, const H5T_t *type, const H5P_t *space, HGOTO_ERROR (H5E_DATASET, H5E_NOSPACE, NULL, "can't allocate raw file storage"); } - if (H5O_modify (f, NO_ADDR, new_dset->ent, H5O_CSTORE, 0, + if (H5O_modify (f, &(new_dset->ent), H5O_CSTORE, 0, &(new_dset->storage.cstore))<0) { HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, NULL, "can't update dataset object header"); @@ -639,7 +635,7 @@ H5D_create (H5F_t *f, const char *name, const H5T_t *type, const H5P_t *space, HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, NULL, "can't initialize chunked storage"); } - if (H5O_modify (f, NO_ADDR, new_dset->ent, H5O_ISTORE, 0, + if (H5O_modify (f, &(new_dset->ent), H5O_ISTORE, 0, &(new_dset->storage.istore))<0) { HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, NULL, "can't update dataset object header"); @@ -651,6 +647,11 @@ H5D_create (H5F_t *f, const char *name, const H5T_t *type, const H5P_t *space, HGOTO_ERROR (H5E_DATASET, H5E_UNSUPPORTED, NULL, "not implemented yet"); } + /* Give the dataset a name */ + if (H5G_insert (f, name, &(new_dset->ent))<0) { + HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, NULL, "unable to name dataset"); + } + /* Success */ ret_value = new_dset; @@ -659,7 +660,9 @@ H5D_create (H5F_t *f, const char *name, const H5T_t *type, const H5P_t *space, if (!ret_value && new_dset) { if (new_dset->type) H5T_close (new_dset->type); if (new_dset->space) H5P_close (new_dset->space); - if (new_dset->ent) H5G_close (f, new_dset->ent); + if (H5F_addr_defined (&(new_dset->ent.header))) { + H5O_close (f, &(new_dset->ent)); + } new_dset->file = NULL; H5MM_xfree (new_dset); } @@ -704,16 +707,20 @@ H5D_open (H5F_t *f, const char *name) dataset = H5MM_xcalloc (1, sizeof(H5D_t)); dataset->file = f; dataset->create_parms = H5D_create_dflt; + H5F_addr_undef (&(dataset->ent.header)); /* Open the dataset object */ - if (NULL==(dataset->ent=H5G_open (f, name))) { + if (H5G_find (f, name, NULL, &(dataset->ent))<0) { HGOTO_ERROR (H5E_DATASET, H5E_NOTFOUND, NULL, "not found"); } + if (H5O_open (f, &(dataset->ent))<0) { + HGOTO_ERROR (H5E_DATASET, H5E_CANTOPENOBJ, NULL, "unable to open"); + } /* Get the type and space */ - if (NULL==(dataset->type = H5O_read (f, NO_ADDR, dataset->ent, H5O_DTYPE, + if (NULL==(dataset->type = H5O_read (f, &(dataset->ent), H5O_DTYPE, 0, NULL)) || - NULL==(dataset->space = H5P_read (f, dataset->ent))) { + NULL==(dataset->space = H5P_read (f, &(dataset->ent)))) { HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, NULL, "can't load type of space info from dataset header"); } @@ -724,12 +731,12 @@ H5D_open (H5F_t *f, const char *name) * values are copied to the dataset create template so the user can query * them. */ - if (H5O_read (dataset->file, NO_ADDR, dataset->ent, H5O_CSTORE, 0, + if (H5O_read (dataset->file, &(dataset->ent), H5O_CSTORE, 0, &(dataset->storage.cstore))) { /* Contiguous storage */ dataset->create_parms.layout = H5D_CONTIGUOUS; - } else if (H5O_read (dataset->file, NO_ADDR, dataset->ent, H5O_ISTORE, 0, + } else if (H5O_read (dataset->file, &(dataset->ent), H5O_ISTORE, 0, &(dataset->storage.istore))) { /* * Chunked storage. The creation template's dimension is one less than @@ -755,7 +762,9 @@ H5D_open (H5F_t *f, const char *name) done: if (!ret_value && dataset) { - if (dataset->ent) H5G_close (f, dataset->ent); + if (H5F_addr_defined (&(dataset->ent.header))) { + H5O_close (f, &(dataset->ent)); + } if (dataset->type) H5T_close (dataset->type); if (dataset->space) H5P_close (dataset->space); dataset->file = NULL; @@ -799,8 +808,7 @@ H5D_close (H5D_t *dataset) assert (dataset && dataset->file); /* Close the dataset object */ - H5G_close (dataset->file, dataset->ent); - dataset->ent = NULL; + H5O_close (dataset->file, &(dataset->ent)); /* * Release dataset type and space - there isn't much we can do if one of @@ -417,14 +417,6 @@ H5F_new (H5F_file_t *shared) /* Create a main cache */ H5AC_create (f, H5AC_NSLOTS); - - /* Create the shadow hash table */ - f->shared->nshadows = H5G_NSHADOWS; - f->shared->shadow = H5MM_xcalloc (f->shared->nshadows, - sizeof(struct H5G_hash_t*)); - - /* Create a root symbol slot */ - f->shared->root_sym = H5G_ent_calloc (); } f->shared->nrefs++; @@ -463,9 +455,7 @@ H5F_dest (H5F_t *f) if (f) { if (0 == --(f->shared->nrefs)) { H5AC_dest (f); - f->shared->root_sym = H5MM_xfree (f->shared->root_sym); - f->shared->nshadows = 0; - f->shared->shadow = H5MM_xfree (f->shared->shadow); + f->shared->root_ent = H5MM_xfree (f->shared->root_ent); f->shared = H5MM_xfree (f->shared); } f->name = H5MM_xfree (f->name); @@ -586,6 +576,7 @@ H5F_open (const H5F_low_class_t *type, const char *name, uintn flags, size_t variable_size; /*variable part of boot block */ H5F_create_t *cp=NULL; /*file creation parameters */ haddr_t addr1, addr2; /*temporary address */ + H5G_entry_t root_ent; /*root symbol table entry */ const char *s = name; FUNC_ENTER (H5F_open, NULL); @@ -887,10 +878,15 @@ H5F_open (const H5F_low_class_t *type, const char *name, uintn flags, H5F_addr_decode (f, &p, &(f->shared->smallobj_addr)); H5F_addr_decode (f, &p, &(f->shared->freespace_addr)); H5F_addr_decode (f, &p, &(f->shared->hdf5_eof)); - if (H5G_ent_decode (f, &p, f->shared->root_sym)<0) { + if (H5G_ent_decode (f, &p, &root_ent)<0) { HGOTO_ERROR (H5E_FILE, H5E_CANTOPENFILE, NULL, "can't read root symbol entry"); } + if (H5F_addr_defined (&(root_ent.header))) { + f->shared->root_ent = H5MM_xmalloc (sizeof(H5G_entry_t)); + *(f->shared->root_ent) = root_ent; + } + /* * The userdefined data is the area of the file before the base @@ -1150,8 +1146,6 @@ hid_t H5Fopen(const char *filename, uintn flags, hid_t access_temp) * Return: Success: SUCCEED * * Failure: FAIL - * -2 if the there are open objects and - * INVALIDATE was non-zero. * * Programmer: Robb Matzke * matzke@llnl.gov @@ -1165,7 +1159,6 @@ static herr_t H5F_flush (H5F_t *f, hbool_t invalidate) { uint8 buf[2048], *p=buf; - herr_t shadow_flush; FUNC_ENTER (H5F_flush, FAIL); @@ -1177,12 +1170,6 @@ H5F_flush (H5F_t *f, hbool_t invalidate) */ if (0==(H5F_ACC_WRITE & f->shared->flags)) HRETURN (SUCCEED); - /* - * Flush all open object info. If this fails just remember it and return - * failure at the end. At least that way we get a consistent file. - */ - shadow_flush = H5G_shadow_flush (f, invalidate); - /* flush (and invalidate) the entire cache */ if (H5AC_flush (f, NULL, 0, invalidate)<0) { HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL, "can't flush cache"); @@ -1207,7 +1194,7 @@ H5F_flush (H5F_t *f, hbool_t invalidate) H5F_addr_encode (f, &p, &(f->shared->smallobj_addr)); H5F_addr_encode (f, &p, &(f->shared->freespace_addr)); H5F_addr_encode (f, &p, &(f->shared->hdf5_eof)); - H5G_ent_encode (f, &p, f->shared->root_sym); + H5G_ent_encode (f, &p, f->shared->root_ent); /* update file length if necessary */ if (!H5F_addr_defined (&(f->shared->hdf5_eof))) { @@ -1226,11 +1213,6 @@ H5F_flush (H5F_t *f, hbool_t invalidate) HRETURN_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "low level flush failed"); } - /* Did shadow flush fail above? */ - if (shadow_flush<0) { - HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, -2, "object are still open"); - } - FUNC_LEAVE (SUCCEED); } @@ -1242,8 +1224,7 @@ H5F_flush (H5F_t *f, hbool_t invalidate) * * Return: Success: SUCCEED * - * Failure: FAIL, or -2 if the failure is due to objects - * still being open. + * Failure: FAIL * * Programmer: Robb Matzke * Tuesday, September 23, 1997 @@ -1255,27 +1236,24 @@ H5F_flush (H5F_t *f, hbool_t invalidate) herr_t H5F_close (H5F_t *f) { - herr_t ret_value = FAIL; - FUNC_ENTER (H5F_close, FAIL); - if (-2==(ret_value=H5F_flush (f, TRUE))) { - /*objects are still open, but don't fail yet*/ - } else if (ret_value<0) { - HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL, - "can't flush cache"); + /* Close all current working groups */ + while (H5G_pop (f)>=0) /*void*/; + + /* Flush the boot block and caches */ + if (H5F_flush (f, TRUE)<0) { + HRETURN_ERROR (H5E_CACHE, H5E_CANTFLUSH, FAIL, "can't flush cache"); } + + /* Dump debugging info */ if (f->intent & H5F_ACC_DEBUG) H5AC_debug (f); + /* Close files and release resources */ H5F_low_close (f->shared->lf); - H5F_dest (f); - - /* Did the H5F_flush() fail because of open objects? */ - if (ret_value<0) { - HRETURN_ERROR (H5E_SYM, H5E_CANTFLUSH, ret_value, "objects are open"); - } + f = H5F_dest (f); - FUNC_LEAVE (ret_value); + FUNC_LEAVE (SUCCEED); } /*-------------------------------------------------------------------------- @@ -1537,8 +1515,14 @@ H5F_debug (H5F_t *f, const haddr_t *addr, FILE *stream, intn indent, "Shared header version number:", (unsigned)(f->shared->create_parms.sharedheader_ver)); - fprintf (stream, "%*sRoot symbol table entry:\n", indent, ""); - H5G_ent_debug (f, f->shared->root_sym, stream, indent+3, MAX(0, fwidth-3)); + fprintf (stream, "%*s%-*s %s\n", indent, "", fwidth, + "Root symbol table entry:", + f->shared->root_ent ? "" : "(none)"); + if (f->shared->root_ent) { + H5G_ent_debug (f, f->shared->root_ent, stream, + indent+3, MAX(0, fwidth-3)); + } + FUNC_LEAVE (SUCCEED); } diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index 250c152..4e1abb1 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -331,9 +331,7 @@ typedef struct H5F_file_t { #ifdef LATER file_access_temp_t file_access_parms; /* File-access template */ #endif - struct H5G_entry_t *root_sym; /* Root symbol table entry */ - uintn nshadows; /* Size of shadow hash table */ - struct H5G_hash_t **shadow; /* The shadow hash table */ + struct H5G_entry_t *root_ent; /* Root symbol table entry */ } H5F_file_t; /* @@ -28,15 +28,13 @@ * Robb Matzke, 30 Aug 1997 * Added `Errors:' field to function prologues. * - * Robb Matzke, 18 Sep 1997 - * Added shadow entry support. - * *------------------------------------------------------------------------- */ #define H5G_PACKAGE /*suppress error message about including H5Gpkg.h*/ /* Packages needed by this file... */ #include <H5private.h> +#include <H5Aprivate.h> #include <H5Bprivate.h> #include <H5Eprivate.h> #include <H5Gpkg.h> @@ -45,37 +43,38 @@ #include <H5Oprivate.h> #define H5G_INIT_HEAP 8192 +#define H5G_RESERVED_ATOMS 0 #define PABLO_MASK H5G_mask /* Interface initialization */ static hbool_t interface_initialize_g = FALSE; -#define INTERFACE_INIT NULL +#define INTERFACE_INIT H5G_init_interface +static herr_t H5G_init_interface (void); +static void H5G_term_interface (void); + +static H5G_entry_t *H5G_getcwg (H5F_t *f); /*------------------------------------------------------------------------- - * Function: H5Gnew + * Function: H5Gcreate * * Purpose: Creates a new group in FILE and gives it the specified * NAME. Unless NAME begins with `/' it is relative to the - * current working group. + * current working group. The group is opened for write access + * and it's object ID is returned. * * The optional SIZE_HINT specifies how much file space to * reserve to store the names that will appear in this - * group (an even number of characters, counting the null - * terminator, is allocated for each name). If a non-positive - * value is supplied for the SIZE_HINT then a default size is - * chosen. + * group. If a non-positive value is supplied for the SIZE_HINT + * then a default size is chosen. * * See also: H5Gset(), H5Gpush(), H5Gpop() * * Errors: - * ARGS BADTYPE Not a file atom. - * ARGS BADVALUE No name given. - * ATOM BADATOM Can't unatomize file. - * SYM CANTINIT Can't close handle. - * SYM CANTINIT Can't create group. * - * Return: Success: SUCCEED + * Return: Success: The object ID of a new, empty group open for + * writing. Call H5Gclose() when finished with + * the group. * * Failure: FAIL * @@ -86,47 +85,139 @@ static hbool_t interface_initialize_g = FALSE; * *------------------------------------------------------------------------- */ -herr_t -H5Gnew (hid_t file, const char *name, size_t size_hint) +hid_t +H5Gcreate (hid_t file_id, const char *name, size_t size_hint) { - H5F_t *f=NULL; - H5G_entry_t *grp_handle=NULL; + H5F_t *f = NULL; + H5G_t *grp; + hid_t ret_value = FAIL; - FUNC_ENTER (H5Gnew, FAIL); + FUNC_ENTER (H5Gcreate, FAIL); + H5ECLEAR; - /* Check/fix arguments */ + /* Check arguments */ + if (H5_FILE!=H5Aatom_group (file_id) || + NULL==(f=H5Aatom_object (file_id))) { + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a file"); + } if (!name || !*name) { HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "no name given"); } - if (H5_FILE!=H5Aatom_group (file)) { - HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a file atom"); + + /* Create the group */ + if (NULL==(grp=H5G_create (f, name, size_hint))) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, "unable to create group"); } - if (NULL==(f=H5Aatom_object (file))) { - HRETURN_ERROR (H5E_ATOM, H5E_BADATOM, FAIL, "can't unatomize file"); + + if ((ret_value = H5Aregister_atom (H5_GROUP, grp))<0) { + H5G_close (grp); + HRETURN_ERROR (H5E_ATOM, H5E_CANTREGISTER, FAIL, + "unable to register group"); } + + FUNC_LEAVE (ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Gopen + * + * Purpose: Opens an existing group for modification. When finished, + * call H5Gclose() to close it and release resources. + * + * Errors: + * + * Return: Success: Object ID of the group. + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Wednesday, December 31, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +hid_t +H5Gopen (hid_t file_id, const char *name) +{ + hid_t ret_value = FAIL; + H5F_t *f = NULL; + H5G_t *grp = NULL; - /* Create the group */ - if (NULL==(grp_handle=H5G_new (f, name, size_hint))) { - HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, - "can't create group"); + FUNC_ENTER (H5Gopen, FAIL); + H5ECLEAR; + + /* Check args */ + if (H5_FILE!=H5Aatom_group (file_id) || + NULL==(f=H5Aatom_object (file_id))) { + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a file"); + } + if (!name || !*name) { + HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "no name"); } - /* Close the group handle */ - if (H5G_close (f, grp_handle)<0) { - HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, "can't close handle"); + /* Open the group */ + if (NULL==(grp=H5G_open (f, name))) { + HRETURN_ERROR (H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group"); } - FUNC_LEAVE (SUCCEED); + /* Register an atom for the group */ + if ((ret_value=H5Aregister_atom (H5_GROUP, grp))<0) { + H5G_close (grp); + HRETURN_ERROR (H5E_ATOM, H5E_CANTREGISTER, FAIL, + "unable to register group"); + } + + FUNC_LEAVE (ret_value); } + +/*------------------------------------------------------------------------- + * Function: H5Gclose + * + * Purpose: Closes the specified group. The group ID will no longer be + * valid for accessing the group. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Wednesday, December 31, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Gclose (hid_t grp_id) +{ + H5G_t *grp = NULL; + + FUNC_ENTER (H5Gclose, FAIL); + H5ECLEAR; + + /* Check args */ + if (H5_GROUP!=H5Aatom_group (grp_id) || + NULL==(grp=H5Aatom_object (grp_id))) { + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a group"); + } + + /* close it */ + if (H5G_close (grp)<0) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, "unable to close group"); + } + + FUNC_LEAVE (SUCCEED); +} /*------------------------------------------------------------------------- * Function: H5Gset * * Purpose: Sets the working group for file handle FILE to the - * specified NAME. Unless NAME begins with a `/' it is - * interpretted relative to the current working group. + * specified group. * * Each file handle maintains its own notion of the current * working group. That is, if a single file is opened with @@ -137,10 +228,6 @@ H5Gnew (hid_t file, const char *name, size_t size_hint) * See also: H5Gpush(), H5Gpop() * * Errors: - * ARGS BADTYPE Not a file atom. - * ARGS BADVALUE No name given. - * ATOM BADATOM Can't unatomize file. - * SYM CANTINIT Can't change current working group. * * Return: Success: SUCCEED * @@ -154,32 +241,33 @@ H5Gnew (hid_t file, const char *name, size_t size_hint) *------------------------------------------------------------------------- */ herr_t -H5Gset (hid_t file, const char *name) +H5Gset (hid_t file_id, hid_t grp_id) { H5F_t *f=NULL; + H5G_t *grp; FUNC_ENTER (H5Gset, FAIL); + H5ECLEAR; /* Check/fix arguments */ - if (!name || !*name) { - HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "no name given"); - } - if (H5_FILE!=H5Aatom_group (file)) { - HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a file atom"); + if (H5_FILE!=H5Aatom_group (file_id) || + NULL==(f=H5Aatom_object (file_id))) { + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a file"); } - if (NULL==(f=H5Aatom_object (file))) { - HRETURN_ERROR (H5E_ATOM, H5E_BADATOM, FAIL, "can't unatomize file"); + if (H5_GROUP!=H5Aatom_group (grp_id) || + NULL==(grp=H5Aatom_object (grp_id))) { + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a group"); } - if (H5G_set (f, name)<0) { + /* Set the current working group */ + if (H5G_set (f, grp)<0) { HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, - "can't change current working group"); + "unable to change current working group"); } FUNC_LEAVE (SUCCEED); } - /*------------------------------------------------------------------------- * Function: H5Gpush @@ -196,10 +284,6 @@ H5Gset (hid_t file, const char *name) * See also: H5Gset(), H5Gpop() * * Errors: - * ARGS BADTYPE Not a file atom. - * ARGS BADVALUE No name given. - * ATOM BADATOM Can't unatomize file. - * SYM CANTINIT Can't change current working group. * * Return: Success: SUCCEED * @@ -213,24 +297,26 @@ H5Gset (hid_t file, const char *name) *------------------------------------------------------------------------- */ herr_t -H5Gpush (hid_t file, const char *name) +H5Gpush (hid_t file_id, hid_t grp_id) { H5F_t *f=NULL; + H5G_t *grp; FUNC_ENTER (H5Gpush, FAIL); + H5ECLEAR; - /* Check/fix arguments */ - if (!name || !*name) { - HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "no name given"); + /* Check arguments */ + if (H5_FILE!=H5Aatom_group (file_id) || + NULL==(f=H5Aatom_object (file_id))) { + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a file"); } - if (H5_FILE!=H5Aatom_group (file)) { - HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a file atom"); + if (H5_GROUP!=H5Aatom_group (grp_id) || + NULL==(grp=H5Aatom_object (grp_id))) { + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a group"); } - if (NULL==(f=H5Aatom_object (file))) { - HRETURN_ERROR (H5E_ATOM, H5E_BADATOM, FAIL, "can't unatomize file"); - } - - if (H5G_push (f, name)<0) { + + /* Push group onto stack */ + if (H5G_push (f, grp)<0) { HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, "can't change current working group"); } @@ -238,7 +324,6 @@ H5Gpush (hid_t file, const char *name) FUNC_LEAVE (SUCCEED); } - /*------------------------------------------------------------------------- * Function: H5Gpop @@ -255,9 +340,6 @@ H5Gpush (hid_t file, const char *name) * See also: H5Gset(), H5Gpush() * * Errors: - * ARGS BADTYPE Not a file atom. - * ATOM BADATOM Can't unatomize file. - * SYM CANTINIT Stack is empty. * * Return: Success: SUCCEED * @@ -273,20 +355,20 @@ H5Gpush (hid_t file, const char *name) *------------------------------------------------------------------------- */ herr_t -H5Gpop (hid_t file) +H5Gpop (hid_t file_id) { H5F_t *f=NULL; FUNC_ENTER (H5Gpop, FAIL); - - /* Check/fix arguments */ - if (H5_FILE!=H5Aatom_group (file)) { - HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a file atom"); - } - if (NULL==(f=H5Aatom_object (file))) { - HRETURN_ERROR (H5E_ATOM, H5E_BADATOM, FAIL, "can't unatomize file"); + H5ECLEAR; + + /* Check arguments */ + if (H5_FILE!=H5Aatom_group (file_id) || + NULL==(f=H5Aatom_object (file_id))) { + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a file"); } + /* pop */ if (H5G_pop (f)<0) { HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, "stack is empty"); @@ -307,9 +389,59 @@ H5Gpop (hid_t file) */ + +/*------------------------------------------------------------------------- + * Function: H5G_init_interface + * + * Purpose: Initializes the H5G interface. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Monday, January 5, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_init_interface (void) +{ + FUNC_ENTER (H5G_init_interface, FAIL); + /* Initialize the atom group for the group IDs */ + if (H5Ainit_group (H5_GROUP, H5A_GROUPID_HASHSIZE, H5G_RESERVED_ATOMS, + (herr_t (*)(void*))H5G_close)<0 || + H5_add_exit (H5G_term_interface)<0) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, + "unable to initialize interface"); + } + + FUNC_LEAVE (SUCCEED); +} - + +/*------------------------------------------------------------------------- + * Function: H5G_term_interface + * + * Purpose: Terminates the H5G interface + * + * Return: void + * + * Programmer: Robb Matzke + * Monday, January 5, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +H5G_term_interface (void) +{ + H5Adestroy_group (H5_GROUP); +} /*------------------------------------------------------------------------- @@ -348,57 +480,58 @@ H5G_component (const char *name, size_t *size_p) /*------------------------------------------------------------------------- * Function: H5G_namei * - * Purpose: (Partially) translates a name to a symbol table entry. - * - * Given a name (absolute or relative) return the symbol table - * entry for that name and for the group that contains the - * base name. These entries (GRP_ENT and BASE_ENT) are returned - * through memory passed into the function by the caller. Either - * or both pointers may be null. Absolute names are looked up - * relative to the root group of file F while relative - * names are traversed beginning at the CWG argument. - * - * Consecutive slash characters are treated like single - * slash characters. Trailing slashes are ignored. The - * component `.' is recognized as the current group - * during the traversal (initially CWG), but the component - * `..' is not internally recognized (it is recognized if - * such a name appears in the symbol table). - * - * If the name cannot be fully resolved, then REST will - * point to the part of NAME where the traversal failed - * (REST will always point to a relative name) and this - * function will return null. GRP_ENT will be initialized with - * information about the group (or other object) at which - * the traversal failed. However, if the name can be fully - * resolved, then REST points to the null terminator of NAME. - * - * As a special case, if the NAME is the name `/' (or - * equivalent) then GRP_ENT is initialized to all zero - * and an invalid header address and a pointer to the root - * symbol table entry is returned. - * - * As a special case, if the NAME is the string `/foo' (or - * equivalent) and the root symbol table entry points to a - * non-group object with a name message with the value - * `foo' then GRP_ENT is initialized to all zero (except for an - * invalid header address) and a pointer to the root symbol - * table entry is returned. - * + * Purpose: Translates a name to a symbol table entry. + * + * If the specified name can be fully resolved, then this + * function returns the symbol table entry for the named object + * through the OBJ_ENT argument. The symbol table entry for the + * group containing the named object is returned through the + * GRP_ENT argument if it is non-null. However, if the name + * refers to the root object then the GRP_ENT will be + * initialized with an undefined object header address. The + * REST argument, if present, will point to the null terminator + * of NAME. + * + * If the specified name cannot be fully resolved, then OBJ_ENT + * is initialized with the undefined object header address. The + * REST argument will point into the NAME argument to the start + * of the component that could not be located. The GRP_ENT will + * contain the entry for the symbol table that was being + * searched at the time of the failure and will have an + * undefined object header address if the search failed at the + * root object. For instance, if NAME is `/foo/bar/baz' and the + * root directory exists and contains an entry for `foo', and + * foo is a group that contains an entry for baz, but baz is not + * a group, then the results will be that REST points to `baz', + * GRP_ENT has an undefined object header address, and GRP_ENT + * is the symbol table entry for `bar' in `/foo'. + * + * If a file contains more than one object, then `/' is the name + * of the root object which is a group. Otherwise, a file can + * consist of a single object, not necessarily a group, whose + * name is `/foo' where `foo' is the value of the name messsage + * in the object header. A file can also contain no objects in + * which case the function returns so REST points to the + * beginning of NAME and OBJ_ENT and GRP_ENT contain undefined + * header addresses. + * + * Components of a name are separated from one another by one or + * more slashes (/). Slashes at the end of a name are ignored. + * If the name begins with a slash then the search begins at the + * root object, otherwise it begins at the group CWG, otherwise + * it begins at the current working group of file F. The + * component `.' is a no-op, but `..' is not understood by this + * function (unless it appears as an entry in the symbol table). + * * Errors: - * SYM COMPLEN Component is too long. - * SYM NOTFOUND Component not found. - * SYM NOTFOUND No root group. - * SYM NOTFOUND Root not found. * - * Return: Success: Pointer to a cached symbol table entry if the - * name can be fully resolved. The pointer is - * valid until one of the H5AC (cache) functions - * is called. + * Return: Success: SUCCEED if name can be fully resolved. See + * above for values of REST, GRP_ENT, and + * OBJ_ENT. * - * Failure: Null if the name could not be fully resolved. - * REST and GRP_ENT are initialized (possibly to - * zero if the failure occurred soon enough). + * Failure: FAIL if the name could not be fully resolved. + * See above for values of REST, GRP_ENT, and + * OBJ_ENT. * * Programmer: Robb Matzke * matzke@llnl.gov @@ -408,46 +541,52 @@ H5G_component (const char *name, size_t *size_p) * *------------------------------------------------------------------------- */ -static H5G_entry_t * +static herr_t H5G_namei (H5F_t *f, H5G_entry_t *cwg, const char *name, - const char **rest/*out*/, H5G_entry_t *grp_ent/*out*/) + const char **rest/*out*/, H5G_entry_t *grp_ent/*out*/, + H5G_entry_t *obj_ent/*out*/) { - H5G_entry_t grp; /*entry for current group */ + H5G_entry_t _grp_ent; /*entry for current group */ + H5G_entry_t _obj_ent; /*entry found */ size_t nchars; /*component name length */ char comp[1024]; /*component name buffer */ hbool_t aside = FALSE; /*did we look at a name message?*/ - H5G_entry_t *ret_value=NULL; /*return value */ /* clear output args before FUNC_ENTER() in case it fails */ if (rest) *rest = name; - if (grp_ent) { - memset (grp_ent, 0, sizeof(H5G_entry_t)); - H5F_addr_undef (&(grp_ent->header)); - } + if (!grp_ent) grp_ent = &_grp_ent; + if (!obj_ent) obj_ent = &_obj_ent; + memset (grp_ent, 0, sizeof(H5G_entry_t)); + H5F_addr_undef (&(grp_ent->header)); + memset (obj_ent, 0, sizeof(H5G_entry_t)); + H5F_addr_undef (&(obj_ent->header)); - FUNC_ENTER (H5G_namei, NULL); + FUNC_ENTER (H5G_namei, FAIL); /* check args */ assert (f); - assert (f->shared->root_sym); assert (name && *name); - assert (cwg || '/'==*name); + /* If the file contains no objects then return failure */ + if (!f->shared->root_ent) { + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "no root group"); + } + /* starting point */ if ('/'==*name) { - if (!H5F_addr_defined (&(f->shared->root_sym->header))) { - HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL, - "no root group"); - } - ret_value = f->shared->root_sym; - grp = *(f->shared->root_sym); + *obj_ent = *(f->shared->root_ent); + } else if (cwg) { + *obj_ent = *cwg; + } else if ((cwg=H5G_getcwg (f))) { + *obj_ent = *cwg; } else { - ret_value = cwg; - grp = *cwg; + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "no current working group"); } + assert (H5F_addr_defined (&(obj_ent->header))); /* traverse the name */ while ((name=H5G_component (name, &nchars)) && *name) { + if (rest) *rest = name; /* * The special name `.' is a no-op. @@ -457,67 +596,51 @@ H5G_namei (H5F_t *f, H5G_entry_t *cwg, const char *name, /* * Advance to the next component of the name. */ - grp = *ret_value; - ret_value = NULL; - if (rest) *rest = name; + *grp_ent = *obj_ent; + HDmemset (obj_ent, 0, sizeof(H5G_entry_t)); + H5F_addr_undef (&(obj_ent->header)); /* * Copy the component name into a null-terminated buffer so * we can pass it down to the other symbol table functions. */ if (nchars+1 > sizeof(comp)) { - if (grp_ent) *grp_ent = grp; - HRETURN_ERROR (H5E_SYM, H5E_COMPLEN, NULL, "component is too long"); + HRETURN_ERROR (H5E_SYM, H5E_COMPLEN, FAIL, "component is too long"); } HDmemcpy (comp, name, nchars); comp[nchars] = '\0'; - if (NULL==(ret_value=H5G_stab_find (f, NO_ADDR, &grp, comp))) { + if (H5G_stab_find (f, grp_ent, comp, obj_ent/*out*/)<0) { /* * Component was not found in the current symbol table, possibly - * because GRP isn't a symbol table. If it is the root symbol then - * see if it has the appropriate name field. The ASIDE variable - * prevents us from saying `/foo/foo' where the root object has - * the name `foo'. + * because GRP_ENT isn't a symbol table. If it is the root symbol + * then see if it has the appropriate name field. The ASIDE + * variable prevents us from saying `/foo/foo' where the root object + * has the name `foo'. */ H5O_name_t mesg={0}; if (!aside && - H5F_addr_defined (&(grp.header)) && - H5F_addr_defined (&(f->shared->root_sym->header)) && - H5F_addr_eq (&(grp.header), &(f->shared->root_sym->header)) && - H5O_read (f, &(grp.header), &grp, H5O_NAME, 0, &mesg) && + H5F_addr_eq (&(grp_ent->header), + &(f->shared->root_ent->header)) && + H5O_read (f, grp_ent, H5O_NAME, 0, &mesg) && !HDstrcmp (mesg.s, comp)) { H5O_reset (H5O_NAME, &mesg); - ret_value = f->shared->root_sym; + *obj_ent = *grp_ent; + HDmemset (grp_ent, 0, sizeof(H5G_entry_t)); + H5F_addr_undef (&(grp_ent->header)); aside = TRUE; } else { H5O_reset (H5O_NAME, &mesg); - if (grp_ent) *grp_ent = grp; - HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL, "component not found"); + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "component not found"); } } /* next component */ name += nchars; } - - /* output parameters */ if (rest) *rest = name; /*final null*/ - if (grp_ent) { - if (H5F_addr_eq (&(ret_value->header), &(f->shared->root_sym->header))) { - HDmemset (grp_ent, 0, sizeof(H5G_entry_t)); /*root has no parent*/ - H5F_addr_undef (&(grp_ent->header)); - } else { - *grp_ent = grp; - } - } - /* Perhaps the root object doesn't even exist! */ - if (!H5F_addr_defined (&(ret_value->header))) { - HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL, "root not found"); - } - - FUNC_LEAVE (ret_value); + FUNC_LEAVE (SUCCEED); } @@ -532,16 +655,8 @@ H5G_namei (H5F_t *f, H5G_entry_t *cwg, const char *name, * is removed). If the root object doesn't have a name message * then the name `Root Object' is used. * - * Warning: This function has a few subtleties. Be warned! - * * Errors: - * SYM CANTINIT Can't open root object. - * SYM CANTINIT Can't reinsert old root object. - * SYM CANTINIT Cant create root. - * SYM EXISTS Root group already exists. - * SYM LINK Bad link count on old root object. - * SYM LINK Cant create root. - * + * * Return: Success: SUCCEED * * Failure: FAIL. This function returns -2 if the @@ -559,71 +674,50 @@ H5G_namei (H5F_t *f, H5G_entry_t *cwg, const char *name, static herr_t H5G_mkroot (H5F_t *f, size_t size_hint) { - H5G_entry_t *handle=NULL; /*handle to open object */ herr_t ret_value=FAIL; /*return value */ H5O_name_t name={NULL}; /*object name */ H5O_stab_t stab; /*symbol table message */ - H5G_entry_t *ent_ptr=NULL; /*pointer to a symbol table entry*/ + H5G_entry_t new_root; /*new root object */ const char *obj_name=NULL; /*name of old root object */ FUNC_ENTER (H5G_mkroot, FAIL); + /* check args */ + assert (f); + /* - * Make sure that the file descriptor has the latest info -- someone might - * have the root object open. - */ - H5G_shadow_sync (f->shared->root_sym); - - /* - * If we already have a root object, then open it and get it's name. The - * root object had better not already be a group. Once the old root - * object is opened and we have a HANDLE, set the dirty bit on the handle. - * This causes the handle data to be written back into f->root_sym by - * H5G_close() if something goes wrong before the old root object is - * re-inserted back into the group directed graph. We might leak file - * memory, but at least we don't loose the original root object. + * If we already have a root object, then get it's name. */ - if (H5F_addr_defined (&(f->shared->root_sym->header))) { - if (H5O_read (f, NO_ADDR, f->shared->root_sym, H5O_STAB, 0, &stab)) { - HGOTO_ERROR (H5E_SYM, H5E_EXISTS, -2, - "root group already exists"); - } else if (NULL==(handle=H5G_shadow_open (f, NULL, - f->shared->root_sym))) { - HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, - "can't open root object"); - } else if (NULL==H5O_read (f, NO_ADDR, handle, H5O_NAME, 0, &name)) { + if (f->shared->root_ent) { + if (H5O_read (f, f->shared->root_ent, H5O_STAB, 0, &stab)) { + HGOTO_ERROR (H5E_SYM, H5E_EXISTS, -2, "root group already exists"); + } else if (NULL==H5O_read (f, f->shared->root_ent, H5O_NAME, 0, &name)) { obj_name = "Root Object"; } else { obj_name = name.s; /*don't reset message until the end!*/ } - handle->dirty = TRUE; } /* - * Create the new root group directly into the file descriptor. If - * something goes wrong at this step, closing the `handle' will rewrite - * info back into f->root_sym because we set the dirty bit. + * Create the new root group. Set the link count to 1. */ - if (H5G_stab_create (f, f->shared->root_sym, size_hint)<0) { + if (H5G_stab_create (f, size_hint, &new_root/*out*/)<0) { HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, "cant create root"); } - if (1!=H5O_link (f, f->shared->root_sym, 1)) { + if (1!=H5O_link (f, &new_root, 1)) { HGOTO_ERROR (H5E_SYM, H5E_LINK, FAIL, "internal error (wrong link count)"); } /* * If there was a previous root object then insert it into the new root - * symbol table with the specified name. Inserting the object will update - * the handle to point to the new symbol table slot instead of f->root_sym. + * symbol table with the specified name. Then make the root object the + * new symbol table. */ - if (obj_name) { - if (1!=H5O_link (f, handle, 0)) { - HGOTO_ERROR (H5E_SYM, H5E_LINK, FAIL, - "bad link count on old root object"); - } - if (NULL==(ent_ptr=H5G_stab_insert (f, f->shared->root_sym, obj_name, - handle))) { + if (f->shared->root_ent) { + assert (1==H5O_link (f, f->shared->root_ent, 0)); + + if (H5G_stab_insert (f, &new_root, obj_name, f->shared->root_ent)<0) { HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, "can't reinsert old root object"); } @@ -633,33 +727,31 @@ H5G_mkroot (H5F_t *f, size_t size_hint) * a name message should ever appear is to give the root object a name, * but the old root object is no longer the root object. */ - H5O_remove (f, NO_ADDR, handle, H5O_NAME, H5O_ALL); + H5O_remove (f, f->shared->root_ent, H5O_NAME, H5O_ALL); H5ECLEAR; /*who really cares?*/ + + *(f->shared->root_ent) = new_root; + + } else { + f->shared->root_ent = H5MM_xmalloc (sizeof(H5G_entry_t)); + *(f->shared->root_ent) = new_root; } - + + H5O_close (f, &new_root); ret_value = SUCCEED; done: - /* - * If the handle is closed before the H5G_stab_insert() call that - * reinserts the root object into the group directed graph, then - * H5G_close() will reset f->root_sym to point to the old root symbol and - * the new root group (if it was created) will be unlinked from the - * group directed graph (and memory leaked). - */ - if (handle) H5G_close (f, handle); H5O_reset (H5O_NAME, &name); - FUNC_LEAVE (ret_value); } /*------------------------------------------------------------------------- - * Function: H5G_new + * Function: H5G_create * - * Purpose: Creates a new empty group with the specified name, - * opening it as an object. The name is either an absolute name - * or is relative to the current working group. + * Purpose: Creates a new empty group with the specified name. The name + * is either an absolute name or is relative to the current + * working group. * * A root group is created implicitly by this function * when necessary. Calling this function with the name "/" @@ -667,16 +759,10 @@ H5G_mkroot (H5F_t *f, size_t size_hint) * failure. * * Errors: - * SYM CANTINIT Can't create grp. - * SYM CANTINIT Can't create root group. - * SYM CANTINIT Can't insert. - * SYM CANTINIT Can't open. - * SYM COMPLEN Component is too long. - * SYM EXISTS Already exists. - * SYM NOTFOUND Missing component. * - * Return: Success: A handle to the open group. Please call - * H5G_close() when you're done with it. + * Return: Success: A handle for the group. The group is opened + * and should eventually be close by calling + * H5G_close(). * * Failure: NULL * @@ -688,57 +774,46 @@ H5G_mkroot (H5F_t *f, size_t size_hint) * *------------------------------------------------------------------------- */ -H5G_entry_t * -H5G_new (H5F_t *f, const char *name, size_t size_hint) +H5G_t * +H5G_create (H5F_t *f, const char *name, size_t size_hint) { const char *rest=NULL; /*the base name */ - H5G_entry_t *cwg=NULL; /*current working group */ H5G_entry_t grp_ent; /*group containing new group */ - H5G_entry_t ent; /*new group entry */ - H5G_entry_t *ent_ptr=NULL; /*ptr to new group entry */ - H5G_entry_t *ret_value=NULL; /*handle return value */ char _comp[1024]; /*name component */ size_t nchars; /*number of characters in compon*/ herr_t status; /*function return status */ + H5G_t *grp = NULL; /*new group */ - FUNC_ENTER (H5G_new, NULL); + FUNC_ENTER (H5G_create, NULL); /* check args */ assert (f); assert (name && *name); -#ifndef LATER - /* Get current working group */ - H5G_shadow_sync (f->shared->root_sym); - cwg = f->shared->root_sym; -#endif - assert (cwg || '/'==*name); /* * Try to create the root group. Ignore the error if this function * fails because the root group already exists. */ if ((status=H5G_mkroot (f, H5G_SIZE_HINT))<0 && -2!=status) { - HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL, - "can't create root group"); + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL, "can't create root group"); } H5ECLEAR; /* lookup name */ - if (H5G_namei (f, cwg, name, &rest, &grp_ent)) { + if (0==H5G_namei (f, NULL, name, &rest, &grp_ent, NULL)) { HRETURN_ERROR (H5E_SYM, H5E_EXISTS, NULL, "already exists"); } H5ECLEAR; /*it's OK that we didn't find it*/ + assert (H5F_addr_defined (&(grp_ent.header))); /* should be one null-terminated component left */ rest = H5G_component (rest, &nchars); assert (rest && *rest); if (rest[nchars]) { if (H5G_component (rest+nchars, NULL)) { - HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL, - "missing component"); + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL, "missing component"); } else if (nchars+1 > sizeof _comp) { - HRETURN_ERROR (H5E_SYM, H5E_COMPLEN, NULL, - "component is too long"); + HRETURN_ERROR (H5E_SYM, H5E_COMPLEN, NULL, "component is too long"); } else { /* null terminate */ HDmemcpy (_comp, rest, nchars); @@ -747,35 +822,154 @@ H5G_new (H5F_t *f, const char *name, size_t size_hint) } } - /* create group */ - if (H5G_stab_create (f, &ent, size_hint)<0) { + /* create and open group */ + grp = H5MM_xcalloc (1, sizeof(H5G_t)); + grp->file = f; + if (H5G_stab_create (f, size_hint, &(grp->ent)/*out*/)<0) { + grp = H5MM_xfree (grp); HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL, "can't create grp"); } /* insert child name into parent */ - if (NULL==(ent_ptr=H5G_stab_insert (f, &grp_ent, rest, &ent))) { + if (H5G_stab_insert (f, &grp_ent, rest, &(grp->ent))<0) { + H5O_close (f, &(grp->ent)); + grp = H5MM_xfree (grp); HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL, "can't insert"); } - /* open the group */ - if (NULL==(ret_value=H5G_shadow_open (f, &grp_ent, ent_ptr))) { - HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL, "can't open"); + grp->nref = 1; + FUNC_LEAVE (grp); +} + + +/*------------------------------------------------------------------------- + * Function: H5G_open + * + * Purpose: Opens an existing group. The group should eventually be + * closed by calling H5G_close(). + * + * Return: Success: Ptr to a new group. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * Monday, January 5, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +H5G_t * +H5G_open (H5F_t *f, const char *name) +{ + H5G_t *grp = NULL; + H5G_t *ret_value = NULL; + + FUNC_ENTER (H5G_open, NULL); + + /* Check args */ + assert (f); + assert (name && *name); + + /* Open the group */ + grp = H5MM_xcalloc (1, sizeof(H5G_t)); + if (H5G_find (f, name, NULL, &(grp->ent))<0) { + HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, NULL, "group not found"); + } + if (H5O_open (f, &(grp->ent))<0) { + HGOTO_ERROR (H5E_SYM, H5E_CANTOPENOBJ, NULL, "unable to open group"); + } + grp->file = f; + grp->nref = 1; + ret_value = grp; + + done: + if (!ret_value && grp) { + H5MM_xfree (grp); } FUNC_LEAVE (ret_value); } + +/*------------------------------------------------------------------------- + * Function: H5G_reopen + * + * Purpose: Reopens a group by incrementing the open count. + * + * Return: Success: The GRP argument. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * Monday, January 5, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +H5G_t * +H5G_reopen (H5G_t *grp) +{ + FUNC_ENTER (H5G_reopen, NULL); + + assert (grp); + assert (grp->nref>0); + + grp->nref++; + + FUNC_LEAVE (grp); +} + + +/*------------------------------------------------------------------------- + * Function: H5G_close + * + * Purpose: Closes the specified group. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Monday, January 5, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_close (H5G_t *grp) +{ + FUNC_ENTER (H5G_close, FAIL); + + /* Check args */ + assert (grp); + assert (grp->nref>0); + + if (1==grp->nref) { + if (H5O_close (grp->file, &(grp->ent))<0) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, "unable to close"); + } + } + --grp->nref; + + FUNC_LEAVE (SUCCEED); +} /*------------------------------------------------------------------------- * Function: H5G_set * - * Purpose: Sets the current working group to be the specified name. + * Purpose: Sets the current working group to be the specified group. * This affects only the top item on the group stack for the * specified file as accessed through this file handle. If the * file is opened multiple times, then the current working group * for this file handle is the only one that is changed. * + * Note: The group is re-opened and held open until it is removed from + * the current working group stack. + * * Errors: * SYM CWG Can't open group. * SYM CWG Couldn't close previous c.w.g. @@ -793,19 +987,20 @@ H5G_new (H5F_t *f, const char *name, size_t size_hint) *------------------------------------------------------------------------- */ herr_t -H5G_set (H5F_t *f, const char *name) +H5G_set (H5F_t *f, H5G_t *grp) { - H5G_entry_t *handle=NULL; - H5O_stab_t stab_mesg; - herr_t ret_value=FAIL; - FUNC_ENTER (H5G_set, FAIL); - if (NULL==(handle=H5G_open (f, name))) { - HGOTO_ERROR (H5E_SYM, H5E_CWG, FAIL, "can't open group"); - } - if (NULL==H5O_read (f, NO_ADDR, handle, H5O_NAME, 0, &stab_mesg)) { - HGOTO_ERROR (H5E_SYM, H5E_CWG, FAIL, "not a group"); + /* check args */ + assert (f); + assert (grp); + + /* + * Are the group and file compatible? + */ + if (grp->file->shared!=f->shared) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, + "group is not compatible with file"); } /* @@ -814,36 +1009,27 @@ H5G_set (H5F_t *f, const char *name) */ if (!f->cwg_stack) { f->cwg_stack = H5MM_xcalloc (1, sizeof(H5G_cwgstk_t)); - f->cwg_stack->handle = handle; - } else { - if (H5G_close (f, f->cwg_stack->handle)<0) { - HGOTO_ERROR (H5E_SYM, H5E_CWG, FAIL, - "couldn't close previous c.w.g."); - } - f->cwg_stack->handle = handle; + } else if (H5G_close (f->cwg_stack->grp)<0) { + HRETURN_ERROR (H5E_SYM, H5E_CWG, FAIL, "couldn't close previous c.w.g."); } - ret_value = SUCCEED; + f->cwg_stack->grp = H5G_reopen (grp); - done: - if (ret_value<0 && handle) { - H5G_close (f, handle); - } - - FUNC_LEAVE (ret_value); + FUNC_LEAVE (SUCCEED); } - /*------------------------------------------------------------------------- * Function: H5G_getcwg * - * Purpose: Returns a handle for the current working group. If there - * is no current working group then a pointer to the root - * symbol is returned but that object is not opened (and it - * might not even be a group). + * Purpose: Returns a ptr to the symbol table entry for the current + * working group. If there is no current working group then a + * pointer to the root symbol is returned. If there is no root + * symbol then the null pointer is returned. * - * Return: Success: Ptr to open group handle with exceptions - * noted above. + * Return: Success: Ptr to the current working group or root + * object. The pointer is valid only until the + * root object changes or the current working + * group changes. * * Failure: NULL * @@ -857,26 +1043,29 @@ H5G_set (H5F_t *f, const char *name) static H5G_entry_t * H5G_getcwg (H5F_t *f) { - H5G_entry_t *handle=NULL; + H5G_entry_t *ret_value=NULL; FUNC_ENTER (H5G_getcwg, NULL); + + /* check args */ + assert (f); - if (f->cwg_stack && f->cwg_stack->handle) { - handle = f->cwg_stack->handle; + /* return a pointer directly into the stack */ + if (f->cwg_stack && f->cwg_stack->grp) { + ret_value = &(f->cwg_stack->grp->ent); } else { - H5G_shadow_sync (f->shared->root_sym); - handle = f->shared->root_sym; + ret_value = f->shared->root_ent; } - FUNC_LEAVE (handle); + FUNC_LEAVE (ret_value); } - /*------------------------------------------------------------------------- * Function: H5G_push * - * Purpose: Pushes a new current working group onto the stack. + * Purpose: Pushes a new current working group onto the stack. The GRP + * is reopened and held open until it is removed from the stack. * * Errors: * SYM CWG Can't open group. @@ -894,35 +1083,31 @@ H5G_getcwg (H5F_t *f) *------------------------------------------------------------------------- */ herr_t -H5G_push (H5F_t *f, const char *name) +H5G_push (H5F_t *f, H5G_t *grp) { - H5G_entry_t *handle=NULL; H5G_cwgstk_t *stack=NULL; - H5O_stab_t stab_mesg; - herr_t ret_value = FAIL; FUNC_ENTER (H5G_push, FAIL); - if (NULL==(handle=H5G_open (f, name))) { - HGOTO_ERROR (H5E_SYM, H5E_CWG, FAIL, "can't open group"); - } - if (NULL==H5O_read (f, NO_ADDR, handle, H5O_NAME, 0, &stab_mesg)) { - HGOTO_ERROR (H5E_SYM, H5E_CWG, FAIL, "not a group"); - } + /* check args */ + assert (f); + assert (grp); /* + * Are the group and file compatible? + */ + if (grp->file->shared!=f->shared) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, + "group is not compatible with file"); + } + + /* * Push a new entry onto the stack. */ stack = H5MM_xcalloc (1, sizeof(H5G_cwgstk_t)); - stack->handle = handle; + stack->grp = H5G_reopen (grp); stack->next = f->cwg_stack; f->cwg_stack = stack; - ret_value = SUCCEED; - - done: - if (ret_value<0 && handle) { - H5G_close (f, handle); - } FUNC_LEAVE (SUCCEED); } @@ -955,13 +1140,16 @@ H5G_pop (H5F_t *f) FUNC_ENTER (H5G_pop, FAIL); + /* check args */ + assert (f); + if ((stack=f->cwg_stack)) { - if (H5G_close (f, stack->handle)<0) { + if (H5G_close (stack->grp)<0) { HRETURN_ERROR (H5E_SYM, H5E_CWG, FAIL, "can't close current working group"); } f->cwg_stack = stack->next; - stack->handle = NULL; + stack->grp = NULL; H5MM_xfree (stack); } else { HRETURN_ERROR (H5E_SYM, H5E_CWG, FAIL, "stack is empty"); @@ -972,30 +1160,13 @@ H5G_pop (H5F_t *f) /*------------------------------------------------------------------------- - * Function: H5G_create + * Function: H5G_insert * - * Purpose: Creates a new empty object header, gives it a name, opens - * the object for modification, and returns a handle to the - * object. The initial size of the object header can be - * supplied with the OHDR_HINT argument. + * Purpose: Inserts a symbol table entry into the group graph. * * Errors: - * SYM CANTINIT Bad link count. - * SYM CANTINIT Can't create header. - * SYM CANTINIT Can't create root group. - * SYM CANTINIT Can't insert. - * SYM CANTINIT Can't open object. - * SYM CANTINIT Cannot add/change name message. - * SYM CANTINIT Create the object header. - * SYM COMPLEN Component is too long. - * SYM EXISTS Already exists. - * SYM EXISTS Root exists. - * SYM LINK Bad link count. - * SYM LINK Link inc failure. - * SYM NOTFOUND Component not found. - * - * Return: Success: A handle for the object. Be sure to - * eventually close it. + * + * Return: Success: SUCCEED * * Failure: FAIL * @@ -1006,35 +1177,28 @@ H5G_pop (H5F_t *f) * *------------------------------------------------------------------------- */ -H5G_entry_t * -H5G_create (H5F_t *f, const char *name, size_t ohdr_hint) +herr_t +H5G_insert (H5F_t *f, const char *name, H5G_entry_t *ent) { - H5G_entry_t ent; /*entry data for the new object */ - H5G_entry_t *ent_ptr; /*ptr into symbol node for entry*/ - H5G_entry_t *cwg=NULL; /*ptr to c.w.g. handle */ const char *rest = NULL; /*part of name not existing yet */ H5G_entry_t grp; /*entry for group to contain obj*/ - H5G_entry_t *ret_value=NULL; /*the object handle */ size_t nchars; /*number of characters in name */ char _comp[1024]; /*name component */ + hbool_t update_grp; + herr_t status; - FUNC_ENTER (H5G_create, NULL); + FUNC_ENTER (H5G_insert, FAIL); /* Check args. */ assert (f); assert (name && *name); - HDmemset (&ent, 0, sizeof(H5G_entry_t)); - - /* - * Get the current working group. - */ - cwg = H5G_getcwg (f); + assert (ent); /* * Look up the name -- it shouldn't exist yet. */ - if (H5G_namei (f, cwg, name, &rest, &grp)) { - HRETURN_ERROR (H5E_SYM, H5E_EXISTS, NULL, "already exists"); + if (H5G_namei (f, NULL, name, &rest, &grp, NULL)>=0) { + HRETURN_ERROR (H5E_SYM, H5E_EXISTS, FAIL, "already exists"); } H5ECLEAR; /*it's OK that we didn't find it*/ rest = H5G_component (rest, &nchars); @@ -1045,22 +1209,16 @@ H5G_create (H5F_t *f, const char *name, size_t ohdr_hint) * doesn't have a name or we shouldn't interfere with the name * it already has as a message. */ - if (H5F_addr_defined (&(f->shared->root_sym->header))) { - HRETURN_ERROR (H5E_SYM, H5E_EXISTS, NULL, "root exists"); + if (f->shared->root_ent) { + HRETURN_ERROR (H5E_SYM, H5E_EXISTS, FAIL, "root exists"); } - if (H5O_create (f, 0, ohdr_hint, &(ent.header)/*out*/)<0) { - HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL, - "can't create header"); + if (1!=H5O_link (f, ent, 1)) { + HRETURN_ERROR (H5E_SYM, H5E_LINK, FAIL, "bad link count"); } - if (1!=H5O_link (f, &ent, 1)) { - HRETURN_ERROR (H5E_SYM, H5E_LINK, NULL, "bad link count"); - } - *(f->shared->root_sym) = ent; - if (NULL==(ret_value=H5G_shadow_open (f, NULL, f->shared->root_sym))) { - HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL, - "can't open root object"); - } - HRETURN (ret_value); + f->shared->root_ent = H5MM_xmalloc (sizeof(H5G_entry_t)); + ent->name_off = 0; + *(f->shared->root_ent) = *ent; + HRETURN (SUCCEED); } /* @@ -1069,11 +1227,9 @@ H5G_create (H5F_t *f, const char *name, size_t ohdr_hint) */ if (rest[nchars]) { if (H5G_component (rest+nchars, NULL)) { - HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL, - "component not found"); + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "component not found"); } else if (nchars+1 > sizeof _comp) { - HRETURN_ERROR (H5E_SYM, H5E_COMPLEN, NULL, - "component is too long"); + HRETURN_ERROR (H5E_SYM, H5E_COMPLEN, FAIL, "component is too long"); } else { /* null terminate */ HDmemcpy (_comp, rest, nchars); @@ -1082,166 +1238,50 @@ H5G_create (H5F_t *f, const char *name, size_t ohdr_hint) } } - /* - * Create the object header. - */ - if (H5O_create (f, 0, ohdr_hint, &(ent.header)/*out*/)<0) { - HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL, - "can't create object header"); - } - - - if (!H5F_addr_defined (&(f->shared->root_sym->header))) { + if (!f->shared->root_ent) { /* * This will be the only object in the file. Insert it as the root * object and add a name messaage to the object header (or modify - * the first one we find). Although the header exists we can guarantee - * that it isn't open since it has no name. + * the first one we find). */ H5O_name_t name_mesg; name_mesg.s = rest; - if (H5O_modify (f, NO_ADDR, &ent, H5O_NAME, 0, &name_mesg)<0) { - HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL, + if (H5O_modify (f, ent, H5O_NAME, 0, &name_mesg)<0) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, "cannot add/change name message"); } - if (1!=H5O_link (f, &ent, 1)) { - HRETURN_ERROR (H5E_SYM, H5E_LINK, NULL, "bad link count"); - } - *(f->shared->root_sym) = ent; - if (NULL==(ret_value=H5G_shadow_open (f, &grp, f->shared->root_sym))) { - HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL, - "can't open root object"); + if (1!=H5O_link (f, ent, 1)) { + HRETURN_ERROR (H5E_SYM, H5E_LINK, FAIL, "bad link count"); } - HRETURN (ret_value); - } else { - /* - * Make sure the root group exists. Ignore the failure if it's - * because the group already exists. - */ - hbool_t update_grp = H5F_addr_eq (&(grp.header), - &(f->shared->root_sym->header)); - herr_t status = H5G_mkroot (f, H5G_SIZE_HINT); - if (status<0 && -2!=status) { - HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL, - "can't create root group"); - } - H5ECLEAR; - if (update_grp) grp = *(f->shared->root_sym); + f->shared->root_ent = H5MM_xmalloc (sizeof(H5G_entry_t)); + *(f->shared->root_ent) = *ent; + HRETURN (SUCCEED); } - + /* - * This is the normal case. The object is just being inserted as a normal - * entry into a symbol table. + * Make sure the root group exists. Ignore the failure if it's + * because the group already exists. */ - if (H5O_link (f, &ent, 1)<0) { - HRETURN_ERROR (H5E_SYM, H5E_LINK, NULL, "link inc failure"); - } - if (NULL==(ent_ptr=H5G_stab_insert (f, &grp, rest, &ent))) { - HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL, "can't insert"); - } - if (NULL==(ret_value=H5G_shadow_open (f, &grp, ent_ptr))) { - HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL, "can't open object"); + update_grp = H5F_addr_eq (&(grp.header), + &(f->shared->root_ent->header)); + if ((status=H5G_mkroot (f, H5G_SIZE_HINT))<0 && -2!=status) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, "can't create root group"); } - FUNC_LEAVE (ret_value); -} + H5ECLEAR; + if (update_grp) grp = *(f->shared->root_ent); - -/*------------------------------------------------------------------------- - * Function: H5G_open - * - * Purpose: Opens an object. That is, it prepares the object for - * modification by returning a handle to the object - * symbol table entry. Opening an object twice with the - * same name (or more precisely, through the same final - * symbol table entry) will return pointers to the same - * H5G_entry_t struct. But opening an object through - * different final H5G_entry_t structs (which implies - * different names) returns pointers to different - * structs. The structs that are returned should be - * released by calling H5G_close(). - * - * Errors: - * SYM BADVALUE Check args. - * SYM CANTOPENOBJ Can't open obj. - * SYM NOTFOUND Object not found. - * - * Return: Success: Ptr to a handle for the object. - * - * Failure: NULL - * - * Programmer: Robb Matzke - * Wednesday, September 17, 1997 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -H5G_entry_t * -H5G_open (H5F_t *f, const char *name) -{ - H5G_entry_t *ent=NULL; - H5G_entry_t *ret_value=NULL; - H5G_entry_t grp; - H5G_entry_t *cwg=NULL; - FUNC_ENTER (H5G_open, NULL); - - /* check args */ - assert (f); - if (!name || !*name) { - HRETURN_ERROR (H5E_SYM, H5E_BADVALUE, NULL, "no name"); - } - - /* Get CWG */ - cwg = H5G_getcwg (f); - assert (cwg || '/'==*name); - - if (!H5F_addr_defined (&(f->shared->root_sym->header))) { - HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL, "object not found"); - } - if (NULL==(ent=H5G_namei (f, cwg, name, NULL, &grp))) { - HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL, "object not found"); + /* + * This is the normal case. The object is just being inserted as a normal + * entry into a symbol table. + */ + if (H5O_link (f, ent, 1)<0) { + HRETURN_ERROR (H5E_SYM, H5E_LINK, FAIL, "link inc failure"); } - if (NULL==(ret_value=H5G_shadow_open (f, &grp, ent))) { - HRETURN_ERROR (H5E_SYM, H5E_CANTOPENOBJ, NULL, "can't open obj"); + if (H5G_stab_insert (f, &grp, rest, ent)<0) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, "can't insert"); } - FUNC_LEAVE (ret_value); -} - - - -/*------------------------------------------------------------------------- - * Function: H5G_close - * - * Purpose: Closes an object that was open for modification. - * - * Errors: - * SYM CANTFLUSH Can't close object. - * - * Return: Success: SUCCEED - * - * Failure: FAIL - * - * Programmer: Robb Matzke - * Thursday, September 18, 1997 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5G_close (H5F_t *f, H5G_entry_t *ent) -{ - FUNC_ENTER (H5G_close, FAIL); - - assert (f); - - if (ent && H5G_shadow_close (f, ent)<0) { - HRETURN_ERROR (H5E_SYM, H5E_CANTFLUSH, FAIL, - "can't close object"); - } - FUNC_LEAVE (SUCCEED); } @@ -1254,25 +1294,19 @@ H5G_close (H5F_t *f, H5G_entry_t *ent) * to the current working group. On successful return, * GRP_ENT (if non-null) will be initialized with the symbol * table information for the group in which the object - * appears (or all zero if the returned object is the root - * object) and ENT will be initialized with the symbol table - * entry for the object (ENT is optional when the caller is - * interested only in the existence of the object). + * appears (it will have an undefined object header address if + * the object is the root object) and OBJ_ENT will be + * initialized with the symbol table entry for the object + * (OBJ_ENT is optional when the caller is interested only in + * the existence of the object). * - * This function will fail if the root object is - * requested and there is none. + * This function will fail if the root object is requested and + * there is none. * * Errors: - * SYM NOTFOUND Object not found. * - * Return: Success: SUCCEED with GRP_ENT and ENT initialized. ENT - * is intended for immediate read-only access. - * If the object that ENT refers to is open - * through the ENT entry (see H5G_open()) then - * the returned ENT will contain the latest - * information. However, subsequent changes to - * the symbol table entry will not be reflected - * in ENT since it is a copy of the symbol table. + * Return: Success: SUCCEED, see above for values of GRP_ENT and + * OBJ_ENT. * * Failure: FAIL * @@ -1286,28 +1320,17 @@ H5G_close (H5F_t *f, H5G_entry_t *ent) */ herr_t H5G_find (H5F_t *f, const char *name, - H5G_entry_t *grp_ent/*out*/, H5G_entry_t *ent/*out*/) + H5G_entry_t *grp_ent/*out*/, H5G_entry_t *obj_ent/*out*/) { - H5G_entry_t *ent_p = NULL; - H5G_entry_t *cwg = NULL; - FUNC_ENTER (H5G_find, FAIL); /* check args */ assert (f); assert (name && *name); - cwg = H5G_getcwg (f); - assert (cwg || '/'==*name); - if (!H5F_addr_defined (&(f->shared->root_sym->header))) { + if (H5G_namei (f, NULL, name, NULL, grp_ent, obj_ent)<0) { HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "object not found"); } - if (NULL==(ent_p=H5G_namei (f, cwg, name, NULL, grp_ent))) { - HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "object not found"); - } - - if (ent) *ent = *ent_p; FUNC_LEAVE (SUCCEED); } - diff --git a/src/H5Gent.c b/src/H5Gent.c index b8510f7..cc33d4c 100644 --- a/src/H5Gent.c +++ b/src/H5Gent.c @@ -364,35 +364,42 @@ H5G_ent_encode (H5F_t *f, uint8 **pp, H5G_entry_t *ent) /* check arguments */ assert (f); assert (pp); - assert (ent); - - /* encode header */ - H5F_encode_length (f, *pp, ent->name_off); - H5F_addr_encode (f, pp, &(ent->header)); - UINT32ENCODE (*pp, ent->type); - - /* encode scratch-pad */ - switch (ent->type) { - case H5G_NOTHING_CACHED: - break; - - case H5G_CACHED_SDSPACE: - assert (5*4 <= H5G_SIZEOF_SCRATCH); - UINT32ENCODE (*pp, ent->cache.sdspace.ndim); - UINT32ENCODE (*pp, ent->cache.sdspace.dim[0]); - UINT32ENCODE (*pp, ent->cache.sdspace.dim[1]); - UINT32ENCODE (*pp, ent->cache.sdspace.dim[2]); - UINT32ENCODE (*pp, ent->cache.sdspace.dim[3]); - break; - case H5G_CACHED_STAB: - assert (2*H5F_SIZEOF_ADDR (f) <= H5G_SIZEOF_SCRATCH); - H5F_addr_encode (f, pp, &(ent->cache.stab.btree_addr)); - H5F_addr_encode (f, pp, &(ent->cache.stab.heap_addr)); - break; - - default: - HDabort(); + if (ent) { + /* encode header */ + H5F_encode_length (f, *pp, ent->name_off); + H5F_addr_encode (f, pp, &(ent->header)); + UINT32ENCODE (*pp, ent->type); + + /* encode scratch-pad */ + switch (ent->type) { + case H5G_NOTHING_CACHED: + break; + + case H5G_CACHED_SDSPACE: + assert (5*4 <= H5G_SIZEOF_SCRATCH); + UINT32ENCODE (*pp, ent->cache.sdspace.ndim); + UINT32ENCODE (*pp, ent->cache.sdspace.dim[0]); + UINT32ENCODE (*pp, ent->cache.sdspace.dim[1]); + UINT32ENCODE (*pp, ent->cache.sdspace.dim[2]); + UINT32ENCODE (*pp, ent->cache.sdspace.dim[3]); + break; + + case H5G_CACHED_STAB: + assert (2*H5F_SIZEOF_ADDR (f) <= H5G_SIZEOF_SCRATCH); + H5F_addr_encode (f, pp, &(ent->cache.stab.btree_addr)); + H5F_addr_encode (f, pp, &(ent->cache.stab.heap_addr)); + break; + + default: + HDabort(); + } + } else { + haddr_t undef; + H5F_encode_length (f, *pp, 0); + H5F_addr_undef (&undef); + H5F_addr_encode (f, pp, &undef); + UINT32ENCODE (*pp, H5G_NOTHING_CACHED); } /* fill with zero */ @@ -443,11 +450,6 @@ H5G_ent_debug (H5F_t *f, H5G_entry_t *ent, FILE *stream, intn indent, fprintf (stream, "%*s%-*s %s\n", indent, "", fwidth, "Dirty:", ent->dirty ? "Yes" : "No"); - fprintf (stream, "%*s%-*s %s\n", indent, "", fwidth, - "Has a shadow:", - H5G_shadow_p (ent)?"This is a shadow!" : - (ent->shadow ? "Yes" : "No")); - fprintf (stream, "%*s%-*s ", indent, "", fwidth, "Symbol type:"); switch (ent->type) { diff --git a/src/H5Gnode.c b/src/H5Gnode.c index c4349a5..f124d3e 100644 --- a/src/H5Gnode.c +++ b/src/H5Gnode.c @@ -15,12 +15,6 @@ * * Modifications: * - * Robb Matzke, 5 Aug 1997 - * Added calls to H5E. - * - * Robb Matzke, 18 Sep 1997 - * Added shadow entries. - * *------------------------------------------------------------------------- */ #define H5G_PACKAGE /*suppress error message about including H5Gpkg.h*/ @@ -216,10 +210,10 @@ H5G_node_size (H5F_t *f) /*------------------------------------------------------------------------- * Function: H5G_node_create * - * Purpose: Creates a new empty symbol table. This function is called - * by the B-tree insert function for an empty tree. It is - * also called internally to split a symbol node with - * LT_KEY and RT_KEY null pointers. + * Purpose: Creates a new empty symbol table node. This function is + * called by the B-tree insert function for an empty tree. It + * is also called internally to split a symbol node with LT_KEY + * and RT_KEY null pointers. * * Return: Success: SUCCEED. The address of symbol table node is * returned through the ADDR argument. @@ -285,10 +279,7 @@ H5G_node_create (H5F_t *f, H5B_ins_t op, /*------------------------------------------------------------------------- * Function: H5G_node_flush * - * Purpose: Flush a symbol table node to disk. If any entries have dirty - * shadows, the shadow value is copied into the entry before the - * entry is flushed. The association between shadows and - * entries is broken. + * Purpose: Flush a symbol table node to disk. * * Return: Success: SUCCEED * @@ -321,15 +312,9 @@ H5G_node_flush (H5F_t *f, hbool_t destroy, const haddr_t *addr, assert (sym); /* - * Synchronize all entries with their corresponding shadow if they have - * one. Also look for dirty entries and set the node dirty flag. + * Look for dirty entries and set the node dirty flag. */ for (i=0; i<sym->nsyms; i++) { - if (H5G_shadow_sync (sym->entry+i)<0) { - HRETURN_ERROR (H5E_SYM, H5E_CANTFLUSH, FAIL, - "unable to synchronize symbol table node with open " - "objects"); - } if (sym->entry[i].dirty) sym->dirty = TRUE; } @@ -366,13 +351,9 @@ H5G_node_flush (H5F_t *f, hbool_t destroy, const haddr_t *addr, /* * Destroy the symbol node? This might happen if the node is being - * preempted from the cache. We should also dissociate the shadow - * from the entry. + * preempted from the cache. */ if (destroy) { - for (i=0; i<sym->nsyms; i++) { - H5G_shadow_dissociate (sym->entry+i); - } sym->entry = H5MM_xfree (sym->entry); H5MM_xfree (sym); } @@ -384,8 +365,7 @@ H5G_node_flush (H5F_t *f, hbool_t destroy, const haddr_t *addr, /*------------------------------------------------------------------------- * Function: H5G_node_load * - * Purpose: Loads a symbol table from the file and associates shadows - * with their entries. + * Purpose: Loads a symbol table node from the file. * * Return: Success: Ptr to the new table. * @@ -407,7 +387,6 @@ H5G_node_load (H5F_t *f, const haddr_t *addr, const void *_udata1, size_t size = 0; uint8 *buf = NULL; const uint8 *p = NULL; - const H5G_ac_ud1_t *ac_udata = (const H5G_ac_ud1_t*)_udata1; H5G_node_t *ret_value = NULL; /*for error handling*/ FUNC_ENTER (H5G_node_load, NULL); @@ -417,7 +396,7 @@ H5G_node_load (H5F_t *f, const haddr_t *addr, const void *_udata1, */ assert (f); assert (addr && H5F_addr_defined (addr)); - assert (ac_udata); + assert (!_udata1); assert (NULL==_udata2); /* @@ -459,18 +438,6 @@ H5G_node_load (H5F_t *f, const haddr_t *addr, const void *_udata1, } buf = H5MM_xfree (buf); - /* - * shadows. If we are running this under the debugger, then the grp_addr - * field of ac_udata might be undefined. If that's the case, then we - * don't try to associate any shadows with this symbol table node. - */ - if (H5F_addr_defined (&(ac_udata->grp_addr)) && - H5G_shadow_assoc_node (f, sym, ac_udata)<0) { - HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, NULL, - "unable to associate symbol table node with open " - "objects"); - } - ret_value = sym; @@ -609,8 +576,8 @@ H5G_node_cmp3 (H5F_t *f, void *_lt_key, void *_udata, void *_rt_key) * entry field. Otherwise the entry is copied from the * UDATA entry field to the symbol table. * - * Return: Success: SUCCEED if found and data returned through the - * UDATA pointer. + * Return: Success: SUCCEED if found and data returned through + * the UDATA pointer. * * Failure: FAIL if not found. * @@ -627,7 +594,6 @@ H5G_node_found (H5F_t *f, const haddr_t *addr, const void *_lt_key, void *_udata, const void *_rt_key) { H5G_bt_ud1_t *bt_udata = (H5G_bt_ud1_t *)_udata; - H5G_ac_ud1_t ac_udata; H5G_node_t *sn = NULL; intn lt=0, idx=0, rt, cmp=1; const char *s; @@ -642,13 +608,11 @@ H5G_node_found (H5F_t *f, const haddr_t *addr, const void *_lt_key, assert (addr && H5F_addr_defined (addr)); assert (bt_udata); - ac_udata.grp_addr = bt_udata->grp_addr; - ac_udata.heap_addr = bt_udata->heap_addr; /* * Load the symbol table node for exclusive access. */ - if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, &ac_udata, NULL))) { + if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, NULL, NULL))) { HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL, "unable to protect symbol table node"); } @@ -680,10 +644,7 @@ H5G_node_found (H5F_t *f, const haddr_t *addr, const void *_lt_key, * The caller is querying the symbol entry. Return just a pointer to * the entry. The pointer is valid until the next call to H5AC. */ - H5G_shadow_sync (sn->entry+idx); - bt_udata->entry_ptr = sn->entry+idx; - bt_udata->node_addr = *addr; - bt_udata->node_ptr = sn; + bt_udata->ent = sn->entry[idx]; break; default: @@ -694,16 +655,9 @@ H5G_node_found (H5F_t *f, const haddr_t *addr, const void *_lt_key, ret_value = SUCCEED; done: - /* - * Don't unprotect the symbol table entry if we're returning success since - * this might invalidate the bt_udata->entry_ptr and bt_udata->node_ptr - * pointers. Instead, we unprotect it in H5G_stab_find(). - */ - if (ret_value<0) { - if (sn && H5AC_unprotect (f, H5AC_SNODE, addr, sn)<0) { - HRETURN_ERROR (H5E_SYM, H5E_PROTECT, FAIL, - "unable to release symbol table node"); - } + if (sn && H5AC_unprotect (f, H5AC_SNODE, addr, sn)<0) { + HRETURN_ERROR (H5E_SYM, H5E_PROTECT, FAIL, + "unable to release symbol table node"); } FUNC_LEAVE (ret_value); @@ -744,10 +698,6 @@ done: * * Modifications: * - * Robb Matzke, 18 Sep 1997 - * If the shadow pointer is non-null then the shadow is updated to point - * to the new entry. - * *------------------------------------------------------------------------- */ static H5B_ins_t @@ -761,15 +711,12 @@ H5G_node_insert (H5F_t *f, const haddr_t *addr, H5G_node_key_t *rt_key = (H5G_node_key_t *)_rt_key; H5G_bt_ud1_t *bt_udata = (H5G_bt_ud1_t *)_udata; - H5G_ac_ud1_t ac_udata; H5G_node_t *sn=NULL, *snrt=NULL; size_t offset; /*offset of name in heap*/ const char *s; intn idx=-1, cmp=1; intn lt=0, rt; /*binary search cntrs */ - intn i; H5B_ins_t ret_value = H5B_INS_ERROR; - H5G_shadow_t *shadow = NULL; H5G_node_t *insert_into=NULL; /*node that gets new entry*/ haddr_t insert_addr; /*address of that node */ @@ -785,17 +732,10 @@ H5G_node_insert (H5F_t *f, const haddr_t *addr, assert (bt_udata); assert (new_node); - /* Init return value */ - H5F_addr_undef (&(bt_udata->node_addr)); - bt_udata->node_ptr = NULL; - bt_udata->entry_ptr = NULL; - /* * Load the symbol node. */ - ac_udata.grp_addr = bt_udata->grp_addr; - ac_udata.heap_addr = bt_udata->heap_addr; - if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, &ac_udata, NULL))) { + if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, NULL, NULL))) { HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR, "unable to protect symbol table node"); } @@ -831,7 +771,7 @@ H5G_node_insert (H5F_t *f, const haddr_t *addr, */ offset = H5H_insert (f, &(bt_udata->heap_addr), HDstrlen(bt_udata->name)+1, bt_udata->name); - bt_udata->entry.name_off = offset; + bt_udata->ent.name_off = offset; if (offset<=0) { HGOTO_ERROR (H5E_SYM, H5E_CANTINSERT, H5B_INS_ERROR, "unable to insert symbol name into heap"); @@ -851,7 +791,7 @@ H5G_node_insert (H5F_t *f, const haddr_t *addr, HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, H5B_INS_ERROR, "unable to split symbol table node"); } - if (NULL==(snrt=H5AC_find (f, H5AC_SNODE, new_node, &ac_udata, NULL))) { + if (NULL==(snrt=H5AC_find (f, H5AC_SNODE, new_node, NULL, NULL))) { HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR, "unable to split symbol table node"); } @@ -860,13 +800,6 @@ H5G_node_insert (H5F_t *f, const haddr_t *addr, snrt->nsyms = H5G_NODE_K(f); snrt->dirty = TRUE; - /* Right shadows */ - for (i=0; i<H5G_NODE_K(f); i++) { - if ((shadow = snrt->entry[i].shadow)) { - shadow->main = snrt->entry + i; - } - } - /* The left node */ HDmemset (sn->entry + H5G_NODE_K(f), 0, H5G_NODE_K(f) * sizeof(H5G_entry_t)); @@ -899,55 +832,18 @@ H5G_node_insert (H5F_t *f, const haddr_t *addr, } } - /* Adjust shadows */ - for (i=idx; i<insert_into->nsyms; i++) { - if (insert_into->entry[i].shadow) { - insert_into->entry[i].shadow->main = insert_into->entry + i + 1; - } - } - if (bt_udata->entry.shadow) { - H5G_shadow_move (f, bt_udata->entry.shadow, - bt_udata->name, - insert_into->entry + idx, - &(bt_udata->grp_addr)); - } - /* Move entries */ HDmemmove (insert_into->entry + idx + 1, insert_into->entry + idx, (insert_into->nsyms-idx) * sizeof(H5G_entry_t)); - insert_into->entry[idx] = bt_udata->entry; - insert_into->entry[idx].name_off = offset; + insert_into->entry[idx] = bt_udata->ent; insert_into->entry[idx].dirty = TRUE; insert_into->nsyms += 1; - /* Update udata return values */ - bt_udata->node_addr = insert_addr; - bt_udata->node_ptr = insert_into; - bt_udata->entry_ptr = insert_into->entry + idx; - done: - if (ret_value<0) { - /* failing... */ - if (sn && H5AC_unprotect (f, H5AC_SNODE, addr, sn)<0) { - HRETURN_ERROR (H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, - "unable to release symbol table node"); - } - } else if (insert_into!=sn) { - /* unprotect the first node and protect the return value */ - if (H5AC_unprotect (f, H5AC_SNODE, addr, sn)<0) { - HRETURN_ERROR (H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, - "unable to release symbol table node"); - } - if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, &insert_addr, &ac_udata, - NULL))) { - HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR, - "unable to protect symbol table node"); - } - bt_udata->node_ptr = sn; - bt_udata->entry_ptr = sn->entry + idx; - } else { - /* keep the node protected until we get back to H5G_stab_insert() */ + if (sn && H5AC_unprotect (f, H5AC_SNODE, addr, sn)<0) { + HRETURN_ERROR (H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, + "unable to release symbol table node"); } FUNC_LEAVE (ret_value); @@ -980,7 +876,6 @@ H5G_node_list (H5F_t *f, const haddr_t *addr, void *_udata) intn i; const char *s; herr_t ret_value = FAIL; - H5G_ac_ud1_t ac_udata; FUNC_ENTER (H5G_node_list, FAIL); @@ -991,9 +886,7 @@ H5G_node_list (H5F_t *f, const haddr_t *addr, void *_udata) assert (addr && H5F_addr_defined (addr)); assert (bt_udata); - ac_udata.grp_addr = bt_udata->grp_addr; - ac_udata.heap_addr = bt_udata->heap_addr; - if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, &ac_udata, NULL))) { + if (NULL==(sn=H5AC_protect (f, H5AC_SNODE, addr, NULL, NULL))) { HGOTO_ERROR (H5E_SYM, H5E_CANTLOAD, FAIL, "unable to protect symbol table node"); } @@ -1013,7 +906,6 @@ H5G_node_list (H5F_t *f, const haddr_t *addr, void *_udata) */ if (bt_udata->entry) { for (i=0; i<sn->nsyms && bt_udata->nsyms+i<bt_udata->maxentries; i++) { - H5G_shadow_sync (sn->entry+i); bt_udata->entry[bt_udata->nsyms+i] = sn->entry[i]; } } @@ -1065,11 +957,10 @@ herr_t H5G_node_debug (H5F_t *f, const haddr_t *addr, FILE *stream, intn indent, intn fwidth, const haddr_t *heap) { - int i, acc; + int i; H5G_node_t *sn = NULL; herr_t status; const char *s; - H5G_ac_ud1_t ac_udata; FUNC_ENTER (H5G_node_debug, FAIL); @@ -1082,23 +973,12 @@ H5G_node_debug (H5F_t *f, const haddr_t *addr, FILE *stream, intn indent, assert (indent>=0); assert (fwidth>=0); - /* - * We have absolutely no idea where the object header for the symbol table - * to which this node belongs is located. In fact, if the file is corrupt, - * there may not even be an object header for that symbol table. So we - * supply UNDEF as the group address which causes no open objects to be - * associated with the node. For that reason, we flush this node from the - * cache when we're done so if some later caller knows the header address - * they'll be able to access the open objects. - */ - H5F_addr_undef (&(ac_udata.grp_addr)); - ac_udata.heap_addr = *heap; /* * If we couldn't load the symbol table node, then try loading the * B-tree node. */ - if (NULL==(sn=H5AC_protect(f, H5AC_SNODE, addr, &ac_udata, NULL))) { + if (NULL==(sn=H5AC_protect(f, H5AC_SNODE, addr, NULL, NULL))) { H5ECLEAR; /*discard that error*/ status = H5B_debug (f, addr, stream, indent, fwidth, H5B_SNODE, NULL); if (status<0) { @@ -1116,11 +996,6 @@ H5G_node_debug (H5F_t *f, const haddr_t *addr, FILE *stream, intn indent, fprintf (stream, "%*s%-*s %d of %d\n", indent, "", fwidth, "Number of Symbols:", sn->nsyms, 2*H5G_NODE_K(f)); - for (i=acc=0; i<sn->nsyms; i++) { - if (sn->entry[i].shadow) acc++; - } - fprintf (stream, "%*s%-*s %d\n", indent, "", fwidth, - "Shadows:", acc); indent += 3; @@ -1134,13 +1009,9 @@ H5G_node_debug (H5F_t *f, const haddr_t *addr, FILE *stream, intn indent, s); } H5G_ent_debug (f, sn->entry+i, stream, indent, fwidth); - fprintf (stream, "%*s%-*s %s\n", indent+3, "", MAX (0, fwidth-3), - "Shadow:", - sn->entry[i].shadow ? "Yes":"No"); } H5AC_unprotect (f, H5AC_SNODE, addr, sn); - H5AC_flush (f, H5AC_SNODE, addr, TRUE); /*see note above*/ FUNC_LEAVE (SUCCEED); } diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h index 473c3c5..5b8bbe5 100644 --- a/src/H5Gpkg.h +++ b/src/H5Gpkg.h @@ -26,21 +26,6 @@ #define H5G_DEFAULT_ROOT_SIZE 32 /* - * A symbol table entry. The two important fields are `name_off' and - * `header'. The remaining fields are used for caching information that - * also appears in the object header to which this symbol table entry - * points. - */ -struct H5G_entry_t { - hbool_t dirty; /*entry out-of-date? */ - size_t name_off; /*offset of name within name heap */ - haddr_t header; /*file address of object header */ - H5G_type_t type; /*type of information cached */ - H5G_cache_t cache; /*cached data from object header */ - H5G_shadow_t *shadow; /*optional ptr to the shadow */ -}; - -/* * A symbol table node is a collection of symbol table entries. It can * be thought of as the lowest level of the B-link tree that points to * a collection of symbol table entries that belong to a specific symbol @@ -53,23 +38,6 @@ typedef struct H5G_node_t { } H5G_node_t; /* - * A shadow is a copy of a symbol table entry which corresponds to an - * `open' object. Shadows are necessary because normal symbol table - * entries can be preempted from the main cache. The `shadow' field - * of the `entry' points to the beginning of the shadow just like the - * shadow field from symbol table entries in H5G_node_t. - */ -struct H5G_shadow_t { - char *name; /*name for this entry */ - haddr_t grp_addr; /*hdr addr for group containing shadow */ - uintn nrefs; /*reference counter */ - H5G_entry_t entry; /*local copy of symbol table entry */ - H5G_entry_t *main; /*main entry in stab node if cached */ - struct H5G_shadow_t *next; /*next shadow for same symbol table */ - struct H5G_shadow_t *prev; /*previous shadow for same symbol table */ -}; - -/* * Each key field of the B-link tree that points to symbol table * nodes consists of this structure... */ @@ -78,13 +46,23 @@ typedef struct H5G_node_key_t { } H5G_node_key_t; /* + * A group handle passed around through layers of the library within and + * above the H5G layer. + */ +struct H5G_t { + H5F_t *file; /*file containing group */ + int nref; /*open reference count */ + H5G_entry_t ent; /*info about the group */ +}; + +/* * Each file has a stack of open groups with the latest entry on the * stack the current working group. If the stack is empty then the * current working group is the root object. */ typedef struct H5G_cwgstk_t { - H5G_entry_t *handle; /*a handle to an open group */ - struct H5G_cwgstk_t *next; /*next item (earlier) on stack */ + H5G_t *grp; /*a handle to an open group */ + struct H5G_cwgstk_t *next; /*next item (earlier) on stack */ } H5G_cwgstk_t; /* @@ -106,16 +84,10 @@ typedef struct H5G_bt_ud1_t { /* downward */ H5G_oper_t operation; /*what operation to perform */ const char *name; /*points to temporary memory */ - haddr_t grp_addr; /*symbol table header address */ haddr_t heap_addr; /*symbol table heap address */ - /* downward for INSERT */ - H5G_entry_t entry; /*entry to insert into table */ - - /* upward for FIND and INSERT */ - haddr_t node_addr; /*address of node for this entry */ - H5G_node_t *node_ptr; /*ptr to the node containing the entry */ - H5G_entry_t *entry_ptr; /*ptr into cached symbol table node */ + /* downward for INSERT, upward for FIND */ + H5G_entry_t ent; /*entry to insert into table */ } H5G_bt_ud1_t; @@ -129,7 +101,6 @@ typedef struct H5G_bt_ud2_t { H5G_entry_t *entry; /*array of entries, alloc'd by caller */ char **name; /*array of string ptrs, allocd by caller*/ intn maxentries; /*size of the ADDR and NAME arrays */ - haddr_t grp_addr; /*symbol table header address */ haddr_t heap_addr; /*heap address */ /* upward */ @@ -142,14 +113,6 @@ typedef struct H5G_bt_ud2_t { */ extern H5B_class_t H5B_SNODE[1]; -/* - * This struct passes information through the H5AC layer. - */ -typedef struct H5G_ac_ud1_t { - haddr_t heap_addr; - haddr_t grp_addr; -} H5G_ac_ud1_t; - /* The cache subclass */ extern const H5AC_class_t H5AC_SNODE[1]; @@ -158,31 +121,15 @@ extern const H5AC_class_t H5AC_SNODE[1]; * functions that understand names are exported to the rest of * the library and appear in H5Gprivate.h. */ -herr_t H5G_stab_create (H5F_t *f, H5G_entry_t *self, size_t init); -H5G_entry_t *H5G_stab_find (H5F_t *f, const haddr_t *addr, H5G_entry_t *self, - const char *name); -H5G_entry_t *H5G_stab_insert (H5F_t *f, H5G_entry_t *self, - const char *name, H5G_entry_t *ent); +herr_t H5G_stab_create (H5F_t *f, size_t size_hint, H5G_entry_t *ent/*out*/); +herr_t H5G_stab_find (H5F_t *f, H5G_entry_t *grp_ent, const char *name, + H5G_entry_t *obj_ent/*out*/); +herr_t H5G_stab_insert (H5F_t *f, H5G_entry_t *grp_ent, const char *name, + H5G_entry_t *obj_ent); intn H5G_stab_list (H5F_t *f, H5G_entry_t *self, intn maxentries, char *names[], H5G_entry_t entries[]); /* - * Functions that understand shadow entries. - */ -herr_t H5G_shadow_sync (H5G_entry_t *ent); -H5G_entry_t *H5G_shadow_open (H5F_t *f, H5G_entry_t *grp, - H5G_entry_t *ent); -herr_t H5G_shadow_close (H5F_t *f, H5G_entry_t *ent); -hbool_t H5G_shadow_p (H5G_entry_t *ent); -herr_t H5G_shadow_dissociate (H5G_entry_t *ent); -herr_t H5G_shadow_assoc_node (H5F_t *f, H5G_node_t *sym, - const H5G_ac_ud1_t *ac_udata); -H5G_shadow_t *H5G_shadow_list (H5F_t *f, const haddr_t *stab_header_addr); -herr_t H5G_shadow_move (H5F_t *f, H5G_shadow_t *shadow, - const char *new_name, H5G_entry_t *new_entry, - const haddr_t *grp_addr); - -/* * Functions that understand symbol table entries. */ herr_t H5G_ent_decode_vec (H5F_t *f, const uint8 **pp, H5G_entry_t *ent, diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h index 6b8989e..0ee5e17 100644 --- a/src/H5Gprivate.h +++ b/src/H5Gprivate.h @@ -24,11 +24,7 @@ #include <H5Fprivate.h> /* - * FEATURE: If this macro is defined then H5G_shadow_check() is occassionally - * (actually, quite often) called to check the consistency of the - * shadow table. If there's something wrong with the table then - * abort() is called. Shadow table checking is a rather expensive - * operation. + * Define this to enable debugging. */ #ifdef NDEBUG # undef H5G_DEBUG @@ -37,7 +33,6 @@ #define H5G_NODE_MAGIC "SNOD" /*symbol table node magic number */ #define H5G_NODE_SIZEOF_MAGIC 4 /*sizeof symbol node magic number */ #define H5G_NO_CHANGE (-1) /*see H5G_ent_modified() */ -#define H5G_NSHADOWS 10331 /*default size of shadow hash table */ /* * The disk size for a symbol table entry... @@ -78,24 +73,33 @@ typedef union H5G_cache_t { } H5G_cache_t; /* - * An H5G_shadow_t is the struct used to describe object headers that - * are currently open for modification. It's contents is not - * important outside H5G. + * A symbol table entry. The two important fields are `name_off' and + * `header'. The remaining fields are used for caching information that + * also appears in the object header to which this symbol table entry + * points. */ -typedef struct H5G_shadow_t H5G_shadow_t; -typedef struct H5G_entry_t H5G_entry_t; +typedef struct H5G_entry_t { + hbool_t dirty; /*entry out-of-date? */ + size_t name_off; /*offset of name within name heap */ + haddr_t header; /*file address of object header */ + H5G_type_t type; /*type of information cached */ + H5G_cache_t cache; /*cached data from object header */ +} H5G_entry_t; + +typedef struct H5G_t H5G_t; /* * Library prototypes... These are the ones that other packages routinely * call. */ -H5G_entry_t *H5G_new (H5F_t *f, const char *name, size_t size_hint); -herr_t H5G_set (H5F_t *f, const char *name); -herr_t H5G_push (H5F_t *f, const char *name); +H5G_t *H5G_create (H5F_t *f, const char *name, size_t size_hint); +H5G_t *H5G_open (H5F_t *f, const char *name); +H5G_t *H5G_reopen (H5G_t *grp); +herr_t H5G_close (H5G_t *grp); +herr_t H5G_set (H5F_t *f, H5G_t *grp); +herr_t H5G_push (H5F_t *f, H5G_t *grp); herr_t H5G_pop (H5F_t *f); -H5G_entry_t *H5G_create (H5F_t *f, const char *name, size_t ohdr_hint); -H5G_entry_t *H5G_open (H5F_t *f, const char *name); -herr_t H5G_close (H5F_t *f, H5G_entry_t *ent); +herr_t H5G_insert (H5F_t *f, const char *name, H5G_entry_t *ent); herr_t H5G_find (H5F_t *f, const char *name, H5G_entry_t *grp_ent, H5G_entry_t *ent); herr_t H5G_ent_encode (H5F_t *f, uint8 **pp, H5G_entry_t *ent); @@ -108,11 +112,6 @@ herr_t H5G_node_debug (H5F_t *f, const haddr_t *addr, FILE *stream, intn indent, intn fwidth, const haddr_t *heap); /* - * These functions operate on shadow entries. - */ -herr_t H5G_shadow_flush (H5F_t *f, hbool_t invalidate); - -/* * These functions operate on symbol table entries. They're used primarily * in the H5O package where header messages are cached in symbol table * entries. The subclasses of H5O probably don't need them though. diff --git a/src/H5Gpublic.h b/src/H5Gpublic.h index e546e6d..2d6b55c 100644 --- a/src/H5Gpublic.h +++ b/src/H5Gpublic.h @@ -27,9 +27,12 @@ extern "C" { #endif -herr_t H5Gnew (hid_t file, const char *name, size_t size_hint); -herr_t H5Gset (hid_t file, const char *name); -herr_t H5Gpush (hid_t file, const char *name); +hid_t H5Gcreate (hid_t file_id, const char *name, size_t size_hint); +hid_t H5Gopen (hid_t file_id, const char *name); +herr_t H5Gclose (hid_t grp_id); + +herr_t H5Gset (hid_t file, hid_t grp_id); +herr_t H5Gpush (hid_t file, hid_t grp_id); herr_t H5Gpop (hid_t file); #ifdef __cplusplus diff --git a/src/H5Gshad.c b/src/H5Gshad.c deleted file mode 100644 index 861f7e5..0000000 --- a/src/H5Gshad.c +++ /dev/null @@ -1,810 +0,0 @@ -/* - * Copyright (C) 1997 National Center for Supercomputing Applications. - * All rights reserved. - * - * Programmer: Robb Matzke <matzke@llnl.gov> - * Thursday, September 18, 1997 - */ -#define H5G_PACKAGE /*suppress error message about including H5Gpkg.h*/ - -#include <H5private.h> /*library */ -#include <H5Eprivate.h> /*error handling */ -#include <H5Gpkg.h> /*symbol tables */ -#include <H5Hprivate.h> /*heap functions */ -#include <H5MMprivate.h> /*memory management */ -#include <H5Oprivate.h> /*object header messages */ - -#define PABLO_MASK H5G_shadow_mask - -/* Interface initialization */ -static hbool_t interface_initialize_g = FALSE; -#define INTERFACE_INIT NULL - -typedef struct H5G_hash_t { - haddr_t grp_addr; - H5G_shadow_t *head; - struct H5G_hash_t *next; - struct H5G_hash_t *prev; -} H5G_hash_t; - - -/*------------------------------------------------------------------------- - * Function: H5G_shadow_check - * - * Purpose: Checks the shadow data structures for validity. This is a - * debugging function only--it aborts on failure! - * - * Return: void - * - * Programmer: Robb Matzke - * Sunday, September 21, 1997 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -#ifdef H5G_DEBUG -static void -H5G_shadow_check (H5F_t *f) -{ - H5G_hash_t *hash=NULL; - H5G_shadow_t *shadow=NULL, *prev_shadow=NULL; - uintn idx; - hbool_t shadow_error=FALSE; - uintn nerrors=0; - static int ncalls=0; - - if (0==ncalls++) { - fprintf (stderr, "HDF5-DIAG: debugging group shadows (expensive)\n"); - } - - for (idx=0; idx<f->shared->nshadows; idx++) { - for (hash=f->shared->shadow[idx]; hash; hash=hash->next) { - for (shadow=hash->head,prev_shadow=NULL; - shadow; - shadow=shadow->next) { - shadow_error = FALSE; - - /* Each shadow has a name and the names are in order */ - if (!shadow->name) { - fprintf (stderr, "name=NULL, "); - shadow_error = TRUE; - } - if (prev_shadow && strcmp (prev_shadow->name, shadow->name)>=0) { - fprintf (stderr, "names not sorted, "); - shadow_error = TRUE; - } - - /* - * Valid group addresses. The root (which is hashed to entry - * zero) always has an undefined group address. - */ - if (idx==0 && - !H5F_addr_defined (&(shadow->grp_addr)) && - !H5F_addr_defined (&(hash->grp_addr))) { - /* - * The shadow for the root object always has an undefined - * group address. - */ - - } else if (!H5F_addr_defined (&(shadow->grp_addr)) || - !H5F_addr_defined (&(hash->grp_addr))) { - /* - * Non-root objects must have defined group addresses. - */ - fprintf (stderr, "grp_addr="); - H5F_addr_print (stderr, &(shadow->grp_addr)); - fprintf (stderr, ", hash_addr="); - H5F_addr_print (stderr, &(hash->grp_addr)); - fprintf (stderr, ", "); - shadow_error = TRUE; - - } else if (H5F_addr_ne (&(shadow->grp_addr), &(hash->grp_addr))) { - /* - * Something's wrong with the data structure. The hash - * address should always be the same as the shadow group - * address. - */ - fprintf (stderr, "grp_addr="); - H5F_addr_print (stderr, &(shadow->grp_addr)); - fprintf (stderr, " (should be "); - H5F_addr_print (stderr, &(hash->grp_addr)); - fprintf (stderr, "), "); - shadow_error = TRUE; - } - - /* Linked to symbol table entry */ - if (shadow->main && shadow!=shadow->main->shadow) { - fprintf (stderr, "entry linkage problem, "); - shadow_error = TRUE; - } - - /* Shadow linked list is consistent */ - if (shadow->prev && prev_shadow!=shadow->prev) { - fprintf (stderr, "shadow linked list problem, "); - shadow_error = TRUE; - } - prev_shadow = shadow; - - /* If an error occurred then print other info */ - if (shadow_error) { - fprintf (stderr, "idx=%u, shadow=0x%08lx, grp_addr=", - idx, (unsigned long)shadow); - H5F_addr_print (stderr, &(shadow->grp_addr)); - fprintf (stderr, "\n"); - nerrors++; - } - } - } - } - if (nerrors) { - fprintf (stderr, "Error in H5G_shadow_check, call %d\n", ncalls); - abort (); - } -} -#endif - - -/*------------------------------------------------------------------------- - * Function: H5G_shadow_p - * - * Purpose: Determines if ENT is a shadow or a real symbol table entry. - * - * Return: Success: Non-zero if ENT is a shadow; zero otherwise. - * - * Failure: FALSE - * - * Programmer: Robb Matzke - * Thursday, September 18, 1997 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -hbool_t -H5G_shadow_p (H5G_entry_t *ent) -{ - H5G_shadow_t tmp; - size_t delta = (char*)&(tmp.entry) - (char*)&tmp; - hbool_t ret_value = FALSE; - - FUNC_ENTER (H5G_shadow_p, FALSE); - - if (!ent || !ent->shadow) return FALSE; - ret_value = ((char*)ent - (char*)(ent->shadow) == delta); - - FUNC_LEAVE (ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5G_shadow_dissociate - * - * Purpose: Removes the association between a shadow and its entry or an - * entry and its shadow. The ENT argument can be a shadow or a - * cached entry. - * - * Return: Success: SUCCEED - * - * Failure: FAIL - * - * Programmer: Robb Matzke - * Thursday, September 18, 1997 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5G_shadow_dissociate (H5G_entry_t *ent) -{ - FUNC_ENTER (H5G_shadow_dissociate, FAIL); - - if (H5G_shadow_p (ent)) { - if (ent->shadow->main) { - ent->shadow->main->shadow = NULL; - ent->shadow->main = NULL; - } - } else if (ent && ent->shadow) { - ent->shadow->main = NULL; - ent->shadow = NULL; - } - - FUNC_LEAVE (SUCCEED); -} - - -/*------------------------------------------------------------------------- - * Function: H5G_shadow_sync - * - * Purpose: Synchronizes a shadow with an entry by copying the - * shadow contents to the entry if the shadow is dirty, - * and then clearing the shadow dirty bit. You may call this - * function with either a shadow or a real entry. - * - * If ENT is a shadow, then the shadow is synchronized only if - * the entry is currently cached. - * - * Return: Success: SUCCEED - * - * Failure: FAIL - * - * Programmer: Robb Matzke - * Thursday, September 18, 1997 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5G_shadow_sync (H5G_entry_t *ent) -{ - H5G_shadow_t *shadow = NULL; - FUNC_ENTER (H5G_shadow_sync, FAIL); - - /* - * If the caller supplied us with a shadow instead of the main entry, then - * adjust the arguments. - */ - if (H5G_shadow_p (ent)) { - shadow = ent->shadow; - ent = shadow->main; - } else { - shadow = ent->shadow; - } - - if (shadow && shadow->entry.dirty) { - if (!ent) { - HRETURN_ERROR (H5E_SYM, H5E_NOTCACHED, FAIL, - "main entry is not cached"); - } - *ent = shadow->entry; - shadow->entry.dirty = FALSE; - } - FUNC_LEAVE (SUCCEED); -} - - -/*------------------------------------------------------------------------- - * Function: H5G_shadow_list - * - * Purpose: Returns a doubly linked list of shadows for the symbol - * table whose header address is GRP_ADDR. - * - * Return: Success: Ptr shadow list or null. - * - * Failure: NULL - * - * Programmer: Robb Matzke - * Wednesday, September 17, 1997 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -H5G_shadow_t * -H5G_shadow_list (H5F_t *f, const haddr_t *grp_addr) -{ - uintn idx = H5F_addr_hash (grp_addr, f->shared->nshadows); - H5G_hash_t *bucket = NULL; - - FUNC_ENTER (H5G_shadows, NULL); - - for (bucket=f->shared->shadow[idx]; bucket; bucket=bucket->next) { - if (0==idx && - !H5F_addr_defined (&(bucket->grp_addr)) && - !H5F_addr_defined (grp_addr)) { - HRETURN (bucket->head);/*shadow list for root object*/ - } else if (H5F_addr_eq (&(bucket->grp_addr), grp_addr)) { - HRETURN (bucket->head);/*shadow list for other objects*/ - } - } - FUNC_LEAVE (NULL); -} - - -/*------------------------------------------------------------------------- - * Function: H5G_shadow_assoc_node - * - * Purpose: Given a new symbol table node and a symbol table header - * address, associate entries in that node with their shadow if - * they have one. - * - * SYM must be an uncached or protected symbol table node. - * - * Return: Success: SUCCEED - * - * Failure: FAIL, if an error occurs then none of the - * entries are associated with shadows. - * - * Programmer: Robb Matzke - * Wednesday, September 17, 1997 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5G_shadow_assoc_node (H5F_t *f, H5G_node_t *sym, const H5G_ac_ud1_t *ac_udata) -{ - H5G_shadow_t *shadow = NULL; - const char *s = NULL; - intn i = 0; - haddr_t heap_addr; - - FUNC_ENTER (H5G_shadow_assoc_node, FAIL); - - /* Check arguments */ - assert (f); /* The file */ - assert (sym); /* The symbol table node */ - assert (ac_udata); /* The symbol table header info */ - -#ifdef H5G_DEBUG - H5G_shadow_check (f); -#endif - - if ((shadow=H5G_shadow_list (f, &(ac_udata->grp_addr)))) { - heap_addr = ac_udata->heap_addr; - - while (i<sym->nsyms && shadow) { - /* Advance the Entry ptr until it gets to the next shadow. */ - while (i<sym->nsyms && - (s=H5H_peek (f, &heap_addr, sym->entry[i].name_off)) && - strcmp (s, shadow->name)<0) i++; - - /* Advance the Shadow ptr until it gets to the next entry. */ - while (i<sym->nsyms && s && shadow && - strcmp (s, shadow->name)>0) shadow = shadow->next; - - /* Did we find a match? */ - if (i<sym->nsyms && s && shadow && !strcmp (s, shadow->name)) { - shadow->main = sym->entry + i; - sym->entry[i].shadow = shadow; - i++; - shadow = shadow->next; - } - } - } - - FUNC_LEAVE (SUCCEED); -} - - -/*------------------------------------------------------------------------- - * Function: H5G_shadow_open - * - * Purpose: Given a handle to an already open object, or given a - * pointer to the cached symbol table entry for that - * object, open the object (again) and return a handle - * to it. - * - * If ENT refers to the root object, then GRP can be a null - * pointer or a pointer to an entry with an invalid header - * address. - * - * Return: Success: Handle to open object - * - * Failure: NULL - * - * Programmer: Robb Matzke - * Thursday, September 18, 1997 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -H5G_entry_t * -H5G_shadow_open (H5F_t *f, H5G_entry_t *grp, H5G_entry_t *ent) -{ - H5G_shadow_t *shadow = NULL; - H5O_stab_t stab; - const char *s = NULL; - H5G_hash_t *hash = NULL; - H5G_shadow_t *hash_ent = NULL, *prev_ent = NULL; - uintn idx; - H5O_name_t name_mesg = {NULL}; - H5G_entry_t *ret_value = NULL; - haddr_t grp_header; - - FUNC_ENTER (H5G_shadow_open, NULL); - - /* check args */ - assert (f); - assert (ent); - - if ((shadow = ent->shadow)) { - /* Object is already open. Open it again */ - shadow->nrefs += 1; - HRETURN (&(shadow->entry)); - } - - /* - * If the root object is being opened then the GRP argument is optional. - * If it's supplied then it had better have an undefined header address. - * For all other objects the GRP argument is required to have a valid - * header address. - */ - if (ent==f->shared->root_sym) { - assert (!grp || !H5F_addr_defined (&(grp->header))); - H5F_addr_undef (&grp_header); - idx = 0; - } else { - assert (grp && H5F_addr_defined (&(grp->header))); - grp_header = grp->header; - idx = H5F_addr_hash (&grp_header, f->shared->nshadows); - } - - /* - * Build the new shadow. - */ - shadow = H5MM_xcalloc (1, sizeof(H5G_shadow_t)); - ent->shadow = shadow; - shadow->main = ent; - shadow->nrefs = 1; - shadow->entry = *ent; - shadow->entry.dirty = FALSE; - shadow->grp_addr = grp_header; - - /* - * Give the shadow a name. Obtaining the name might remove ENT from the - * cache, so we're careful not to reference it again. - */ - if (ent==f->shared->root_sym) { - /* - * We're opening the root entry. Get the name from the name message or - * use a generic default. - */ - if (H5O_read (f, NO_ADDR, ent, H5O_NAME, 0, &name_mesg)) { - shadow->name = H5MM_xstrdup (name_mesg.s); - H5O_reset (H5O_NAME, &name_mesg); - } else { - shadow->name = H5MM_xstrdup ("Root Object"); - } - - } else { - /* - * Some entry other than the root. - */ - if (NULL==H5O_read (f, NO_ADDR, grp, H5O_STAB, 0, &stab)) { - HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, NULL, - "unable to read symbol table object header message"); - } - if (NULL==(s=H5H_peek (f, &(stab.heap_addr), ent->name_off))) { - HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, NULL, - "unable to read symbol name"); - } - shadow->name = H5MM_xstrdup (s); - } - ent = NULL; /*previous ops might have invalidated it*/ - - - /* - * Link it into the shadow heap - */ - for (hash=f->shared->shadow[idx]; hash; hash=hash->next) { - if (0==idx && - !H5F_addr_defined (&(hash->grp_addr)) && - !H5F_addr_defined (&grp_header)) { - break; /*shadow list for root object*/ - } else if (H5F_addr_eq (&(hash->grp_addr), &grp_header)) { - break; /*shadow list for other objects*/ - } - } - if (!hash) { - hash = H5MM_xcalloc (1, sizeof(H5G_hash_t)); - hash->grp_addr = grp_header; - hash->next = f->shared->shadow[idx]; - f->shared->shadow[idx] = hash; - if (hash->next) hash->next->prev = hash; - } - if (hash->head) { - for (hash_ent=hash->head,prev_ent=NULL; - hash_ent; - hash_ent=hash_ent->next) { - if (strcmp (shadow->name, hash_ent->name)<0) break; - prev_ent = hash_ent; - } - if (hash_ent) { - /* Insert SHADOW before HASH_ENT */ - if (hash_ent->prev) hash_ent->prev->next = shadow; - else hash->head = shadow; - shadow->prev = hash_ent->prev; - shadow->next = hash_ent; - hash_ent->prev = shadow; - } else { - /* Append SHADOW to list */ - assert (prev_ent && NULL==prev_ent->next); - prev_ent->next = shadow; - shadow->prev = prev_ent; - } - } else { - /* Insert shadow at head of list */ - shadow->next = hash->head; - if (hash->head) hash->head->prev = shadow; - hash->head = shadow; - } - -#ifdef H5G_DEBUG - H5G_shadow_check (f); -#endif - - ret_value = &(shadow->entry); - - done: - if (!ret_value) { - if (shadow) { - H5MM_xfree (shadow->name); - H5MM_xfree (shadow); - } - } - - FUNC_LEAVE (ret_value); -} - - - -/*------------------------------------------------------------------------- - * Function: H5G_shadow_close - * - * Purpose: Closes an open object. - * - * Return: Success: SUCCEED - * - * Failure: FAIL - * - * Programmer: Robb Matzke - * Thursday, September 18, 1997 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5G_shadow_close (H5F_t *f, H5G_entry_t *ent) -{ - uintn idx; - H5G_hash_t *hash=NULL; - H5G_shadow_t *hash_ent=NULL, *shadow=NULL; - - FUNC_ENTER (H5G_shadow_close, FAIL); - - /* check args */ - assert (ent); - assert (H5G_shadow_p (ent)); - assert (ent->shadow->nrefs>0); - shadow = ent->shadow; - - /* clean the shadow */ - if (1==shadow->nrefs && ent->dirty) { - if (!shadow->main && - NULL==H5G_stab_find (f, &(shadow->grp_addr), NULL, shadow->name)) { - HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, - "unable to find shadow name in symbol table"); - } - assert (shadow->main); - *(shadow->main) = *ent; - ent->dirty = FALSE; - } - - /* close */ - shadow->nrefs -= 1; - - if (0==shadow->nrefs) { - /* dissociate shadow and entry */ - H5G_shadow_dissociate (ent); - - /* - * find symtabs shadow list -- if this is a shadow of the root object - * then use zero for the hash value. The root object always has an - * undefined group address. - */ - if (H5F_addr_defined (&(shadow->grp_addr))) { - idx = H5F_addr_hash (&(shadow->grp_addr), f->shared->nshadows); - } else { - idx = 0; - } - for (hash=f->shared->shadow[idx]; hash; hash=hash->next) { - if (0==idx && - !H5F_addr_defined (&(hash->grp_addr)) && - !H5F_addr_defined (&(shadow->grp_addr))) { - break; /*shadow list for root object*/ - } else if (H5F_addr_eq (&(hash->grp_addr), &(shadow->grp_addr))) { - break; /*shadow list for other objects*/ - } - } - assert (hash); - - /* find shadow in shadow list */ - for (hash_ent=hash->head; hash_ent; hash_ent=hash_ent->next) { - if (hash_ent==shadow) break; - } - assert (hash_ent); - - /* remove shadow from shadow list */ - if (hash_ent->prev) hash_ent->prev->next = hash_ent->next; - else hash->head = hash_ent->next; - if (hash_ent->next) hash_ent->next->prev = hash_ent->prev; - H5MM_xfree (shadow->name); - H5MM_xfree (shadow); - - /* remove symtab's shadow list if empty */ - if (!hash->head) { - if (hash->prev) hash->prev->next = hash->next; - else f->shared->shadow[idx] = hash->next; - if (hash->next) hash->next->prev = hash->prev; - H5MM_xfree (hash); - } - } - - FUNC_LEAVE (SUCCEED); -} - - - -/*------------------------------------------------------------------------- - * Function: H5G_shadow_move - * - * Purpose: Moves the SHADOW for some entry to correspond to a - * NEW_ENTRY. The GRP_ADDR is the address for the group - * which contains NEW_ENTRY. - * - * Return: Success: SUCCEED - * - * Failure: FAIL - * - * Programmer: Robb Matzke - * Friday, September 19, 1997 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5G_shadow_move (H5F_t *f, H5G_shadow_t *shadow, const char *new_name, - H5G_entry_t *new_entry, const haddr_t *grp_addr) -{ - H5G_hash_t *hash; - uintn idx; - - FUNC_ENTER (H5G_shadow_move, FAIL); - - assert (shadow); - assert (new_entry); - assert (grp_addr && H5F_addr_defined (grp_addr)); - - if (!H5F_addr_defined (&(shadow->grp_addr))) { - /* - * We're moving the shadow for the root object. This simplifies things - * greatly since it implies that this is the only shadow currently - * defined for the entire file. - */ - idx = H5F_addr_hash (grp_addr, f->shared->nshadows); - assert (NULL==f->shared->shadow[idx]); /*Nothing at new idx... */ - hash = f->shared->shadow[0]; - assert (hash); /*..but root idx has something. */ - assert (!H5F_addr_defined (&(hash->grp_addr)));/*..it's the root obj*/ - assert (NULL==hash->next); /*..and just that */ - assert (hash->head==shadow); /*..and exactly that */ - - /* Move root entry to new hash bucket */ - f->shared->shadow[idx] = hash; - f->shared->shadow[0] = NULL; - hash->grp_addr = *grp_addr; - - /* Associate SHADOW with NEW_ENTRY */ - shadow->grp_addr = *grp_addr; - shadow->main = new_entry; - new_entry->shadow = shadow; - - /* Give the shadow a new name */ - H5MM_xfree (shadow->name); - shadow->name = H5MM_xstrdup (new_name); - - } else { - /* - * Other shadows never move. - */ - assert (H5F_addr_eq (&(shadow->grp_addr), grp_addr)); - shadow->main = new_entry; - new_entry->shadow = shadow; - } - - FUNC_LEAVE (SUCCEED); -} - - - -/*------------------------------------------------------------------------- - * Function: H5G_shadow_flush - * - * Purpose: Flush all open object information to the main cache. - * - * Return: Success: SUCCEED - * - * Failure: FAIL if INVALIDATE is non-zero and there are - * open objects. - * - * Programmer: Robb Matzke - * Friday, September 19, 1997 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5G_shadow_flush (H5F_t *f, hbool_t invalidate) -{ - uintn idx; - H5G_hash_t *hash = NULL; - H5G_shadow_t *shadow = NULL; - intn nfound=0; - - FUNC_ENTER (H5G_shadow_flush, FAIL); - - for (idx=0; idx<f->shared->nshadows; idx++) { - for (hash=f->shared->shadow[idx]; hash; hash=hash->next) { - for (shadow=hash->head; shadow; shadow=shadow->next) { - /* - * If the shadow is dirty, then transfer the shadow info to the - * symbol table node. - */ - if (shadow->entry.dirty) { - if (0==idx && !H5F_addr_defined (&(shadow->grp_addr)) && - shadow->main==f->shared->root_sym) { - /* - * The shadow for the root entry gets copied back into the - * root symbol - */ - *f->shared->root_sym = shadow->entry; - } else { - /* - * Other shadows get copied back into the symbol table. - */ - if (!shadow->main && - NULL==H5G_stab_find (f, &(shadow->grp_addr), NULL, - shadow->name)) { - HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, - "unable to find shadow name in symbol " - "table"); - } - assert (shadow->main); - *(shadow->main) = shadow->entry; - shadow->entry.dirty = FALSE; - nfound++; - } - } -#ifndef NDEBUG - /* - * This is usually a bad thing--an hdf5 programmer forgot to close - * some object before closing the file. Since this is hard to - * debug, we'll be nice and print the names here. We don't know - * the full name, but we'll print the relative file address - * of the object header for the group that contains the open - * object. - */ - if (invalidate) { - fprintf (stderr, "HDF5-DIAG: warning: open object <"); - H5F_addr_print (stderr, &(shadow->grp_addr)); - fprintf (stderr, ">/%s", shadow->name); - if (shadow->nrefs>1) { - fprintf (stderr, " (%d times)", shadow->nrefs); - } - fputc ('\n', stderr); - } -#endif - } - } - } - - if (invalidate && nfound) { - /* - * No clean easy way to do this, just leak the memory. If we free a - * shadow and then something else tries to access it (perhaps to close - * it) then they trample on freed memory. - */ - HRETURN_ERROR (H5E_SYM, H5E_UNSUPPORTED, FAIL, - "leaking memory due to shadow errors"); - } - - FUNC_LEAVE (SUCCEED); -} diff --git a/src/H5Gstab.c b/src/H5Gstab.c index a607e5e..1cf36ec 100644 --- a/src/H5Gstab.c +++ b/src/H5Gstab.c @@ -26,21 +26,14 @@ static hbool_t interface_initialize_g = FALSE; * * Purpose: Creates a new empty symbol table (object header, name heap, * and B-tree). The caller can specify an initial size for the - * name heap. + * name heap. The object header of the group is opened for + * write access. * * In order for the B-tree to operate correctly, the first * item in the heap is the empty string, and must appear at * heap offset zero. * * Errors: - * INTERNAL CANTINIT B-tree's won't work if the first - * name isn't at the beginning of the - * heap. - * SYM CANTINIT Can't create B-tree. - * SYM CANTINIT Can't create header. - * SYM CANTINIT Can't create heap. - * SYM CANTINIT Can't create message. - * SYM CANTINIT Can't initialize heap. * * Return: Success: SUCCEED * @@ -55,10 +48,9 @@ static hbool_t interface_initialize_g = FALSE; *------------------------------------------------------------------------- */ herr_t -H5G_stab_create (H5F_t *f, H5G_entry_t *self, size_t init) +H5G_stab_create (H5F_t *f, size_t init, H5G_entry_t *self/*out*/) { size_t name; /*offset of "" name */ - haddr_t addr; /*object header address */ H5O_stab_t stab; /*symbol table message */ FUNC_ENTER (H5G_stab_create, FAIL); @@ -77,14 +69,11 @@ H5G_stab_create (H5F_t *f, H5G_entry_t *self, size_t init) if ((name = H5H_insert (f, &(stab.heap_addr), 1, "")<0)) { HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, "can't initialize heap"); } - if (0!=name) { - /* - * B-tree's won't work if the first name isn't at the beginning - * of the heap. - */ - HRETURN_ERROR (H5E_INTERNAL, H5E_CANTINIT, FAIL, - "internal error (heap doesn't begin at zero)"); - } + /* + * B-tree's won't work if the first name isn't at the beginning + * of the heap. + */ + assert (0==name); /* Create the B-tree */ if (H5B_create (f, H5B_SNODE, NULL, &(stab.btree_addr)/*out*/)<0) { @@ -96,14 +85,13 @@ H5G_stab_create (H5F_t *f, H5G_entry_t *self, size_t init) * since nothing refers to it yet. The link count will be * incremented if the object is added to the group directed graph. */ - if (H5O_create (f, 0, 4+2*H5F_SIZEOF_ADDR(f), &addr/*out*/)<0) { + if (H5O_create (f, 4+2*H5F_SIZEOF_ADDR(f), self/*out*/)<0) { HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, "can't create header"); } /* insert the symbol table message */ - memset (self, 0, sizeof(H5G_entry_t)); - self->header = addr; - if (H5O_modify(f, NO_ADDR, self, H5O_STAB, H5O_NEW_MESG, &stab)<0) { + if (H5O_modify (f, self, H5O_STAB, H5O_NEW_MESG, &stab)<0) { + H5O_close (f, self); HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, "can't create message"); } @@ -115,23 +103,14 @@ H5G_stab_create (H5F_t *f, H5G_entry_t *self, size_t init) * Function: H5G_stab_find * * Purpose: Finds a symbol named NAME in the symbol table whose - * description is stored in SELF in file F and returns a - * pointer to the symbol table entry. SELF is optional if the - * symbol table address is supplied through ADDR. + * description is stored in GRP_ENT in file F and returns its + * symbol table entry through OBJ_ENT (which is optional). * * Errors: - * SYM BADMESG Can't read message. - * SYM NOTFOUND Not found. * - * Return: Success: Pointer to the symbol table entry. - * The pointer is intended for immediate - * read-only access since it points - * directly to an entry in a cached - * symbol table node. The pointer is - * guaranteed to be valid only until the - * next call to one of the H5AC functions. + * Return: Success: SUCCEED * - * Failure: NULL + * Failure: FAIL * * Programmer: Robb Matzke * matzke@llnl.gov @@ -141,75 +120,50 @@ H5G_stab_create (H5F_t *f, H5G_entry_t *self, size_t init) * *------------------------------------------------------------------------- */ -H5G_entry_t * -H5G_stab_find (H5F_t *f, const haddr_t *addr, H5G_entry_t *self, - const char *name) +herr_t +H5G_stab_find (H5F_t *f, H5G_entry_t *grp_ent, const char *name, + H5G_entry_t *obj_ent/*out*/) { H5G_bt_ud1_t udata; /*data to pass through B-tree */ H5O_stab_t stab; /*symbol table message */ - FUNC_ENTER (H5G_stab_find, NULL); + FUNC_ENTER (H5G_stab_find, FAIL); /* Check arguments */ assert (f); - assert (!addr || H5F_addr_defined (addr)); - if (!addr && (!self || !H5F_addr_defined (&(self->header)))) { - HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL, "bad address"); - } - if (!name || !*name) { - HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL, "no name"); - } - if (!addr) addr = &(self->header); + assert (grp_ent); + assert (name && *name); /* set up the udata */ - if (NULL==H5O_read (f, addr, self, H5O_STAB, 0, &stab)) { - HRETURN_ERROR (H5E_SYM, H5E_BADMESG, NULL, "can't read message"); + if (NULL==H5O_read (f, grp_ent, H5O_STAB, 0, &stab)) { + HRETURN_ERROR (H5E_SYM, H5E_BADMESG, FAIL, "can't read message"); } udata.operation = H5G_OPER_FIND; udata.name = name; udata.heap_addr = stab.heap_addr; - udata.grp_addr = *addr; - udata.node_ptr = NULL; /* search the B-tree */ if (H5B_find (f, H5B_SNODE, &(stab.btree_addr), &udata)<0) { - if (udata.node_ptr) { - H5AC_unprotect (f, H5AC_SNODE, &(udata.node_addr), udata.node_ptr); - } - HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL, "not found"); - } - - /* Unprotect the symbol table node */ - if (udata.node_ptr) { - if (H5AC_unprotect (f, H5AC_SNODE, &(udata.node_addr), - udata.node_ptr)<0) { - HRETURN_ERROR (H5E_SYM, H5E_PROTECT, NULL, - "unable to release symbol table node"); - } + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "not found"); } - /* return the result */ - FUNC_LEAVE (udata.entry_ptr); + if (obj_ent) *obj_ent = udata.ent; + FUNC_LEAVE (SUCCEED); } /*------------------------------------------------------------------------- * Function: H5G_stab_insert * - * Purpose: Insert a new symbol into the table described by SELF in + * Purpose: Insert a new symbol into the table described by GRP_ENT in * file F. The name of the new symbol is NAME and its symbol - * table entry is ENT. + * table entry is OBJ_ENT. * * Errors: - * SYM BADMESG Can't read message. - * SYM CANTINSERT Can't insert entry. * - * Return: Success: Pointer to the cached symbol table entry. - * This is a pointer directly into a symbol - * table node and will become invalid on the - * next call to the H5AC package. + * Return: Success: SUCCEED * - * Failure: NULL + * Failure: FAIL * * Programmer: Robb Matzke * matzke@llnl.gov @@ -217,61 +171,41 @@ H5G_stab_find (H5F_t *f, const haddr_t *addr, H5G_entry_t *self, * * Modifications: * - * Robb Matzke, 18 Sep 1997 - * If ENT has a shadow, then the shadow will be associated with the - * entry when it is added to the symbol table. - * *------------------------------------------------------------------------- */ -H5G_entry_t * -H5G_stab_insert (H5F_t *f, H5G_entry_t *self, const char *name, - H5G_entry_t *ent) +herr_t +H5G_stab_insert (H5F_t *f, H5G_entry_t *grp_ent, const char *name, + H5G_entry_t *obj_ent) { H5O_stab_t stab; /*symbol table message */ H5G_bt_ud1_t udata; /*data to pass through B-tree */ - FUNC_ENTER (H5G_stab_insert, NULL); + FUNC_ENTER (H5G_stab_insert, FAIL); /* check arguments */ assert (f); - assert (self && H5F_addr_defined (&(self->header))); + assert (grp_ent && H5F_addr_defined (&(grp_ent->header))); assert (name && *name); - assert (ent); + assert (obj_ent && H5F_addr_defined (&(obj_ent->header))); /* initialize data to pass through B-tree */ - if (NULL==H5O_read (f, &(self->header), self, H5O_STAB, 0, &stab)) { - HRETURN_ERROR (H5E_SYM, H5E_BADMESG, NULL, "can't read message"); + if (NULL==H5O_read (f, grp_ent, H5O_STAB, 0, &stab)) { + HRETURN_ERROR (H5E_SYM, H5E_BADMESG, FAIL, "not a symbol table"); } udata.operation = H5G_OPER_INSERT; udata.name = name; udata.heap_addr = stab.heap_addr; - udata.grp_addr = self->header; - udata.entry = *ent; - udata.entry.name_off = -1; - udata.node_ptr = NULL; + udata.ent = *obj_ent; /* insert */ if (H5B_insert (f, H5B_SNODE, &(stab.btree_addr), &udata)<0) { - if (udata.node_ptr) { - H5AC_unprotect (f, H5AC_SNODE, &(udata.node_addr), udata.node_ptr); - } - HRETURN_ERROR (H5E_SYM, H5E_CANTINSERT, NULL, "can't insert entry"); + HRETURN_ERROR (H5E_SYM, H5E_CANTINSERT, FAIL, "can't insert entry"); } - /* - * The H5G_node_insert() called H5AC_protect() for the node so that the - * udata.entry_ptr field didn't become invalid on the way back out of the - * B-tree code. We unprotect it now, but the pointer will remain valid - * until the next call to H5AC. - */ - if (H5AC_unprotect (f, H5AC_SNODE, &(udata.node_addr), udata.node_ptr)<0) { - HRETURN_ERROR (H5E_SYM, H5E_PROTECT, NULL, "can't unprotect"); - } - /* update the name offset in the entry */ - ent->name_off = udata.entry.name_off; - FUNC_LEAVE (udata.entry_ptr); + obj_ent->name_off = udata.ent.name_off; + FUNC_LEAVE (SUCCEED); } @@ -307,7 +241,7 @@ H5G_stab_insert (H5F_t *f, H5G_entry_t *self, const char *name, *------------------------------------------------------------------------- */ intn -H5G_stab_list (H5F_t *f, H5G_entry_t *self, intn maxentries, +H5G_stab_list (H5F_t *f, H5G_entry_t *grp_ent, intn maxentries, char *names[], H5G_entry_t entries[]) { H5G_bt_ud2_t udata; @@ -318,16 +252,15 @@ H5G_stab_list (H5F_t *f, H5G_entry_t *self, intn maxentries, /* check args */ assert (f); - assert (self && H5F_addr_defined (&(self->header))); + assert (grp_ent && H5F_addr_defined (&(grp_ent->header))); assert (maxentries>=0); /* initialize data to pass through B-tree */ - if (NULL==H5O_read (f, &(self->header), self, H5O_STAB, 0, &stab)) { + if (NULL==H5O_read (f, grp_ent, H5O_STAB, 0, &stab)) { HRETURN_ERROR (H5E_SYM, H5E_BADMESG, FAIL, "not a symbol table"); } udata.entry = entries; udata.name = names; - udata.grp_addr = self->header; udata.heap_addr = stab.heap_addr; udata.maxentries = maxentries; udata.nsyms = 0; @@ -74,10 +74,13 @@ static const H5O_class_t *const message_type_g[] = { * Function: H5O_create * * Purpose: Creates a new object header, sets the link count - * to NLINK, and caches the header. + * to 0, and caches the header. The object header is opened for + * write access and should eventually be closed by calling + * H5O_close(). * - * Return: Success: SUCCEED, the address of new header is - * returned through the ADDR argument. + * Return: Success: SUCCEED, the ENT argument contains + * information about the object header, + * including its address. * * Failure: FAIL * @@ -90,7 +93,7 @@ static const H5O_class_t *const message_type_g[] = { *------------------------------------------------------------------------- */ herr_t -H5O_create (H5F_t *f, intn nlink, size_t size_hint, haddr_t *addr/*out*/) +H5O_create (H5F_t *f, size_t size_hint, H5G_entry_t *ent/*out*/) { size_t size; /*total size of object header */ H5O_t *oh = NULL; @@ -100,14 +103,14 @@ H5O_create (H5F_t *f, intn nlink, size_t size_hint, haddr_t *addr/*out*/) /* check args */ assert (f); - assert (nlink>=0); - assert (addr); + assert (ent); + HDmemset (ent, 0, sizeof(H5G_entry_t)); if (size_hint<H5O_MIN_SIZE) size_hint = H5O_MIN_SIZE; H5O_ALIGN (size_hint, H5O_ALIGNMENT); /* allocate disk space for header and first chunk */ size = H5O_SIZEOF_HDR(f) + size_hint; - if (H5MF_alloc (f, H5MF_META, size, addr/*out*/)<0) { + if (H5MF_alloc (f, H5MF_META, size, &(ent->header)/*out*/)<0) { HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate file space for object header hdr"); } @@ -117,14 +120,14 @@ H5O_create (H5F_t *f, intn nlink, size_t size_hint, haddr_t *addr/*out*/) oh->dirty = TRUE; oh->version = H5O_VERSION; oh->alignment = H5O_ALIGNMENT; - oh->nlink = nlink; + oh->nlink = 0; /* create the chunk list and initialize the first chunk */ oh->nchunks = 1; oh->alloc_nchunks = H5O_NCHUNKS; oh->chunk = H5MM_xmalloc (oh->alloc_nchunks * sizeof (H5O_chunk_t)); - tmp_addr = *addr; + tmp_addr = ent->header; H5F_addr_inc (&tmp_addr, H5O_SIZEOF_HDR (f)); oh->chunk[0].dirty = TRUE; oh->chunk[0].addr = tmp_addr; @@ -144,12 +147,82 @@ H5O_create (H5F_t *f, intn nlink, size_t size_hint, haddr_t *addr/*out*/) oh->mesg[0].chunkno = 0; /* cache it */ - if (H5AC_set (f, H5AC_OHDR, addr, oh)<0) { + if (H5AC_set (f, H5AC_OHDR, &(ent->header), oh)<0) { H5MM_xfree (oh); HRETURN_ERROR (H5E_OHDR, H5E_CANTINIT, FAIL, "unable to cache object header"); } + /* open it */ + if (H5O_open (f, ent)<0) { + HRETURN_ERROR (H5E_OHDR, H5E_CANTOPENOBJ, FAIL, + "unable to open object header"); + } + + FUNC_LEAVE (SUCCEED); +} + + +/*------------------------------------------------------------------------- + * Function: H5O_open + * + * Purpose: Opens an object header which is described by the symbol table + * entry OBJ_ENT. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Monday, January 5, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_open (H5F_t *f, H5G_entry_t *obj_ent) +{ + FUNC_ENTER (H5O_open, FAIL); + + /* + * There is nothing to do here now. Opening an object header should + * eventually do something to prevent the object header from being deleted, + * but since object deletion isn't implemented yet, we don't care. + */ + + FUNC_LEAVE (SUCCEED); +} + + +/*------------------------------------------------------------------------- + * Function: H5O_close + * + * Purpose: Closes an object header that was previously open. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Monday, January 5, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_close (H5F_t *f, H5G_entry_t *obj_ent) +{ + FUNC_ENTER (H5O_close, FAIL); + + /* + * There is nothing to do here now. See H5O_open(). Eventually this + * function will free resources if the object header hard link count is + * zero and this was the last oustanding open for the object. Since + * object deletion isn't implemented yet, we don't care. + */ + FUNC_LEAVE (SUCCEED); } @@ -590,52 +663,40 @@ H5O_link (H5F_t *f, H5G_entry_t *ent, intn adjust) *------------------------------------------------------------------------- */ void * -H5O_read (H5F_t *f, const haddr_t *addr, H5G_entry_t *ent, - const H5O_class_t *type, intn sequence, void *mesg) +H5O_read (H5F_t *f, H5G_entry_t *ent, const H5O_class_t *type, + intn sequence, void *mesg) { H5O_t *oh = NULL; void *retval = NULL; intn idx; H5G_cache_t *cache = NULL; H5G_type_t cache_type; - haddr_t _addr; FUNC_ENTER (H5O_read, NULL); /* check args */ assert (f); - if (!addr) { - if (!ent || H5G_ent_addr (ent, &_addr/*out*/)) { - HRETURN_ERROR (H5E_OHDR, H5E_NOTFOUND, NULL, - "invalid symbol table entry"); - } - addr = &_addr; - } - assert (H5F_addr_defined (addr)); + assert (ent); + assert (H5F_addr_defined (&(ent->header))); + assert (type); assert (sequence>=0); /* can we get it from the symbol table? */ - if (ent) { - cache = H5G_ent_cache (ent, &cache_type); - if (type && cache_type==type->cache_type && type->fast) { - retval = (type->fast)(cache, mesg); - if (retval) HRETURN (retval); - H5ECLEAR; - } + cache = H5G_ent_cache (ent, &cache_type); + if (type && cache_type==type->cache_type && type->fast) { + retval = (type->fast)(cache, mesg); + if (retval) HRETURN (retval); + H5ECLEAR; } /* can we get it from the object header? */ - if ((idx = H5O_find_in_ohdr (f, addr, &type, sequence))<0) { + if ((idx = H5O_find_in_ohdr (f, &(ent->header), &type, sequence))<0) { HRETURN_ERROR (H5E_OHDR, H5E_NOTFOUND, NULL, "unable to find message in object header"); } -#ifdef LATER - /* should we cache it in ENT? */ -#endif - /* copy the message to the user-supplied buffer */ - if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL, NULL))) { + if (NULL==(oh=H5AC_find (f, H5AC_OHDR, &(ent->header), NULL, NULL))) { HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, NULL, "unable to load object header"); } @@ -740,7 +801,7 @@ H5O_find_in_ohdr (H5F_t *f, const haddr_t *addr, const H5O_class_t **type_p, *------------------------------------------------------------------------- */ const void * -H5O_peek (H5F_t *f, const haddr_t *addr, const H5O_class_t *type, +H5O_peek (H5F_t *f, H5G_entry_t *ent, const H5O_class_t *type, intn sequence) { intn idx; @@ -750,13 +811,13 @@ H5O_peek (H5F_t *f, const haddr_t *addr, const H5O_class_t *type, /* check args */ assert (f); - assert (addr && H5F_addr_defined (addr)); + assert (ent && H5F_addr_defined (&(ent->header))); - if ((idx = H5O_find_in_ohdr (f, addr, &type, sequence))<0) { + if ((idx = H5O_find_in_ohdr (f, &(ent->header), &type, sequence))<0) { HRETURN_ERROR (H5E_OHDR, H5E_NOTFOUND, NULL, "unable to find object header message"); } - if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL, NULL))) { + if (NULL==(oh=H5AC_find (f, H5AC_OHDR, &(ent->header), NULL, NULL))) { HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, NULL, "unable to load object header"); } @@ -769,11 +830,8 @@ H5O_peek (H5F_t *f, const haddr_t *addr, const H5O_class_t *type, * Function: H5O_modify * * Purpose: Modifies an existing message or creates a new message. - * The object header is at file address ADDR of file F (but if - * ENT is present then its `header' field is used instead). An - * optional symbol table entry ENT can be supplied in which - * case the cache fields in that symbol table are updated if - * appropriate. + * The cache fields in that symbol table entry ENT are updated + * as appropriate. * * The OVERWRITE argument is either a sequence number of a * message to overwrite (usually zero) or the constant @@ -798,30 +856,23 @@ H5O_peek (H5F_t *f, const haddr_t *addr, const H5O_class_t *type, *------------------------------------------------------------------------- */ intn -H5O_modify (H5F_t *f, const haddr_t *addr, H5G_entry_t *ent, - const H5O_class_t *type, intn overwrite, const void *mesg) +H5O_modify (H5F_t *f, H5G_entry_t *ent, const H5O_class_t *type, + intn overwrite, const void *mesg) { H5O_t *oh = NULL; intn idx, sequence; size_t size; - haddr_t _addr; FUNC_ENTER (H5O_modify, FAIL); /* check args */ assert (f); + assert (ent); + assert (H5F_addr_defined (&(ent->header))); assert (type); assert (mesg); - if (!addr) { - if (!ent || H5G_ent_addr (ent, &_addr)<0) { - HRETURN_ERROR (H5E_OHDR, H5E_CANTINIT, FAIL, - "invalid object header address"); - } - addr = &_addr; - } - assert (H5F_addr_defined (addr)); - if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL, NULL))) { + if (NULL==(oh=H5AC_find (f, H5AC_OHDR, &(ent->header), NULL, NULL))) { HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header"); } @@ -866,7 +917,7 @@ H5O_modify (H5F_t *f, const haddr_t *addr, H5G_entry_t *ent, oh->dirty = TRUE; /* Copy into the symbol table entry */ - if (oh->nlink<=1 && ent && type->cache) { + if (oh->nlink<=1 && type->cache) { H5G_type_t cache_type; H5G_cache_t *cache = H5G_ent_cache (ent, &cache_type); hbool_t modified = (type->cache)(&cache_type, cache, mesg); @@ -909,29 +960,21 @@ H5O_modify (H5F_t *f, const haddr_t *addr, H5G_entry_t *ent, *------------------------------------------------------------------------- */ herr_t -H5O_remove (H5F_t *f, const haddr_t *addr, H5G_entry_t *ent, - const H5O_class_t *type, intn sequence) +H5O_remove (H5F_t *f, H5G_entry_t *ent, const H5O_class_t *type, intn sequence) { H5O_t *oh = NULL; intn i, seq; - haddr_t _addr; FUNC_ENTER (H5O_remove, FAIL); /* check args */ assert (f); + assert (ent); + assert (H5F_addr_defined (&(ent->header))); assert (type); - if (!addr) { - if (!ent || H5G_ent_addr (ent, &_addr)<0) { - HRETURN_ERROR (H5E_OHDR, H5E_CANTINIT, FAIL, - "invalid object header address"); - } - addr = &_addr; - } - assert (H5F_addr_defined (addr)); /* load the object header */ - if (NULL==(oh=H5AC_find (f, H5AC_OHDR, addr, NULL, NULL))) { + if (NULL==(oh=H5AC_find (f, H5AC_OHDR, &(ent->header), NULL, NULL))) { HRETURN_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header"); } diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h index 8d00117..da682c6 100644 --- a/src/H5Oprivate.h +++ b/src/H5Oprivate.h @@ -180,16 +180,18 @@ typedef struct H5O_stab_t { -herr_t H5O_create (H5F_t *f, intn nlink, size_t size_hint, haddr_t*); +herr_t H5O_create (H5F_t *f, size_t size_hint, H5G_entry_t *ent/*out*/); +herr_t H5O_open (H5F_t *f, H5G_entry_t *ent); +herr_t H5O_close (H5F_t *f, H5G_entry_t *ent); intn H5O_link (H5F_t *f, H5G_entry_t *ent, intn adjust); -void *H5O_read (H5F_t *f, const haddr_t *addr, H5G_entry_t *ent, - const H5O_class_t *type, intn sequence, void *mesg); -const void *H5O_peek (H5F_t *f, const haddr_t *addr, const H5O_class_t *type, +void *H5O_read (H5F_t *f, H5G_entry_t *ent, const H5O_class_t *type, + intn sequence, void *mesg); +const void *H5O_peek (H5F_t *f, H5G_entry_t *ent, const H5O_class_t *type, intn sequence); -intn H5O_modify (H5F_t *f, const haddr_t *addr, H5G_entry_t *ent, - const H5O_class_t *type, intn overwrite, const void *mesg); -herr_t H5O_remove (H5F_t *f, const haddr_t *addr, H5G_entry_t *ent, - const H5O_class_t *type, intn sequence); +intn H5O_modify (H5F_t *f, H5G_entry_t *ent, const H5O_class_t *type, + intn overwrite, const void *mesg); +herr_t H5O_remove (H5F_t *f, H5G_entry_t *ent, const H5O_class_t *type, + intn sequence); herr_t H5O_reset (const H5O_class_t *type, void *native); herr_t H5O_debug (H5F_t *f, const haddr_t *addr, FILE *stream, intn indent, intn fwidth); @@ -610,7 +610,7 @@ H5P_modify (H5F_t *f, H5G_entry_t *ent, const H5P_t *ds) "scalar data spaces are not implemented yet"); case H5P_SIMPLE: - if (H5O_modify (f, NO_ADDR, ent, H5O_SDSPACE, 0, &(ds->u.simple))<0) { + if (H5O_modify (f, ent, H5O_SDSPACE, 0, &(ds->u.simple))<0) { HRETURN_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't update simple data space message"); } @@ -658,7 +658,7 @@ H5P_read (H5F_t *f, H5G_entry_t *ent) ds = H5MM_xcalloc (1, sizeof(H5P_t)); - if (H5O_read (f, NO_ADDR, ent, H5O_SDSPACE, 0, &(ds->u.simple))) { + if (H5O_read (f, ent, H5O_SDSPACE, 0, &(ds->u.simple))) { ds->type = H5P_SIMPLE; } else { diff --git a/src/H5private.h b/src/H5private.h index 6972ebf..d650c03 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -22,7 +22,7 @@ #include <H5public.h> /* Include Public Definitions */ /* Version #'s of library code */ -#define HDF5_MAJOR_VERSION 0 /* For major interface changes */ +#define HDF5_MAJOR_VERSION 5 /* For major interface changes */ #define HDF5_MINOR_VERSION 0 /* For minor interface changes */ #define HDF5_RELEASE_VERSION 0 /* For interface tweaks & bug-fixes */ #define HDF5_PATCH_VERSION 0 /* For small groups of bug fixes*/ diff --git a/src/Makefile.in b/src/Makefile.in index 16086f2..0304868 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -16,10 +16,9 @@ PROGS=debug # Source and object files for the library (lexicographically)... LIB_SRC=H5.c H5A.c H5AC.c H5B.c H5C.c H5D.c H5Dconv.c H5E.c H5F.c H5Fcore.c \ H5Ffamily.c H5Fistore.c H5Flow.c H5Fsec2.c H5Fsplit.c H5Fstdio.c \ - H5G.c H5Gent.c H5Gnode.c H5Gshad.c H5Gstab.c H5H.c H5M.c H5MF.c \ - H5MM.c H5O.c H5Ocont.c H5Ocstore.c H5Odtype.c H5Oefl.c H5Oistore.c \ - H5Oname.c H5Onull.c H5Osdspace.c H5Ostab.c H5P.c H5T.c H5Tinit.c \ - H5V.c + H5G.c H5Gent.c H5Gnode.c H5Gstab.c H5H.c H5M.c H5MF.c H5MM.c H5O.c \ + H5Ocont.c H5Ocstore.c H5Odtype.c H5Oefl.c H5Oistore.c H5Oname.c \ + H5Onull.c H5Osdspace.c H5Ostab.c H5P.c H5T.c H5Tinit.c H5V.c LIB_OBJ=$(LIB_SRC:.c=.o) diff --git a/test/istore.c b/test/istore.c index 580518b..81ae8c2 100644 --- a/test/istore.c +++ b/test/istore.c @@ -15,10 +15,10 @@ #include <H5Oprivate.h> #include <H5Vprivate.h> -#if 0 +#if 1 # define FILETYPE H5F_LOW_DFLT # define FILENAME "istore.h5" -#elif 1 +#elif 0 # define FILETYPE H5F_LOW_FAM # define FILENAME "istore-%05d.h5" # define TEST_FAMILY 1 @@ -96,22 +96,21 @@ print_array (uint8 *array, size_t nx, size_t ny, size_t nz) * *------------------------------------------------------------------------- */ -static H5G_entry_t * -new_object (H5F_t *f, const char *name, size_t ndims) +static int +new_object (H5F_t *f, const char *name, size_t ndims, H5G_entry_t *ent/*out*/) { - H5G_entry_t *handle = NULL; H5O_istore_t istore; size_t alignment[H5O_ISTORE_NDIMS]; intn i; - /* Create the object symbol table entry and header */ - if (NULL==(handle=H5G_create (f, name, 64))) { + /* Create the object header */ + if (H5O_create (f, 64, ent)) { puts ("*FAILED*"); if (!isatty (1)) { AT (); - printf (" H5G_create (f, name=\"%s\") = NULL\n", name); + printf (" H5O_create() = NULL\n"); } - return NULL; + return -1; } /* Add the indexed-storage message */ @@ -122,19 +121,30 @@ new_object (H5F_t *f, const char *name, size_t ndims) alignment[i] = 2; } } - H5F_istore_create (f, &istore, ndims, alignment); - if (H5O_modify (f, NO_ADDR, handle, H5O_ISTORE, H5O_NEW_MESG, - &istore)<0) { + if (H5O_modify (f, ent, H5O_ISTORE, H5O_NEW_MESG, &istore)<0) { printf ("*FAILED*\n"); if (!isatty (1)) { AT(); - printf (" H5G_modify istore message failure\n"); + printf (" H5O_modify istore message failure\n"); } - return NULL; + return -1; } - return handle; + /* Give the object header a name */ + if (H5G_insert (f, name, ent)<0) { + printf ("*FAILED*\n"); + if (!isatty (1)) { + AT (); + printf (" H5G_insert(f, name=\"%s\", ent) failed\n", name); + } + return -1; + } + + /* Close the header */ + H5O_close (f, ent); + + return 0; } @@ -158,7 +168,7 @@ new_object (H5F_t *f, const char *name, size_t ndims) static herr_t test_create (H5F_t *f, const char *prefix) { - H5G_entry_t *handle = NULL; + H5G_entry_t handle; intn i; char name[256]; @@ -166,8 +176,7 @@ test_create (H5F_t *f, const char *prefix) for (i=1; i<=H5O_ISTORE_NDIMS; i++) { sprintf (name, "%s_%02d", prefix, i); - if (NULL==(handle=new_object (f, name, i))) return FAIL; - H5G_close (f, handle); + if (new_object (f, name, i, &handle)<0) return FAIL; } puts (" PASSED"); @@ -198,7 +207,7 @@ static herr_t test_extend (H5F_t *f, const char *prefix, size_t nx, size_t ny, size_t nz) { - H5G_entry_t *handle = NULL; + H5G_entry_t handle; int i, j, k, ndims, ctr; uint8 *buf=NULL, *check=NULL, *whole=NULL; char dims[64], s[256], name[256]; @@ -234,14 +243,14 @@ test_extend (H5F_t *f, const char *prefix, /* Build the new empty object */ sprintf (name, "%s_%s", prefix, dims); - if (NULL==(handle=new_object (f, name, ndims))) { + if (new_object (f, name, ndims, &handle)<0) { if (!isatty (1)) { AT (); printf (" Cannot create %d-d object `%s'\n", ndims, name); } goto error; } - if (NULL==H5O_read (f, NO_ADDR, handle, H5O_ISTORE, 0, &istore)) { + if (NULL==H5O_read (f, &handle, H5O_ISTORE, 0, &istore)) { puts ("*FAILED*"); if (!isatty (1)) { AT (); @@ -377,7 +386,6 @@ test_extend (H5F_t *f, const char *prefix, } } - H5G_close (f, handle); puts (" PASSED"); H5MM_xfree (buf); H5MM_xfree (check); @@ -417,7 +425,7 @@ test_sparse (H5F_t *f, const char *prefix, size_t nblocks, intn ndims, ctr; char dims[64], s[256], name[256]; size_t offset[3], size[3], total=0; - H5G_entry_t *handle = NULL; + H5G_entry_t handle; H5O_istore_t istore; uint8 *buf = NULL; @@ -443,14 +451,14 @@ test_sparse (H5F_t *f, const char *prefix, size_t nblocks, /* Build the new empty object */ sprintf (name, "%s_%s", prefix, dims); - if (NULL==(handle=new_object (f, name, ndims))) { + if (new_object (f, name, ndims, &handle)<0) { if (!isatty (1)) { AT (); printf (" Cannot create %d-d object `%s'\n", ndims, name); } goto error; } - if (NULL==H5O_read (f, NO_ADDR, handle, H5O_ISTORE, 0, &istore)) { + if (NULL==H5O_read (f, &handle, H5O_ISTORE, 0, &istore)) { puts ("*FAILED*"); if (!isatty (1)) { AT (); @@ -493,7 +501,6 @@ test_sparse (H5F_t *f, const char *prefix, size_t nblocks, } - H5G_close (f, handle); puts (" PASSED"); H5MM_xfree (buf); return SUCCEED; @@ -528,9 +535,9 @@ main (int argc, char *argv[]) int nerrors = 0; uintn size_of_test; size_t offset_size; - H5G_entry_t *ent = NULL; hid_t template_id; H5F_create_t *creation_template = NULL; + H5G_t *dir = NULL; setbuf (stdout, NULL); @@ -591,9 +598,9 @@ main (int argc, char *argv[]) * By creating a group we cause the library to emit it's debugging * diagnostic messages before we begin testing... */ - ent = H5G_new (f, "flushing_diagnostics", 0); - H5G_close (f, ent); - ent = NULL; + dir = H5G_create (f, "flushing_diagnostics", 0); + H5G_close (dir); + dir = NULL; /* diff --git a/test/testhdf5.c b/test/testhdf5.c index 716a740..93e059a 100644 --- a/test/testhdf5.c +++ b/test/testhdf5.c @@ -163,8 +163,8 @@ int main(int argc, char *argv[]) H5version(&major, &minor, &release, &patch); print_func("\nFor help use: testhdf5 -help\n"); - print_func("Built with HDF5 Library Version: %u.%ur%u, patch %u\n\n", (unsigned) major, - (unsigned) minor, (unsigned) release, (unsigned)patch); + print_func("Linked with HDF %u.%u.%u%c\n\n", (unsigned) major, + (unsigned) minor, (unsigned) release, 'a'+patch); for (CLLoop = 1; CLLoop < argc; CLLoop++) { if ((argc > CLLoop + 1) && ((HDstrcmp(argv[CLLoop], "-verbose") == 0) || diff --git a/test/tohdr.c b/test/tohdr.c index 5c0711d..9965092 100644 --- a/test/tohdr.c +++ b/test/tohdr.c @@ -49,11 +49,10 @@ test_ohdr (void) { hid_t fid; H5F_t *f; - haddr_t oh_addr; + H5G_entry_t oh_ent; H5O_stab_t stab, ro; herr_t status; void *ptr; - H5G_entry_t ent; int i; MESSAGE (5, ("Testing Object Headers\n")); @@ -66,7 +65,7 @@ test_ohdr (void) /* the new object header */ MESSAGE (8, ("Creating new object header...\n")); - status = H5O_create (f, 1, 64, &oh_addr/*out*/); + status = H5O_create (f, 64, &oh_ent/*out*/); CHECK_I (status, "H5O_new"); /* @@ -75,11 +74,11 @@ test_ohdr (void) MESSAGE (8, ("Creating new message...\n")); stab.btree_addr.offset = 11111111; stab.heap_addr.offset = 22222222; - status = H5O_modify (f, &oh_addr, NULL, H5O_STAB, H5O_NEW_MESG, &stab); + status = H5O_modify (f, &oh_ent, H5O_STAB, H5O_NEW_MESG, &stab); VERIFY (status, 0, "H5O_modify"); H5AC_flush (f, NULL, 0, TRUE); - ptr = H5O_read (f, &oh_addr, NULL, H5O_STAB, 0, &ro); + ptr = H5O_read (f, &oh_ent, H5O_STAB, 0, &ro); CHECK_PTR (ptr, "H5O_read"); VERIFY (ptr, &ro, "H5O_read"); VERIFY (ro.btree_addr.offset, stab.btree_addr.offset, "H5O_read"); @@ -91,11 +90,11 @@ test_ohdr (void) MESSAGE (8, ("Modifying message...\n")); stab.btree_addr.offset = 33333333; stab.heap_addr.offset = 44444444; - status = H5O_modify (f, &oh_addr, NULL, H5O_STAB, 0, &stab); + status = H5O_modify (f, &oh_ent, H5O_STAB, 0, &stab); VERIFY (status, 0, "H5O_modify"); H5AC_flush (f, NULL, 0, TRUE); - ptr = H5O_read (f, &oh_addr, NULL, H5O_STAB, 0, &ro); + ptr = H5O_read (f, &oh_ent, H5O_STAB, 0, &ro); CHECK_PTR (ptr, "H5O_read"); VERIFY (ptr, &ro, "H5O_read"); VERIFY (ro.btree_addr.offset, stab.btree_addr.offset, "H5O_read"); @@ -106,22 +105,19 @@ test_ohdr (void) * table. */ MESSAGE (8, ("Creating a duplicate message...\n")); - ent.header.offset = 0; - ent.type = H5G_NOTHING_CACHED; - ent.dirty = FALSE; stab.btree_addr.offset = 55555555; stab.heap_addr.offset = 66666666; - status = H5O_modify (f, &oh_addr, &ent, H5O_STAB, H5O_NEW_MESG, &stab); + status = H5O_modify (f, &oh_ent, H5O_STAB, H5O_NEW_MESG, &stab); VERIFY (status, 1, "H5O_modify"); - VERIFY (ent.dirty, TRUE, "H5O_modify"); - VERIFY (ent.type, H5G_CACHED_STAB, "H5O_modify"); - VERIFY (ent.cache.stab.heap_addr.offset, stab.heap_addr.offset, + VERIFY (oh_ent.dirty, TRUE, "H5O_modify"); + VERIFY (oh_ent.type, H5G_CACHED_STAB, "H5O_modify"); + VERIFY (oh_ent.cache.stab.heap_addr.offset, stab.heap_addr.offset, "H5O_modify"); - VERIFY (ent.cache.stab.btree_addr.offset, stab.btree_addr.offset, + VERIFY (oh_ent.cache.stab.btree_addr.offset, stab.btree_addr.offset, "H5O_modify"); H5AC_flush (f, NULL, 0, TRUE); - ptr = H5O_read (f, &oh_addr, NULL, H5O_STAB, 1, &ro); + ptr = H5O_read (f, &oh_ent, H5O_STAB, 1, &ro); CHECK_PTR (ptr, "H5O_read"); VERIFY (ptr, &ro, "H5O_read"); VERIFY (ro.btree_addr.offset, stab.btree_addr.offset, "H5O_read"); @@ -131,20 +127,19 @@ test_ohdr (void) * Test modification of the second message with a symbol table. */ MESSAGE (8, ("Modifying the duplicate message...\n")); - ent.dirty = FALSE; stab.btree_addr.offset = 77777777; stab.heap_addr.offset = 88888888; - status = H5O_modify (f, &oh_addr, &ent, H5O_STAB, 1, &stab); + status = H5O_modify (f, &oh_ent, H5O_STAB, 1, &stab); VERIFY (status, 1, "H5O_modify"); - VERIFY (ent.dirty, TRUE, "H5O_modify"); - VERIFY (ent.type, H5G_CACHED_STAB, "H5O_modify"); - VERIFY (ent.cache.stab.heap_addr.offset, stab.heap_addr.offset, + VERIFY (oh_ent.dirty, TRUE, "H5O_modify"); + VERIFY (oh_ent.type, H5G_CACHED_STAB, "H5O_modify"); + VERIFY (oh_ent.cache.stab.heap_addr.offset, stab.heap_addr.offset, "H5O_modify"); - VERIFY (ent.cache.stab.btree_addr.offset, stab.btree_addr.offset, + VERIFY (oh_ent.cache.stab.btree_addr.offset, stab.btree_addr.offset, "H5O_modify"); H5AC_flush (f, NULL, 0, TRUE); - ptr = H5O_read (f, &oh_addr, NULL, H5O_STAB, 1, &ro); + ptr = H5O_read (f, &oh_ent, H5O_STAB, 1, &ro); CHECK_PTR (ptr, "H5O_read"); VERIFY (ptr, &ro, "H5O_read"); VERIFY (ro.btree_addr.offset, stab.btree_addr.offset, "H5O_read"); @@ -158,7 +153,7 @@ test_ohdr (void) for (i=0; i<40; i++) { stab.btree_addr.offset = (i+1)*1000 + 1; stab.heap_addr.offset = (i+1)*1000 + 2; - status = H5O_modify (f, &oh_addr, NULL, H5O_STAB, H5O_NEW_MESG, &stab); + status = H5O_modify (f, &oh_ent, H5O_STAB, H5O_NEW_MESG, &stab); VERIFY (status, 2+i, "H5O_modify"); } H5AC_flush (f, NULL, 0, TRUE); @@ -171,7 +166,7 @@ test_ohdr (void) for (i=0; i<10; i++) { stab.btree_addr.offset = (i+1)*1000 + 10; stab.heap_addr.offset = (i+1)*1000 + 20; - status = H5O_modify (f, &oh_addr, NULL, H5O_STAB, H5O_NEW_MESG, &stab); + status = H5O_modify (f, &oh_ent, H5O_STAB, H5O_NEW_MESG, &stab); VERIFY (status, 42+i, "H5O_modify"); H5AC_flush (f, NULL, 0, TRUE); } @@ -179,7 +174,7 @@ test_ohdr (void) /* * Delete all symbol table messages. */ - status = H5O_remove (f, &oh_addr, NULL, H5O_STAB, H5O_ALL); + status = H5O_remove (f, &oh_ent, H5O_STAB, H5O_ALL); CHECK_I (status, "H5O_remove"); /* close the file */ diff --git a/test/tstab.c b/test/tstab.c index e2384f8..c5542ee 100644 --- a/test/tstab.c +++ b/test/tstab.c @@ -18,6 +18,7 @@ #include <H5private.h> #include <H5ACprivate.h> +#include <H5Cprivate.h> #include <H5Fprivate.h> #include <H5Gprivate.h> #include <H5Oprivate.h> @@ -51,8 +52,7 @@ test_1 (void) { hid_t fid; H5F_t *f; - H5G_entry_t *obj1=NULL, *obj2=NULL; - H5G_entry_t ent1, dir_ent; + H5G_entry_t ent1, ent2, obj_ent, dir_ent; herr_t status; H5O_name_t name_mesg; void *status_ptr; @@ -73,26 +73,28 @@ test_1 (void) CHECK (f, NULL, "H5Aatom_object"); /* create the object */ - obj1 = H5G_create (f, "/", 0); - CHECK_PTR (obj1, "H5G_new"); + status = H5O_create (f, 0, &ent1); + CHECK_I (status, "H5O_create"); + status = H5G_insert (f, "/", &ent1); + CHECK_I (status, "H5G_insert"); /* look for a name message -- it shouldn't be present */ - status_ptr = H5O_read (f, NO_ADDR, obj1, H5O_NAME, 0, &name_mesg); + status_ptr = H5O_read (f, &ent1, H5O_NAME, 0, &name_mesg); VERIFY (status_ptr, NULL, "H5O_read [didn't fail but should have]"); /* * Test 1B: Attempt to read the root object using the name `/'. */ memset (&dir_ent, 0xff, sizeof(H5G_entry_t)); - memset (&ent1, 0xff, sizeof(H5G_entry_t)); - status = H5G_find (f, "/", &dir_ent, &ent1); + memset (&obj_ent, 0xff, sizeof(H5G_entry_t)); + status = H5G_find (f, "/", &dir_ent, &obj_ent); CHECK_I (status, "H5G_find"); /* Is it really the root object? */ b = H5F_addr_defined (&(dir_ent.header)); - VERIFY (b, FALSE, "H5G_create"); - b = H5F_addr_eq (&(ent1.header), &(obj1->header)); - VERIFY (b, TRUE, "H5G_create"); + VERIFY (b, FALSE, "H5G_insert"); + b = H5F_addr_eq (&(obj_ent.header), &(ent1.header)); + VERIFY (b, TRUE, "H5G_insert"); /* @@ -101,24 +103,20 @@ test_1 (void) */ /* create the object */ - obj2 = H5G_create (f, "/second", 0); - CHECK_PTR (obj2, "H5G_new"); + status = H5O_create (f, 0, &ent2); + CHECK_I (status, "H5O_create"); + status = H5G_insert (f, "/second", &ent2); + CHECK_I (status, "H5G_insert"); /* try to read the first object */ - HDmemset (&ent1, 0xff, sizeof(H5G_entry_t)); - status = H5G_find (f, "/Root Object", NULL, &ent1); + HDmemset (&obj_ent, 0xff, sizeof(H5G_entry_t)); + status = H5G_find (f, "/Root Object", NULL, &obj_ent); CHECK_I (status, "H5G_find"); - b = H5F_addr_defined (&(ent1.header)); - VERIFY (b, TRUE, "H5G_create"); - b = H5F_addr_eq (&(ent1.header), &(obj1->header)); + b = H5F_addr_defined (&(obj_ent.header)); + VERIFY (b, TRUE, "H5G_insert"); + b = H5F_addr_eq (&(obj_ent.header), &(ent1.header)); VERIFY (b, TRUE, "H5G_create"); - /* close the objects */ - H5G_close (f, obj1); - obj1 = NULL; - H5G_close (f, obj2); - obj2 = NULL; - /* close the file */ H5Fclose (fid); @@ -137,14 +135,16 @@ test_1 (void) CHECK (f, NULL, "H5Aatom_object"); /* create the object */ - obj1 = H5G_create (f, "/foo", 0); - CHECK_PTR (obj1, "H5G_create"); + status = H5O_create (f, 0, &ent1); + CHECK_I (status, "H5O_create"); + status = H5G_insert (f, "/foo", &ent1); + CHECK_I (status, "H5G_insert"); /* does it have the correct name message? */ - status_ptr = H5O_read (f, NO_ADDR, obj1, H5O_NAME, 0, &name_mesg); + status_ptr = H5O_read (f, &ent1, H5O_NAME, 0, &name_mesg); CHECK_PTR (status_ptr, "H5O_read"); CHECK_PTR (name_mesg.s, "H5O_read"); - VERIFY (strcmp(name_mesg.s, "foo"), 0, "H5O_read"); + VERIFY (strcmp(name_mesg.s, "foo"), 0, "H5G_insert"); if (status_ptr) H5O_reset (H5O_NAME, &name_mesg); /*free message data*/ @@ -152,23 +152,23 @@ test_1 (void) * Test 1E: Try to read the root object with the name `/' and `/foo' */ HDmemset (&dir_ent, 0, sizeof(H5G_entry_t)); - HDmemset (&ent1, 0, sizeof(H5G_entry_t)); - status = H5G_find (f, "/", &dir_ent, &ent1); + HDmemset (&obj_ent, 0, sizeof(H5G_entry_t)); + status = H5G_find (f, "/", &dir_ent, &obj_ent); CHECK_I (status, "H5G_find"); b = H5F_addr_defined (&(dir_ent.header)); - VERIFY (b, FALSE, "H5G_create"); - b = H5F_addr_eq (&(ent1.header), &(obj1->header)); - VERIFY (b, TRUE, "H5G_create"); + VERIFY (b, FALSE, "H5G_insert"); + b = H5F_addr_eq (&(obj_ent.header), &(ent1.header)); + VERIFY (b, TRUE, "H5G_insert"); /* now as `/foo' */ HDmemset (&dir_ent, 0, sizeof(H5G_entry_t)); - HDmemset (&ent1, 0, sizeof(H5G_entry_t)); - status = H5G_find (f, "/foo", &dir_ent, &ent1); + HDmemset (&obj_ent, 0, sizeof(H5G_entry_t)); + status = H5G_find (f, "/foo", &dir_ent, &obj_ent); CHECK_I (status, "H5G_find"); b = H5F_addr_defined (&(dir_ent.header)); - VERIFY (b, FALSE, "H5G_create"); - b = H5F_addr_eq (&(ent1.header), &(obj1->header)); - VERIFY (b, TRUE, "H5G_find"); + VERIFY (b, FALSE, "H5G_insert"); + b = H5F_addr_eq (&(obj_ent.header), &(ent1.header)); + VERIFY (b, TRUE, "H5G_insert"); /* @@ -177,26 +177,22 @@ test_1 (void) */ /* create the object */ - obj2 = H5G_create (f, "/second", 0); - CHECK_PTR (obj2, "H5G_new"); + status = H5O_create (f, 0, &ent2); + CHECK_I (status, "H5O_create"); + status = H5G_insert (f, "/second", &ent2); + CHECK_I (status, "H5G_insert"); /* try to read the first object */ - HDmemset (&ent1, 0, sizeof(H5G_entry_t)); - status = H5G_find (f, "/foo", NULL, &ent1); + HDmemset (&obj_ent, 0, sizeof(H5G_entry_t)); + status = H5G_find (f, "/foo", NULL, &obj_ent); CHECK_I (status, "H5G_find"); - b = H5F_addr_eq (&(ent1.header), &(obj1->header)); - VERIFY (b, TRUE, "H5G_find"); + b = H5F_addr_eq (&(obj_ent.header), &(ent1.header)); + VERIFY (b, TRUE, "H5G_insert"); /* the first object should not have a name message */ - status_ptr = H5O_read (f, NO_ADDR, obj1, H5O_NAME, 0, &name_mesg); + status_ptr = H5O_read (f, &ent1, H5O_NAME, 0, &name_mesg); VERIFY (status_ptr, NULL, "H5O_read [didn't fail but should have]"); - /* close the objects */ - H5G_close (f, obj1); - obj1 = NULL; - H5G_close (f, obj2); - obj2 = NULL; - /* close the file */ status = H5Fclose (fid); CHECK_I (status, "H5Fclose"); @@ -221,18 +217,28 @@ test_1 (void) static void test_2 (void) { - hid_t fid; + hid_t fid, props; H5F_t *f; - H5G_entry_t *obj1=NULL; int i; char name[256]; herr_t status; int nsyms = 5000; + H5G_t *dir = NULL; MESSAGE (2, ("........large directories\n")); + /* + * Use larger symbol table data structures to be more efficient, use + * defaults to bang harder on the library for testing. + */ + props = H5Ccreate (H5C_FILE_CREATE); +#if 1 + H5Cset_prop (props, H5F_SYM_LEAF_K, 16); + H5Cset_prop (props, H5F_SYM_INTERN_K, 16); +#endif + /* create the file */ - fid = H5Fcreate ("tstab2.h5", H5ACC_OVERWRITE, 0, 0); + fid = H5Fcreate ("tstab2.h5", H5ACC_OVERWRITE, props, 0); CHECK (fid, FAIL, "H5Fcreate"); f = H5Aatom_object (fid); CHECK (f, NULL, "H5Aatom_object"); @@ -242,19 +248,17 @@ test_2 (void) * Create a directory that has so many entries that the root * of the B-tree ends up splitting. */ - obj1 = H5G_new (f, "/big", nsyms*12+2); - CHECK_PTR (obj1, "H5G_mkdir"); - H5G_close (f, obj1); - obj1 = NULL; + dir = H5G_create (f, "/big", nsyms*12+2); + CHECK_PTR (dir, "H5G_mkdir"); + status = H5G_close (dir); + CHECK_I (status, "H5G_close"); for (i=0; i<nsyms; i++) { - sprintf (name, "/big/%05d%05d", rand()%100000, i); MESSAGE (8, ("%s\n", name)); - obj1 = H5G_create (f, name, 0); - CHECK_PTR (obj1, "H5G_mkdir"); - H5G_close (f, obj1); - obj1 = NULL; + dir = H5G_create (f, name, 0); + CHECK_PTR (dir, "H5G_create"); + H5G_close (dir); } |