diff options
Diffstat (limited to 'src')
88 files changed, 12277 insertions, 7203 deletions
@@ -221,6 +221,9 @@ H5_term_library(void) pending += DOWN(A); pending += DOWN(S); pending += DOWN(T); + /* Don't shut down the object header code until objects are shut down */ + if(pending==0) + pending += DOWN(O); /* Don't shut down the file code until objects in files are shut down */ if(pending==0) pending += DOWN(F); @@ -28,14 +28,14 @@ #include "H5Sprivate.h" /* Dataspace functions */ /* PRIVATE PROTOTYPES */ -static hid_t H5A_create(const H5G_entry_t *ent, const char *name, +static hid_t H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type, const H5S_t *space, hid_t dxpl_id); -static hid_t H5A_open(H5G_entry_t *ent, unsigned idx, hid_t dxpl_id); +static hid_t H5A_open(H5G_loc_t *loc, unsigned idx, hid_t dxpl_id); static herr_t H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf, hid_t dxpl_id); static herr_t H5A_read(const H5A_t *attr, const H5T_t *mem_type, void *buf, hid_t dxpl_id); -static int H5A_get_index(H5G_entry_t *ent, const char *name, hid_t dxpl_id); +static int H5A_get_index(H5O_loc_t *loc, const char *name, hid_t dxpl_id); static hsize_t H5A_get_storage_size(const H5A_t *attr); -static herr_t H5A_rename(H5G_entry_t *ent, const char *old_name, const char *new_name, hid_t dxpl_id); +static herr_t H5A_rename(H5O_loc_t *loc, const char *old_name, const char *new_name, hid_t dxpl_id); /* Object header iterator callbacks */ /* Data structure for callback for locating the index by name */ @@ -70,14 +70,14 @@ DESCRIPTION static herr_t H5A_init_interface(void) { - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5A_init_interface) /* * Create attribute group. */ - if (H5I_register_type(H5I_ATTR, (size_t)H5I_ATTRID_HASHSIZE, H5A_RESERVED_ATOMS, (H5I_free_t)H5A_close)<H5I_FILE) + if(H5I_register_type(H5I_ATTR, (size_t)H5I_ATTRID_HASHSIZE, H5A_RESERVED_ATOMS, (H5I_free_t)H5A_close) < H5I_FILE) HGOTO_ERROR(H5E_INTERNAL, H5E_CANTINIT, FAIL, "unable to initialize interface") done: @@ -108,8 +108,8 @@ H5A_term_interface(void) FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_term_interface) - if (H5_interface_initialize_g) { - if ((n=H5I_nmembers(H5I_ATTR))>0) { + if(H5_interface_initialize_g) { + if((n = H5I_nmembers(H5I_ATTR))>0) { (void)H5I_clear_type(H5I_ATTR, FALSE); } else { (void)H5I_dec_type_ref(H5I_ATTR); @@ -136,8 +136,6 @@ H5A_term_interface(void) RETURNS Non-negative on success/Negative on failure - ERRORS - DESCRIPTION This function creates an attribute which is attached to the object specified with 'location_id'. The name specified with 'name' for each @@ -154,18 +152,14 @@ H5A_term_interface(void) attribute is reduced to zero. The location object may be either a group or a dataset, both of which may have any sort of attribute. - * - * Modifications: - * Robb Matzke, 5 Jun 1998 - * The LOC_ID can also be a committed datatype. - * + --------------------------------------------------------------------------*/ /* ARGSUSED */ hid_t H5Acreate(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id, hid_t UNUSED plist_id) { - H5G_entry_t *ent = NULL; + H5G_loc_t loc; /* Object location */ H5T_t *type = NULL; H5S_t *space = NULL; hid_t ret_value = FAIL; @@ -174,20 +168,20 @@ H5Acreate(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id, H5TRACE5("i","isiii",loc_id,name,type_id,space_id,plist_id); /* check arguments */ - if (H5I_FILE==H5I_get_type(loc_id) || H5I_ATTR==H5I_get_type(loc_id)) + if(H5I_FILE == H5I_get_type(loc_id) || H5I_ATTR == H5I_get_type(loc_id)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute") - if (NULL==(ent=H5G_loc(loc_id))) + if(H5G_loc(loc_id, &loc) < 0) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") - if (!name || !*name) + if(!name || !*name) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") - if (NULL == (type = H5I_object_verify(type_id, H5I_DATATYPE))) + if(NULL == (type = H5I_object_verify(type_id, H5I_DATATYPE))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a type") - if (NULL == (space = H5I_object_verify(space_id, H5I_DATASPACE))) + if(NULL == (space = H5I_object_verify(space_id, H5I_DATASPACE))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space") /* Go do the real work for attaching the attribute to the dataset */ - if ((ret_value=H5A_create(ent,name,type,space, H5AC_dxpl_id))<0) - HGOTO_ERROR (H5E_ATTR, H5E_CANTINIT, FAIL, "unable to create attribute") + if((ret_value = H5A_create(&loc, name, type, space, H5AC_dxpl_id)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to create attribute") done: FUNC_LEAVE_API(ret_value) @@ -211,16 +205,11 @@ done: * Programmer: Quincey Koziol * April 2, 1998 * - * Modifications: - * - * Pedro Vicente, <pvn@ncsa.uiuc.edu> 22 Aug 2002 - * Added a deep copy of the symbol table entry - * *------------------------------------------------------------------------- */ static hid_t -H5A_create(const H5G_entry_t *ent, const char *name, const H5T_t *type, - const H5S_t *space, hid_t dxpl_id) +H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type, + const H5S_t *space, hid_t dxpl_id) { H5A_t *attr = NULL; H5A_iter_cb1 cb; /* Iterator callback */ @@ -229,47 +218,51 @@ H5A_create(const H5G_entry_t *ent, const char *name, const H5T_t *type, FUNC_ENTER_NOAPI_NOINIT(H5A_create) /* check args */ - assert(ent); - assert(name); - assert(type); - assert(space); + HDassert(loc); + HDassert(name); + HDassert(type); + HDassert(space); /* Iterate over the existing attributes to check for duplicates */ - cb.name=name; - cb.idx=(-1); - if((ret_value=H5O_iterate(ent,H5O_ATTR_ID,H5A_find_idx_by_name,&cb,dxpl_id))<0) + cb.name = name; + cb.idx = (-1); + if((ret_value = H5O_iterate(loc->oloc, H5O_ATTR_ID, H5A_find_idx_by_name, &cb, dxpl_id)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "error iterating over attributes") - if(ret_value>0) + if(ret_value > 0) HGOTO_ERROR(H5E_ATTR, H5E_ALREADYEXISTS, FAIL, "attribute already exists") /* Check if the dataspace has an extent set (or is NULL) */ - if( !(H5S_has_extent(space)) ) + if(!(H5S_has_extent(space))) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspace extent has not been set") /* Build the attribute information */ - if((attr = H5FL_CALLOC(H5A_t))==NULL) + if((attr = H5FL_CALLOC(H5A_t)) == NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for attribute info") /* Copy the attribute name */ - attr->name=HDstrdup(name); + attr->name = HDstrdup(name); /* Copy the attribute's datatype */ - attr->dt=H5T_copy(type, H5T_COPY_ALL); + attr->dt = H5T_copy(type, H5T_COPY_ALL); /* Mark any datatypes as being on disk now */ - if (H5T_set_loc(attr->dt, ent->file, H5T_LOC_DISK)<0) + if(H5T_set_loc(attr->dt, loc->oloc->file, H5T_LOC_DISK) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location") /* Copy the dataspace for the attribute */ - attr->ds=H5S_copy(space, FALSE); + attr->ds = H5S_copy(space, FALSE); /* Mark it initially set to initialized */ attr->initialized = TRUE; /*for now, set to false later*/ - /* Deep copy of the symbol table entry */ - if (H5G_ent_copy(&(attr->ent),ent,H5G_COPY_DEEP)<0) + /* Copy the object header information */ + if(H5O_loc_copy(&(attr->oloc), loc->oloc, H5O_COPY_DEEP) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to copy entry") + /* Deep copy of the group hierarchy path */ + if(H5G_name_copy(&(attr->path), loc->path, H5G_COPY_DEEP) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to copy path") + /* Compute the size of pieces on disk */ if(H5T_committed(attr->dt)) { H5O_shared_t sh_mesg; @@ -278,37 +271,37 @@ H5A_create(const H5G_entry_t *ent, const char *name, const H5T_t *type, HDmemset(&sh_mesg,0,sizeof(H5O_shared_t)); /* Get shared message information for datatype */ - if (H5O_get_share(H5O_DTYPE_ID,attr->ent.file, type, &sh_mesg/*out*/)<0) + if(H5O_get_share(H5O_DTYPE_ID, attr->oloc.file, type, &sh_mesg/*out*/) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to copy entry") /* Compute shared message size for datatype */ - attr->dt_size=H5O_raw_size(H5O_SHARED_ID,attr->ent.file,&sh_mesg); + attr->dt_size = H5O_raw_size(H5O_SHARED_ID, attr->oloc.file, &sh_mesg); } /* end if */ else - attr->dt_size=H5O_raw_size(H5O_DTYPE_ID,attr->ent.file,type); - assert(attr->dt_size>0); - attr->ds_size=H5S_raw_size(attr->ent.file,space); - assert(attr->ds_size>0); - H5_ASSIGN_OVERFLOW(attr->data_size,H5S_GET_EXTENT_NPOINTS(attr->ds)*H5T_get_size(attr->dt),hssize_t,size_t); + attr->dt_size = H5O_raw_size(H5O_DTYPE_ID, attr->oloc.file, type); + HDassert(attr->dt_size > 0); + attr->ds_size = H5S_raw_size(attr->oloc.file, space); + HDassert(attr->ds_size > 0); + H5_ASSIGN_OVERFLOW(attr->data_size, H5S_GET_EXTENT_NPOINTS(attr->ds) * H5T_get_size(attr->dt), hssize_t, size_t); /* Hold the symbol table entry (and file) open */ - if (H5O_open(&(attr->ent)) < 0) + if(H5O_open(&(attr->oloc)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open") - attr->ent_opened=1; + attr->obj_opened = TRUE; /* Create the attribute message and save the attribute index */ - if (H5O_modify(&(attr->ent), H5O_ATTR_ID, H5O_NEW_MESG, 0, H5O_UPDATE_TIME, attr, dxpl_id) < 0) + if(H5O_modify(&(attr->oloc), H5O_ATTR_ID, H5O_NEW_MESG, 0, H5O_UPDATE_TIME, attr, dxpl_id) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to update attribute header messages") /* Register the new attribute and get an ID for it */ - if ((ret_value = H5I_register(H5I_ATTR, attr)) < 0) + if((ret_value = H5I_register(H5I_ATTR, attr)) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register attribute for ID") /* Now it's safe to say it's uninitialized */ attr->initialized = FALSE; done: - if (ret_value < 0) { + if(ret_value < 0) { if(attr) (void)H5A_close(attr); } /* end if */ @@ -330,8 +323,6 @@ done: RETURNS Non-negative on success, negative on failure - ERRORS - DESCRIPTION This function determines if an attribute matches the name to search for (from the 'op_data') and sets the index value in the 'op_data'. @@ -353,7 +344,7 @@ H5A_find_idx_by_name(const void *_mesg, unsigned idx, void *_op_data) * callback info if names are the same. */ if(HDstrcmp(mesg->name,op_data->name)==0) { - op_data->idx=idx; + op_data->idx = idx; ret_value=1; } /* end if */ else @@ -370,13 +361,11 @@ H5A_find_idx_by_name(const void *_mesg, unsigned idx, void *_op_data) Determine the index of an attribute in an object header USAGE int H5A_get_index (ent, name) - H5G_entry_t *ent; IN: Symbol table entry of object - const char *name; IN: Name of dataset to find + H5O_loc_t *loc; IN: Object location + const char *name; IN: Name of dataset to find RETURNS non-negative on success, negative on failure - ERRORS - DESCRIPTION This function determines the index of the attribute within an object header. This is not stored in the attribute structure because it is only @@ -384,22 +373,22 @@ H5A_find_idx_by_name(const void *_mesg, unsigned idx, void *_op_data) object header. --------------------------------------------------------------------------*/ static int -H5A_get_index(H5G_entry_t *ent, const char *name, hid_t dxpl_id) +H5A_get_index(H5O_loc_t *loc, const char *name, hid_t dxpl_id) { - H5A_iter_cb1 cb; /* Iterator callback */ - int ret_value=FAIL; /* Return value */ + H5A_iter_cb1 udata; /* Iterator callback info */ + int ret_value = FAIL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5A_get_index) - assert(ent); - assert(name); + HDassert(loc); + HDassert(name); - cb.name=name; - cb.idx=(-1); - if((ret_value=H5O_iterate(ent,H5O_ATTR_ID,H5A_find_idx_by_name,&cb,dxpl_id))<0) + udata.name = name; + udata.idx = (-1); + if((ret_value = H5O_iterate(loc, H5O_ATTR_ID, H5A_find_idx_by_name, &udata, dxpl_id)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "error iterating over attributes") - if(ret_value>0) - ret_value=cb.idx; + if(ret_value > 0) + ret_value = udata.idx; else HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "attribute not found") @@ -420,8 +409,6 @@ done: RETURNS ID of attribute on success, negative on failure - ERRORS - DESCRIPTION This function opens an existing attribute for access. The attribute name specified is used to look up the corresponding attribute for the @@ -429,36 +416,32 @@ done: H5Aclose or resource leaks will develop. The location object may be either a group or a dataset, both of which may have any sort of attribute. - * - * Modifications: - * Robb Matzke, 5 Jun 1998 - * The LOC_ID can also be a named (committed) datatype. --------------------------------------------------------------------------*/ hid_t H5Aopen_name(hid_t loc_id, const char *name) { - H5G_entry_t *ent = NULL; /*Symtab entry of object to attribute*/ - int idx=0; + H5G_loc_t loc; /* Object location */ + int idx; hid_t ret_value; FUNC_ENTER_API(H5Aopen_name, FAIL) H5TRACE2("i","is",loc_id,name); /* check arguments */ - if (H5I_FILE==H5I_get_type(loc_id) || H5I_ATTR==H5I_get_type(loc_id)) + if(H5I_FILE == H5I_get_type(loc_id) || H5I_ATTR == H5I_get_type(loc_id)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute") - if (NULL==(ent=H5G_loc(loc_id))) + if(H5G_loc(loc_id, &loc) < 0) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") - if (!name || !*name) + if(!name || !*name) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") /* Look up the attribute for the object */ - if((idx=H5A_get_index(ent,name, H5AC_dxpl_id))<0) + if((idx = H5A_get_index(loc.oloc, name, H5AC_dxpl_id)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, "attribute not found") /* Go do the real work for opening the attribute */ - if ((ret_value=H5A_open(ent, (unsigned)idx, H5AC_dxpl_id))<0) - HGOTO_ERROR (H5E_ATTR, H5E_CANTINIT, FAIL, "unable to open attribute") + if((ret_value = H5A_open(&loc, (unsigned)idx, H5AC_dxpl_id)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to open attribute") done: FUNC_LEAVE_API(ret_value) @@ -477,8 +460,6 @@ done: RETURNS ID of attribute on success, negative on failure - ERRORS - DESCRIPTION This function opens an existing attribute for access. The attribute index specified is used to look up the corresponding attribute for the @@ -486,30 +467,25 @@ done: H5Aclose or resource leaks will develop. The location object may be either a group or a dataset, both of which may have any sort of attribute. - * - * Modifications: - * Robb Matzke, 5 Jun 1998 - * The LOC_ID can also be a named (committed) datatype. - * --------------------------------------------------------------------------*/ hid_t H5Aopen_idx(hid_t loc_id, unsigned idx) { - H5G_entry_t *ent = NULL; /*Symtab entry of object to attribute */ + H5G_loc_t loc; /* Object location */ hid_t ret_value; FUNC_ENTER_API(H5Aopen_idx, FAIL) H5TRACE2("i","iIu",loc_id,idx); /* check arguments */ - if (H5I_FILE==H5I_get_type(loc_id) || H5I_ATTR==H5I_get_type(loc_id)) + if(H5I_FILE == H5I_get_type(loc_id) || H5I_ATTR == H5I_get_type(loc_id)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute") - if (NULL==(ent=H5G_loc(loc_id))) + if(H5G_loc(loc_id, &loc) < 0) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") /* Go do the real work for opening the attribute */ - if ((ret_value=H5A_open(ent, idx, H5AC_dxpl_id))<0) - HGOTO_ERROR (H5E_ATTR, H5E_CANTINIT, FAIL, "unable to open attribute") + if((ret_value = H5A_open(&loc, idx, H5AC_dxpl_id)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to open attribute") done: FUNC_LEAVE_API(ret_value) @@ -531,15 +507,10 @@ done: * Programmer: Quincey Koziol * April 2, 1998 * - * Modifications: - * - * Pedro Vicente, <pvn@ncsa.uiuc.edu> 22 Aug 2002 - * Added a deep copy of the symbol table entry - * *------------------------------------------------------------------------- */ static hid_t -H5A_open(H5G_entry_t *ent, unsigned idx, hid_t dxpl_id) +H5A_open(H5G_loc_t *loc, unsigned idx, hid_t dxpl_id) { H5A_t *attr = NULL; hid_t ret_value; @@ -547,32 +518,36 @@ H5A_open(H5G_entry_t *ent, unsigned idx, hid_t dxpl_id) FUNC_ENTER_NOAPI_NOINIT(H5A_open) /* check args */ - assert(ent); + HDassert(loc); /* Read in attribute with H5O_read() */ H5_CHECK_OVERFLOW(idx,unsigned,int); - if (NULL==(attr=H5O_read(ent, H5O_ATTR_ID, (int)idx, NULL, dxpl_id))) + if(NULL == (attr = H5O_read(loc->oloc, H5O_ATTR_ID, (int)idx, NULL, dxpl_id))) HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to load attribute info from dataset header") - attr->initialized=1; + attr->initialized = TRUE; /* Deep copy of the symbol table entry */ - if (H5G_ent_copy(&(attr->ent),ent,H5G_COPY_DEEP)<0) + if(H5O_loc_copy(&(attr->oloc), loc->oloc, H5O_COPY_DEEP) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to copy entry") + + /* Deep copy of the group hier. path */ + if(H5G_name_copy(&(attr->path), loc->path, H5G_COPY_DEEP) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to copy entry") /* Hold the symbol table entry (and file) open */ - if (H5O_open(&(attr->ent)) < 0) + if(H5O_open(&(attr->oloc)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open") - attr->ent_opened=1; + attr->obj_opened = TRUE; /* Register the new attribute and get an ID for it */ - if ((ret_value = H5I_register(H5I_ATTR, attr)) < 0) + if((ret_value = H5I_register(H5I_ATTR, attr)) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register attribute for ID") done: - if (ret_value < 0) { + if(ret_value < 0) { if(attr) (void)H5A_close(attr); - } + } /* end if */ FUNC_LEAVE_NOAPI(ret_value) } /* H5A_open() */ @@ -591,8 +566,6 @@ done: RETURNS Non-negative on success/Negative on failure - ERRORS - DESCRIPTION This function writes a complete attribute to disk. --------------------------------------------------------------------------*/ @@ -607,15 +580,15 @@ H5Awrite(hid_t attr_id, hid_t type_id, const void *buf) H5TRACE3("e","iix",attr_id,type_id,buf); /* check arguments */ - if (NULL == (attr = H5I_object_verify(attr_id, H5I_ATTR))) + if(NULL == (attr = H5I_object_verify(attr_id, H5I_ATTR))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute") - if (NULL == (mem_type = H5I_object_verify(type_id, H5I_DATATYPE))) + if(NULL == (mem_type = H5I_object_verify(type_id, H5I_DATATYPE))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype") - if (NULL == buf) + if(NULL == buf) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "null attribute buffer") /* Go write the actual data to the attribute */ - if ((ret_value=H5A_write(attr,mem_type,buf, H5AC_dxpl_id))<0) + if((ret_value = H5A_write(attr,mem_type,buf, H5AC_dxpl_id)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_WRITEERROR, FAIL, "unable to write attribute") done: @@ -636,8 +609,6 @@ done: RETURNS Non-negative on success/Negative on failure - ERRORS - DESCRIPTION This function writes a complete attribute to disk. --------------------------------------------------------------------------*/ @@ -658,41 +629,41 @@ H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf, hid_t dxpl_id) FUNC_ENTER_NOAPI_NOINIT(H5A_write) - assert(attr); - assert(mem_type); - assert(buf); + HDassert(attr); + HDassert(mem_type); + HDassert(buf); /* Create buffer for data to store on disk */ - if((snelmts=H5S_GET_EXTENT_NPOINTS(attr->ds))<0) - HGOTO_ERROR (H5E_ATTR, H5E_CANTCOUNT, FAIL, "dataspace is invalid") - H5_ASSIGN_OVERFLOW(nelmts,snelmts,hssize_t,size_t); + if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->ds)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, FAIL, "dataspace is invalid") + H5_ASSIGN_OVERFLOW(nelmts, snelmts, hssize_t, size_t); - if(nelmts>0) { + if(nelmts > 0) { /* Get the memory and file datatype sizes */ src_type_size = H5T_get_size(mem_type); dst_type_size = H5T_get_size(attr->dt); /* Convert memory buffer into disk buffer */ /* Set up type conversion function */ - if (NULL == (tpath = H5T_path_find(mem_type, attr->dt, NULL, NULL, dxpl_id, FALSE))) + if(NULL == (tpath = H5T_path_find(mem_type, attr->dt, NULL, NULL, dxpl_id, FALSE))) HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dst datatypes") /* Check for type conversion required */ - if (!H5T_path_noop(tpath)) { - if ((src_id = H5I_register(H5I_DATATYPE, H5T_copy(mem_type, H5T_COPY_ALL)))<0 || - (dst_id = H5I_register(H5I_DATATYPE, H5T_copy(attr->dt, H5T_COPY_ALL)))<0) + if(!H5T_path_noop(tpath)) { + if((src_id = H5I_register(H5I_DATATYPE, H5T_copy(mem_type, H5T_COPY_ALL))) < 0 || + (dst_id = H5I_register(H5I_DATATYPE, H5T_copy(attr->dt, H5T_COPY_ALL))) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, FAIL, "unable to register types for conversion") /* Get the maximum buffer size needed and allocate it */ - buf_size=nelmts*MAX(src_type_size,dst_type_size); - if (NULL==(tconv_buf = H5FL_BLK_MALLOC (attr_buf, buf_size)) || NULL==(bkg_buf = H5FL_BLK_CALLOC(attr_buf, buf_size))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + buf_size = nelmts * MAX(src_type_size, dst_type_size); + if(NULL == (tconv_buf = H5FL_BLK_MALLOC (attr_buf, buf_size)) || NULL == (bkg_buf = H5FL_BLK_CALLOC(attr_buf, buf_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") /* Copy the user's data into the buffer for conversion */ - HDmemcpy(tconv_buf,buf,(src_type_size*nelmts)); + HDmemcpy(tconv_buf, buf, (src_type_size * nelmts)); /* Perform datatype conversion */ - if (H5T_convert(tpath, src_id, dst_id, nelmts, (size_t)0, (size_t)0, tconv_buf, bkg_buf, dxpl_id)<0) + if(H5T_convert(tpath, src_id, dst_id, nelmts, (size_t)0, (size_t)0, tconv_buf, bkg_buf, dxpl_id) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "datatype conversion failed") /* Free the previous attribute data buffer, if there is one */ @@ -700,40 +671,40 @@ H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf, hid_t dxpl_id) H5FL_BLK_FREE(attr_buf, attr->data); /* Set the pointer to the attribute data to the converted information */ - attr->data=tconv_buf; + attr->data = tconv_buf; } /* end if */ /* No type conversion necessary */ else { - HDassert(dst_type_size==src_type_size); + HDassert(dst_type_size == src_type_size); /* Allocate the attribute buffer, if there isn't one */ - if(attr->data==NULL) - if (NULL==(attr->data = H5FL_BLK_MALLOC(attr_buf, dst_type_size*nelmts))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + if(attr->data == NULL) + if(NULL == (attr->data = H5FL_BLK_MALLOC(attr_buf, dst_type_size * nelmts))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") /* Copy the attribute data into the user's buffer */ - HDmemcpy(attr->data,buf,(dst_type_size*nelmts)); + HDmemcpy(attr->data, buf, (dst_type_size * nelmts)); } /* end else */ /* Look up the attribute for the object */ - if((idx=H5A_get_index(&(attr->ent),attr->name,dxpl_id))<0) + if((idx = H5A_get_index(&(attr->oloc), attr->name, dxpl_id)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, "attribute not found") /* Modify the attribute data */ - if (H5O_modify(&(attr->ent), H5O_ATTR_ID, idx, 0, H5O_UPDATE_DATA_ONLY|H5O_UPDATE_TIME, attr, dxpl_id) < 0) + if(H5O_modify(&(attr->oloc), H5O_ATTR_ID, idx, 0, H5O_UPDATE_DATA_ONLY|H5O_UPDATE_TIME, attr, dxpl_id) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to update attribute header messages") } /* end if */ /* Indicate the the attribute doesn't need fill-values */ - attr->initialized=TRUE; + attr->initialized = TRUE; done: /* Release resources */ - if (src_id >= 0) + if(src_id >= 0) (void)H5I_dec_ref(src_id); - if (dst_id >= 0) + if(dst_id >= 0) (void)H5I_dec_ref(dst_id); - if (bkg_buf) + if(bkg_buf) H5FL_BLK_FREE(attr_buf, bkg_buf); FUNC_LEAVE_NOAPI(ret_value) @@ -753,8 +724,6 @@ done: RETURNS Non-negative on success/Negative on failure - ERRORS - DESCRIPTION This function reads a complete attribute from disk. --------------------------------------------------------------------------*/ @@ -769,15 +738,15 @@ H5Aread(hid_t attr_id, hid_t type_id, void *buf) H5TRACE3("e","iix",attr_id,type_id,buf); /* check arguments */ - if (NULL == (attr = H5I_object_verify(attr_id, H5I_ATTR))) + if(NULL == (attr = H5I_object_verify(attr_id, H5I_ATTR))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute") - if (NULL == (mem_type = H5I_object_verify(type_id, H5I_DATATYPE))) + if(NULL == (mem_type = H5I_object_verify(type_id, H5I_DATATYPE))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype") - if (NULL == buf) + if(NULL == buf) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "null attribute buffer") /* Go write the actual data to the attribute */ - if ((ret_value=H5A_read(attr,mem_type,buf,H5AC_dxpl_id))<0) + if((ret_value = H5A_read(attr,mem_type,buf,H5AC_dxpl_id)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_READERROR, FAIL, "unable to read attribute") done: @@ -798,8 +767,6 @@ done: RETURNS Non-negative on success/Negative on failure - ERRORS - DESCRIPTION This function reads a complete attribute from disk. --------------------------------------------------------------------------*/ @@ -824,8 +791,8 @@ H5A_read(const H5A_t *attr, const H5T_t *mem_type, void *buf, hid_t dxpl_id) assert(buf); /* Create buffer for data to store on disk */ - if((snelmts=H5S_GET_EXTENT_NPOINTS(attr->ds))<0) - HGOTO_ERROR (H5E_ATTR, H5E_CANTCOUNT, FAIL, "dataspace is invalid") + if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->ds)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, FAIL, "dataspace is invalid") H5_ASSIGN_OVERFLOW(nelmts,snelmts,hssize_t,size_t); if(nelmts>0) { @@ -834,31 +801,31 @@ H5A_read(const H5A_t *attr, const H5T_t *mem_type, void *buf, hid_t dxpl_id) dst_type_size = H5T_get_size(mem_type); /* Check if the attribute has any data yet, if not, fill with zeroes */ - if(attr->ent_opened && !attr->initialized) { + if(attr->obj_opened && !attr->initialized) { HDmemset(buf,0,(dst_type_size*nelmts)); } /* end if */ else { /* Attribute exists and has a value */ /* Convert memory buffer into disk buffer */ /* Set up type conversion function */ - if (NULL == (tpath = H5T_path_find(attr->dt, mem_type, NULL, NULL, dxpl_id, FALSE))) + if(NULL == (tpath = H5T_path_find(attr->dt, mem_type, NULL, NULL, dxpl_id, FALSE))) HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dst datatypes") /* Check for type conversion required */ - if (!H5T_path_noop(tpath)) { - if ((src_id = H5I_register(H5I_DATATYPE, H5T_copy(attr->dt, H5T_COPY_ALL)))<0 || - (dst_id = H5I_register(H5I_DATATYPE, H5T_copy(mem_type, H5T_COPY_ALL)))<0) + if(!H5T_path_noop(tpath)) { + if((src_id = H5I_register(H5I_DATATYPE, H5T_copy(attr->dt, H5T_COPY_ALL))) < 0 || + (dst_id = H5I_register(H5I_DATATYPE, H5T_copy(mem_type, H5T_COPY_ALL))) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, FAIL, "unable to register types for conversion") /* Get the maximum buffer size needed and allocate it */ - buf_size=nelmts*MAX(src_type_size,dst_type_size); - if (NULL==(tconv_buf = H5FL_BLK_MALLOC(attr_buf, buf_size)) || NULL==(bkg_buf = H5FL_BLK_CALLOC(attr_buf, buf_size))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + buf_size = nelmts*MAX(src_type_size,dst_type_size); + if(NULL == (tconv_buf = H5FL_BLK_MALLOC(attr_buf, buf_size)) || NULL == (bkg_buf = H5FL_BLK_CALLOC(attr_buf, buf_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") /* Copy the attribute data into the buffer for conversion */ HDmemcpy(tconv_buf,attr->data,(src_type_size*nelmts)); /* Perform datatype conversion. */ - if (H5T_convert(tpath, src_id, dst_id, nelmts, (size_t)0, (size_t)0, tconv_buf, bkg_buf, dxpl_id)<0) + if(H5T_convert(tpath, src_id, dst_id, nelmts, (size_t)0, (size_t)0, tconv_buf, bkg_buf, dxpl_id) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "datatype conversion failed") /* Copy the converted data into the user's buffer */ @@ -866,7 +833,7 @@ H5A_read(const H5A_t *attr, const H5T_t *mem_type, void *buf, hid_t dxpl_id) } /* end if */ /* No type conversion necessary */ else { - HDassert(dst_type_size==src_type_size); + HDassert(dst_type_size == src_type_size); /* Copy the attribute data into the user's buffer */ HDmemcpy(buf,attr->data,(dst_type_size*nelmts)); @@ -876,13 +843,13 @@ H5A_read(const H5A_t *attr, const H5T_t *mem_type, void *buf, hid_t dxpl_id) done: /* Release resources */ - if (src_id >= 0) + if(src_id >= 0) (void)H5I_dec_ref(src_id); - if (dst_id >= 0) + if(dst_id >= 0) (void)H5I_dec_ref(dst_id); - if (tconv_buf) + if(tconv_buf) H5FL_BLK_FREE(attr_buf, tconv_buf); - if (bkg_buf) + if(bkg_buf) H5FL_BLK_FREE(attr_buf, bkg_buf); FUNC_LEAVE_NOAPI(ret_value) @@ -900,8 +867,6 @@ done: RETURNS A dataspace ID on success, negative on failure - ERRORS - DESCRIPTION This function retrieves a copy of the dataspace for an attribute. The dataspace ID returned from this function must be released with H5Sclose @@ -918,16 +883,16 @@ H5Aget_space(hid_t attr_id) H5TRACE1("i","i",attr_id); /* check arguments */ - if (NULL == (attr = H5I_object_verify(attr_id, H5I_ATTR))) + if(NULL == (attr = H5I_object_verify(attr_id, H5I_ATTR))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute") /* Copy the attribute's dataspace */ - if (NULL==(dst=H5S_copy (attr->ds, FALSE))) - HGOTO_ERROR (H5E_ATTR, H5E_CANTINIT, FAIL, "unable to copy dataspace") + if(NULL == (dst = H5S_copy (attr->ds, FALSE))) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to copy dataspace") /* Atomize */ - if ((ret_value=H5I_register (H5I_DATASPACE, dst))<0) - HGOTO_ERROR (H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace atom") + if((ret_value = H5I_register (H5I_DATASPACE, dst)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace atom") done: FUNC_LEAVE_API(ret_value) @@ -945,19 +910,10 @@ done: RETURNS A datatype ID on success, negative on failure - ERRORS - DESCRIPTION This function retrieves a copy of the datatype for an attribute. The datatype ID returned from this function must be released with H5Tclose or resource leaks will develop. - * - * Modifications: - * Robb Matzke, 4 Jun 1998 - * The datatype is reopened if it's a named type before returning it to - * the application. The datatypes returned by this function are always - * read-only. If an error occurs when atomizing the return datatype - * then the datatype is closed. --------------------------------------------------------------------------*/ hid_t H5Aget_type(hid_t attr_id) @@ -970,7 +926,7 @@ H5Aget_type(hid_t attr_id) H5TRACE1("i","i",attr_id); /* check arguments */ - if (NULL == (attr = H5I_object_verify(attr_id, H5I_ATTR))) + if(NULL == (attr = H5I_object_verify(attr_id, H5I_ATTR))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute") /* @@ -978,21 +934,21 @@ H5Aget_type(hid_t attr_id) * reopen the type before returning it to the user. Make the type * read-only. */ - if (NULL==(dst=H5T_copy(attr->dt, H5T_COPY_REOPEN))) + if(NULL == (dst = H5T_copy(attr->dt, H5T_COPY_REOPEN))) HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to copy datatype") /* Mark any datatypes as being in memory now */ - if (H5T_set_loc(dst, NULL, H5T_LOC_MEMORY)<0) + if(H5T_set_loc(dst, NULL, H5T_LOC_MEMORY) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location") - if (H5T_lock(dst, FALSE)<0) + if(H5T_lock(dst, FALSE) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to lock transient datatype") /* Atomize */ - if ((ret_value=H5I_register(H5I_DATATYPE, dst))<0) + if((ret_value = H5I_register(H5I_DATATYPE, dst)) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register datatype atom") done: - if(ret_value<0) { + if(ret_value < 0) { if(dst!=NULL) (void)H5T_close(dst); } /* end if */ @@ -1015,8 +971,6 @@ done: This function returns the length of the attribute's name (which may be longer than 'buf_size') on success or negative for failure. - ERRORS - DESCRIPTION This function retrieves the name of an attribute for an attribute ID. Up to 'buf_size' characters are stored in 'buf' followed by a '\0' string @@ -1035,9 +989,9 @@ H5Aget_name(hid_t attr_id, size_t buf_size, char *buf) H5TRACE3("Zs","izs",attr_id,buf_size,buf); /* check arguments */ - if (NULL == (attr = H5I_object_verify(attr_id, H5I_ATTR))) + if(NULL == (attr = H5I_object_verify(attr_id, H5I_ATTR))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute") - if (!buf && buf_size) + if(!buf && buf_size) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid buffer") /* get the real attribute length */ @@ -1085,14 +1039,14 @@ done: hsize_t H5Aget_storage_size(hid_t attr_id) { - H5A_t *attr=NULL; + H5A_t *attr = NULL; hsize_t ret_value; /* Return value */ FUNC_ENTER_API(H5Aget_storage_size, 0) H5TRACE1("h","i",attr_id); /* Check args */ - if (NULL==(attr=H5I_object_verify(attr_id, H5I_ATTR))) + if(NULL == (attr = H5I_object_verify(attr_id, H5I_ATTR))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not an attribute") /* Set return value */ @@ -1148,20 +1102,14 @@ H5A_get_storage_size(const H5A_t *attr) RETURNS Number of attributes on success, negative on failure - ERRORS - DESCRIPTION This function returns the number of attributes attached to a dataset or group, 'location_id'. - * - * Modifications: - * Robb Matzke, 5 Jun 1998 - * The LOC_ID can also be a named (committed) datatype. --------------------------------------------------------------------------*/ int H5Aget_num_attrs(hid_t loc_id) { - H5G_entry_t *ent = NULL; /*symtab ent of object to attribute */ + H5O_loc_t *loc = NULL; /* Object location for attribute */ void *obj = NULL; int ret_value; @@ -1169,27 +1117,30 @@ H5Aget_num_attrs(hid_t loc_id) H5TRACE1("Is","i",loc_id); /* check arguments */ - if (H5I_FILE==H5I_get_type(loc_id) || H5I_ATTR==H5I_get_type(loc_id)) + if(H5I_FILE == H5I_get_type(loc_id) || H5I_ATTR == H5I_get_type(loc_id)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute") if(NULL == (obj = H5I_object(loc_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADATOM, FAIL, "illegal object atom") switch (H5I_get_type (loc_id)) { case H5I_DATASET: - ent = H5D_entof ((H5D_t*)obj); + loc = H5D_oloc((H5D_t*)obj); break; + case H5I_DATATYPE: - if (NULL==(ent=H5T_entof ((H5T_t*)obj))) - HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "target datatype is not committed") + if(NULL == (loc = H5T_oloc((H5T_t*)obj))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "target datatype is not committed") break; + case H5I_GROUP: - ent = H5G_entof ((H5G_t*)obj); + loc = H5G_oloc((H5G_t*)obj); break; + default: - HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "inappropriate attribute target") + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "inappropriate attribute target") } /*lint !e788 All appropriate cases are covered */ /* Look up the attribute for the object */ - ret_value=H5O_count(ent, H5O_ATTR_ID, H5AC_ind_dxpl_id); + ret_value = H5O_count(loc, H5O_ATTR_ID, H5AC_ind_dxpl_id); done: FUNC_LEAVE_API(ret_value) @@ -1202,35 +1153,33 @@ done: * Purpose: Rename an attribute * * Return: Success: Non-negative - * * Failure: Negative * * Programmer: Raymond Lu * October 23, 2002 * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t H5Arename(hid_t loc_id, const char *old_name, const char *new_name) { - H5G_entry_t *ent = NULL; /*symtab ent of object to attribute */ - herr_t ret_value; /* Return value */ + H5G_loc_t loc; /* Object location */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(H5Arename, FAIL) H5TRACE3("e","iss",loc_id,old_name,new_name); /* check arguments */ - if (!old_name || !new_name) + if(!old_name || !new_name) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "name is nil") - if (H5I_FILE==H5I_get_type(loc_id) || H5I_ATTR==H5I_get_type(loc_id)) + if(H5I_FILE == H5I_get_type(loc_id) || H5I_ATTR == H5I_get_type(loc_id)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute") - if (NULL==(ent=H5G_loc(loc_id))) + if(H5G_loc(loc_id, & loc) < 0) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") /* Call private function */ - ret_value = H5A_rename(ent, old_name, new_name, H5AC_dxpl_id); + if(H5A_rename(loc.oloc, old_name, new_name, H5AC_dxpl_id) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTRENAME, FAIL, "can't rename attribute") done: FUNC_LEAVE_API(ret_value) @@ -1243,46 +1192,43 @@ done: * Purpose: Private function for H5Arename. Rename an attribute * * Return: Success: Non-negative - * * Failure: Negative * * Programmer: Raymond Lu * October 23, 2002 * - * Modifications: - * *------------------------------------------------------------------------- */ static herr_t -H5A_rename(H5G_entry_t *ent, const char *old_name, const char *new_name, hid_t dxpl_id) +H5A_rename(H5O_loc_t *loc, const char *old_name, const char *new_name, hid_t dxpl_id) { - int seq, idx=FAIL; /* Index of attribute being querried */ - H5A_t found_attr; /* Attribute with OLD_NAME */ - herr_t ret_value=SUCCEED; /* Return value */ + int seq, idx = FAIL; /* Index of attribute being querried */ + H5A_t found_attr; /* Attribute with OLD_NAME */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5A_rename) /* Check arguments */ - assert(ent); - assert(old_name); - assert(new_name); + HDassert(loc); + HDassert(old_name); + HDassert(new_name); /* Read in the existing attributes to check for duplicates */ - seq=0; - while(H5O_read(ent, H5O_ATTR_ID, seq, &found_attr, dxpl_id)!=NULL) { + seq = 0; + while(H5O_read(loc, H5O_ATTR_ID, seq, &found_attr, dxpl_id) != NULL) { /* * Compare found attribute name. */ - if(HDstrcmp(found_attr.name,old_name)==0) { + if(HDstrcmp(found_attr.name, old_name) == 0) { idx = seq; break; } - if(H5O_reset (H5O_ATTR_ID, &found_attr)<0) + if(H5O_reset(H5O_ATTR_ID, &found_attr) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "can't release attribute info") seq++; - } + } /* end while */ H5E_clear_stack(NULL); - if(idx<0) + if(idx < 0) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "attribute cannot be found") /* Copy the attribute name. */ @@ -1293,20 +1239,20 @@ H5A_rename(H5G_entry_t *ent, const char *old_name, const char *new_name, hid_t d HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "String copy failed") /* Indicate entry is not opened and the attribute doesn't need fill-values. */ - found_attr.ent_opened=FALSE; - found_attr.initialized=TRUE; + found_attr.obj_opened = FALSE; + found_attr.initialized = TRUE; /* Modify the attribute message */ - if (H5O_modify(ent, H5O_ATTR_ID, idx, 0, H5O_UPDATE_TIME, &found_attr, dxpl_id) < 0) + if(H5O_modify(loc, H5O_ATTR_ID, idx, 0, H5O_UPDATE_TIME, &found_attr, dxpl_id) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to update attribute header messages") /* Close the attribute */ - if(H5A_free(&found_attr)<0) + if(H5A_free(&found_attr) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "unable to close renamed attribute") done: FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5A_rename() */ /*-------------------------------------------------------------------------- @@ -1324,8 +1270,6 @@ done: Returns a negative value if something is wrong, the return value of the last operator if it was non-zero, or zero if all attributes were processed. - ERRORS - DESCRIPTION This function interates over the attributes of dataset or group specified with 'loc_id'. For each attribute of the object, the @@ -1345,31 +1289,22 @@ done: C. Negative causes the iterator to immediately return that value, indicating failure. The iterator can be restarted at the next attribute. - * - * Modifications: - * Robb Matzke, 5 Jun 1998 - * The LOC_ID can also be a named (committed) datatype. - * - * Robb Matzke, 5 Jun 1998 - * Like the group iterator, if ATTR_NUM is the null pointer then all - * attributes are processed. - * --------------------------------------------------------------------------*/ herr_t H5Aiterate(hid_t loc_id, unsigned *attr_num, H5A_operator_t op, void *op_data) { - H5G_entry_t *ent = NULL; /*symtab ent of object to attribute */ + H5G_loc_t loc; /* Object location */ H5A_t found_attr; + int idx, start_idx; herr_t ret_value = 0; - int idx, start_idx; FUNC_ENTER_API(H5Aiterate, FAIL) H5TRACE4("e","i*Iuxx",loc_id,attr_num,op,op_data); /* check arguments */ - if (H5I_FILE==H5I_get_type(loc_id) || H5I_ATTR==H5I_get_type(loc_id)) + if(H5I_FILE == H5I_get_type(loc_id) || H5I_ATTR == H5I_get_type(loc_id)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute") - if (NULL==(ent=H5G_loc(loc_id))) + if(H5G_loc(loc_id, &loc) < 0) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") /* @@ -1377,29 +1312,29 @@ H5Aiterate(hid_t loc_id, unsigned *attr_num, H5A_operator_t op, void *op_data) * reasonable. */ start_idx = idx = (attr_num ? (int)*attr_num : 0); - if (idx<0) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified") - if(idx<H5O_count(ent, H5O_ATTR_ID, H5AC_dxpl_id)) { - while(H5O_read(ent, H5O_ATTR_ID, idx++, &found_attr, H5AC_dxpl_id)!=NULL) { + if(idx < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified") + if(idx < H5O_count(loc.oloc, H5O_ATTR_ID, H5AC_dxpl_id)) { + while(H5O_read(loc.oloc, H5O_ATTR_ID, idx++, &found_attr, H5AC_dxpl_id) != NULL) { /* * Compare found attribute name to new attribute name reject * creation if names are the same. */ - if((ret_value=(op)(loc_id,found_attr.name,op_data))!=0) { - if(H5O_reset (H5O_ATTR_ID, &found_attr)<0) + if((ret_value = (op)(loc_id,found_attr.name,op_data)) != 0) { + if(H5O_reset(H5O_ATTR_ID, &found_attr) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "can't release attribute info") break; - } - if(H5O_reset (H5O_ATTR_ID, &found_attr)<0) + } /* end if */ + if(H5O_reset(H5O_ATTR_ID, &found_attr) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "can't release attribute info") - } + } /* end while */ H5E_clear_stack(NULL); - } + } /* end if */ else if(start_idx>0) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified") + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified") - if (attr_num) + if(attr_num) *attr_num = (unsigned)idx; done: @@ -1419,23 +1354,16 @@ done: RETURNS Non-negative on success/Negative on failure - ERRORS - DESCRIPTION This function removes the named attribute from a dataset or group. This function should not be used when attribute IDs are open on 'loc_id' as it may cause the internal indexes of the attributes to change and future writes to the open attributes to produce incorrect results. - * - * Modifications: - * Robb Matzke, 5 Jun 1998 - * The LOC_ID can also be a named (committed) datatype. - * --------------------------------------------------------------------------*/ herr_t H5Adelete(hid_t loc_id, const char *name) { - H5G_entry_t *ent = NULL; /*symtab ent of object to attribute */ + H5G_loc_t loc; /* Object location */ int found; herr_t ret_value; @@ -1443,19 +1371,19 @@ H5Adelete(hid_t loc_id, const char *name) H5TRACE2("e","is",loc_id,name); /* check arguments */ - if (H5I_FILE==H5I_get_type(loc_id) || H5I_ATTR==H5I_get_type(loc_id)) + if(H5I_FILE == H5I_get_type(loc_id) || H5I_ATTR == H5I_get_type(loc_id)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute") - if (NULL==(ent=H5G_loc(loc_id))) + if(H5G_loc(loc_id, &loc) < 0) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") - if (!name || !*name) + if(!name || !*name) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") /* Look up the attribute index for the object */ - if((found=H5A_get_index(ent,name,H5AC_dxpl_id))<0) + if((found = H5A_get_index(loc.oloc, name, H5AC_dxpl_id)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "attribute not found") /* Delete the attribute from the location */ - if ((ret_value=H5O_remove(ent, H5O_ATTR_ID, found, TRUE, H5AC_dxpl_id)) < 0) + if((ret_value = H5O_remove(loc.oloc, H5O_ATTR_ID, found, TRUE, H5AC_dxpl_id)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute header message") done: @@ -1474,8 +1402,6 @@ done: RETURNS Non-negative on success/Negative on failure - ERRORS - DESCRIPTION This function releases an attribute from use. Further use of the attribute ID will result in undefined behavior. @@ -1483,17 +1409,17 @@ done: herr_t H5Aclose(hid_t attr_id) { - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(H5Aclose, FAIL) H5TRACE1("e","i",attr_id); /* check arguments */ - if (NULL == H5I_object_verify(attr_id, H5I_ATTR)) + if(NULL == H5I_object_verify(attr_id, H5I_ATTR)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute") /* Decrement references to that atom (and close it) */ - if(H5I_dec_ref (attr_id)<0) + if(H5I_dec_ref (attr_id) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "can't close attribute") done: @@ -1520,9 +1446,9 @@ done: H5A_t * H5A_copy(H5A_t *_new_attr, const H5A_t *old_attr, unsigned update_flags) { - H5A_t *new_attr=NULL; - hbool_t allocated_attr=FALSE; /* Whether the attribute was allocated */ - H5A_t *ret_value=NULL; /* Return value */ + H5A_t *new_attr = NULL; + hbool_t allocated_attr = FALSE; /* Whether the attribute was allocated */ + H5A_t *ret_value = NULL; /* Return value */ FUNC_ENTER_NOAPI(H5A_copy, NULL) @@ -1530,13 +1456,13 @@ H5A_copy(H5A_t *_new_attr, const H5A_t *old_attr, unsigned update_flags) assert(old_attr); /* get space */ - if(_new_attr==NULL) { + if(_new_attr == NULL) { /* Sanity check - We should not be only updating data if we don'y have anything */ HDassert(!(update_flags&H5O_UPDATE_DATA_ONLY)); - if (NULL==(new_attr = H5FL_MALLOC(H5A_t))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - allocated_attr=TRUE; + if(NULL == (new_attr = H5FL_MALLOC(H5A_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + allocated_attr = TRUE; } /* end if */ else new_attr=_new_attr; @@ -1546,26 +1472,26 @@ H5A_copy(H5A_t *_new_attr, const H5A_t *old_attr, unsigned update_flags) *new_attr = *old_attr; /* Don't open the object header for a copy */ - new_attr->ent_opened=0; + new_attr->obj_opened = FALSE; /* Copy the guts of the attribute */ - new_attr->name=HDstrdup(old_attr->name); - new_attr->dt=H5T_copy(old_attr->dt, H5T_COPY_ALL); - new_attr->ds=H5S_copy(old_attr->ds, FALSE); + new_attr->name = HDstrdup(old_attr->name); + new_attr->dt = H5T_copy(old_attr->dt, H5T_COPY_ALL); + new_attr->ds = H5S_copy(old_attr->ds, FALSE); } /* end if */ if(old_attr->data) { - if(!(update_flags&H5O_UPDATE_DATA_ONLY) || new_attr->data==NULL) { - if (NULL==(new_attr->data=H5FL_BLK_MALLOC(attr_buf,old_attr->data_size))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + if(!(update_flags&H5O_UPDATE_DATA_ONLY) || new_attr->data == NULL) { + if(NULL == (new_attr->data = H5FL_BLK_MALLOC(attr_buf,old_attr->data_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") } /* end if */ HDmemcpy(new_attr->data,old_attr->data,old_attr->data_size); } /* end if */ /* Set the return value */ - ret_value=new_attr; + ret_value = new_attr; done: - if(ret_value==NULL) { + if(ret_value == NULL) { if(new_attr!=NULL && allocated_attr) (void)H5A_close(new_attr); } /* end if */ @@ -1592,7 +1518,7 @@ done: herr_t H5A_free(H5A_t *attr) { - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5A_free, FAIL) @@ -1602,10 +1528,10 @@ H5A_free(H5A_t *attr) if(attr->name) H5MM_xfree(attr->name); if(attr->dt) - if(H5T_close(attr->dt)<0) + if(H5T_close(attr->dt) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release datatype info") if(attr->ds) - if(H5S_close(attr->ds)<0) + if(H5S_close(attr->ds) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release dataspace info") if(attr->data) H5FL_BLK_FREE(attr_buf, attr->data); @@ -1632,20 +1558,20 @@ done: herr_t H5A_close(H5A_t *attr) { - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5A_close, FAIL) - assert(attr); + HDassert(attr); /* Check if the attribute has any data yet, if not, fill with zeroes */ - if(attr->ent_opened && !attr->initialized) { - uint8_t *tmp_buf=H5FL_BLK_CALLOC(attr_buf, attr->data_size); - if (NULL == tmp_buf) + if(attr->obj_opened && !attr->initialized) { + uint8_t *tmp_buf = H5FL_BLK_CALLOC(attr_buf, attr->data_size); + if(NULL == tmp_buf) HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "memory allocation failed for attribute fill-value") /* Go write the fill data to the attribute */ - if (H5A_write(attr,attr->dt,tmp_buf,H5AC_dxpl_id)<0) + if(H5A_write(attr, attr->dt, tmp_buf, H5AC_dxpl_id) < 0) HGOTO_ERROR(H5E_ATTR, H5E_WRITEERROR, FAIL, "unable to write attribute") /* Free temporary buffer */ @@ -1653,14 +1579,18 @@ H5A_close(H5A_t *attr) } /* end if */ /* Free dynamicly allocated items */ - if(H5A_free(attr)<0) + if(H5A_free(attr) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release attribute info") /* Close the object's symbol-table entry */ - if(attr->ent_opened) - if(H5O_close(&(attr->ent))<0) + if(attr->obj_opened) + if(H5O_close(&(attr->oloc)) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release object header info") + /* Release the group hier. path for the object the attribute is on */ + if(H5G_name_free(&(attr->path)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release group hier. path") + H5FL_FREE(H5A_t, attr); done: @@ -1669,34 +1599,65 @@ done: /*------------------------------------------------------------------------- - * Function: H5A_entof + * Function: H5A_oloc * - * Purpose: Return the symbol table entry for an attribute. It's the - * symbol table entry for the object to which the attribute + * Purpose: Return the object location for an attribute. It's the + * object location for the object to which the attribute * belongs, not the attribute itself. * * Return: Success: Ptr to entry - * * Failure: NULL * * Programmer: Robb Matzke * Thursday, August 6, 1998 * - * Modifications: + *------------------------------------------------------------------------- + */ +H5O_loc_t * +H5A_oloc(H5A_t *attr) +{ + H5O_loc_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5A_oloc, NULL) + + HDassert(attr); + + /* Set return value */ + ret_value = &(attr->oloc); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5A_oloc() */ + + +/*------------------------------------------------------------------------- + * Function: H5A_nameof + * + * Purpose: Return the group hier. path for an attribute. It's the + * group hier. path for the object to which the attribute + * belongs, not the attribute itself. + * + * Return: Success: Ptr to entry + * Failure: NULL + * + * Programmer: Quincey Koziol + * Monday, September 12, 2005 * *------------------------------------------------------------------------- */ -H5G_entry_t * -H5A_entof(H5A_t *attr) +H5G_name_t * +H5A_nameof(H5A_t *attr) { - H5G_entry_t *ret_value; /* Return value */ + H5G_name_t *ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5A_entof, NULL) - assert(attr); + FUNC_ENTER_NOAPI(H5A_nameof, NULL) + + HDassert(attr); /* Set return value */ - ret_value=&(attr->ent); + ret_value=&(attr->path); done: FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5A_nameof() */ + diff --git a/src/H5Apkg.h b/src/H5Apkg.h index 753ad64..cfe22ea 100644 --- a/src/H5Apkg.h +++ b/src/H5Apkg.h @@ -39,13 +39,15 @@ /* Other private headers needed by this file */ #include "H5FLprivate.h" /* Free Lists */ +#include "H5Oprivate.h" /* Object headers */ #include "H5Sprivate.h" /* Dataspace */ #include "H5Tprivate.h" /* Datatype functions */ struct H5A_t { - unsigned initialized;/* Indicate whether the attribute has been modified */ - unsigned ent_opened; /* Object header entry opened? */ - H5G_entry_t ent; /* Object Header entry (for both datasets & groups) */ + hbool_t initialized;/* Indicate whether the attribute has been modified */ + hbool_t obj_opened; /* Object header entry opened? */ + H5O_loc_t oloc; /* Object location for object attribute is on */ + H5G_name_t path; /* Group hierarchy path */ char *name; /* Attribute's name */ H5T_t *dt; /* Attribute's datatype */ size_t dt_size; /* Size of datatype on disk */ diff --git a/src/H5Aprivate.h b/src/H5Aprivate.h index 8d694bc..9b24490 100644 --- a/src/H5Aprivate.h +++ b/src/H5Aprivate.h @@ -28,6 +28,7 @@ typedef struct H5A_t H5A_t; /* Library private functions in package */ -H5_DLL H5G_entry_t *H5A_entof(H5A_t *attr); +H5_DLL struct H5O_loc_t *H5A_oloc(H5A_t *attr); +H5_DLL H5G_name_t *H5A_nameof(H5A_t *attr); #endif @@ -96,8 +96,7 @@ static herr_t H5B2_swap_leaf(H5F_t *f, hid_t dxpl_id, unsigned depth, H5B2_internal_t *internal, unsigned *internal_flags_ptr, unsigned idx, void *swap_loc); static herr_t H5B2_insert_internal(H5F_t *f, hid_t dxpl_id, - H5RC_t *bt2_shared, unsigned depth, H5AC_info_t *parent_cache_info, - unsigned *parent_cache_info_flags_ptr, + H5RC_t *bt2_shared, unsigned depth, unsigned *parent_cache_info_flags_ptr, H5B2_node_ptr_t *curr_node_ptr, void *udata); static herr_t H5B2_insert_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, H5B2_node_ptr_t *curr_node_ptr, void *udata); @@ -2476,8 +2475,7 @@ done: */ static herr_t H5B2_insert_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, - unsigned depth, H5AC_info_t *parent_cache_info, - unsigned *parent_cache_info_flags_ptr, + unsigned depth, unsigned *parent_cache_info_flags_ptr, H5B2_node_ptr_t *curr_node_ptr, void *udata) { H5B2_internal_t *internal; /* Pointer to internal node */ @@ -2492,7 +2490,6 @@ H5B2_insert_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, HDassert(f); HDassert(bt2_shared); HDassert(depth>0); - HDassert(parent_cache_info); HDassert(parent_cache_info_flags_ptr); HDassert(curr_node_ptr); HDassert(H5F_addr_defined(curr_node_ptr->addr)); @@ -2583,8 +2580,7 @@ H5B2_insert_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, /* Attempt to insert node */ if(depth>1) { - if(H5B2_insert_internal(f,dxpl_id,bt2_shared,depth-1,&internal->cache_info,&internal_flags, - &internal->node_ptrs[idx],udata)<0) + if(H5B2_insert_internal(f, dxpl_id, bt2_shared, depth-1, &internal_flags, &internal->node_ptrs[idx], udata) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into B-tree internal node") } /* end if */ else { @@ -2670,7 +2666,7 @@ H5B2_insert(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr, /* Attempt to insert record into B-tree */ if(bt2->depth>0) { - if(H5B2_insert_internal(f,dxpl_id,bt2->shared,bt2->depth,&(bt2->cache_info),&bt2_flags,&bt2->root,udata)<0) + if(H5B2_insert_internal(f, dxpl_id, bt2->shared, bt2->depth, &bt2_flags, &bt2->root, udata) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into B-tree internal node") } /* end if */ else { @@ -62,9 +62,9 @@ typedef struct { /* General stuff */ static herr_t H5D_init_storage(H5D_t *dataset, hbool_t full_overwrite, hid_t dxpl_id); static H5D_shared_t * H5D_new(hid_t dcpl_id, hbool_t creating, hbool_t vl_type); -static H5D_t * H5D_create(H5G_entry_t *loc, const char *name, hid_t type_id, +static H5D_t * H5D_create(H5G_loc_t *loc, const char *name, hid_t type_id, const H5S_t *space, hid_t dcpl_id, hid_t dxpl_id); -static H5D_t * H5D_open_oid(const H5G_entry_t *ent, hid_t dxpl_id); +static herr_t H5D_open_oid(H5D_t *dataset, hid_t dxpl_id); static herr_t H5D_get_space_status(H5D_t *dset, H5D_space_status_t *allocation, hid_t dxpl_id); static hsize_t H5D_get_storage_size(H5D_t *dset, hid_t dxpl_id); static haddr_t H5D_get_offset(const H5D_t *dset); @@ -1162,7 +1162,7 @@ hid_t H5Dcreate(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id, hid_t dcpl_id) { - H5G_entry_t *loc; /* Entry for group to insert dataset into */ + H5G_loc_t loc; /* Object location to insert dataset into */ H5D_t *new_dset = NULL; /* New dataset's info */ const H5S_t *space; /* Dataspace for dataset */ hid_t ret_value; /* Return value */ @@ -1171,7 +1171,7 @@ H5Dcreate(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id, H5TRACE5("i","isiii",loc_id,name,type_id,space_id,dcpl_id); /* Check arguments */ - if(NULL == (loc = H5G_loc(loc_id))) + if(H5G_loc(loc_id, &loc) < 0) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location ID") if(!name || !*name) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") @@ -1186,11 +1186,11 @@ H5Dcreate(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id, HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not dataset create property list ID") /* build and open the new dataset */ - if (NULL == (new_dset = H5D_create(loc, name, type_id, space, dcpl_id, H5AC_dxpl_id))) + if(NULL == (new_dset = H5D_create(&loc, name, type_id, space, dcpl_id, H5AC_dxpl_id))) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create dataset") /* Register the new dataset to get an ID for it */ - if ((ret_value = H5I_register(H5I_DATASET, new_dset)) < 0) + if((ret_value = H5I_register(H5I_DATASET, new_dset)) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register dataset") done: @@ -1225,8 +1225,10 @@ hid_t H5Dopen(hid_t loc_id, const char *name) { H5D_t *dset = NULL; - H5G_entry_t *loc = NULL; /*location holding the dataset */ - H5G_entry_t ent; /*dataset symbol table entry */ + H5G_loc_t loc; /* Object location of group */ + H5G_loc_t dset_loc; /* Object location of dataset */ + H5G_name_t path; /* Dataset group hier. path */ + H5O_loc_t oloc; /* Dataset object location */ hbool_t ent_found = FALSE; /* Entry at 'name' found */ hid_t dxpl_id = H5AC_dxpl_id; /* dxpl to use to open datset */ hid_t ret_value; @@ -1235,26 +1237,33 @@ H5Dopen(hid_t loc_id, const char *name) H5TRACE2("i","is",loc_id,name); /* Check args */ - if (NULL == (loc = H5G_loc(loc_id))) + if(H5G_loc(loc_id, &loc) < 0) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") - if (!name || !*name) + if(!name || !*name) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") + /* Set up dataset location to fill in */ + dset_loc.oloc = &oloc; + dset_loc.path = &path; + H5G_loc_reset(&dset_loc); + /* Find the dataset object */ - if (H5G_find(loc, name, &ent, dxpl_id) < 0) + if(H5G_loc_find(&loc, name, &dset_loc, dxpl_id) < 0) HGOTO_ERROR(H5E_DATASET, H5E_NOTFOUND, FAIL, "not found") ent_found = TRUE; /* Check that the object found is the correct type */ - if (H5G_get_type(&ent, dxpl_id) != H5G_DATASET) + if(H5O_obj_type(&oloc, dxpl_id) != H5G_DATASET) HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, FAIL, "not a dataset") /* Open the dataset */ - if ((dset = H5D_open(&ent, dxpl_id))==NULL) + if((dset = H5D_open(&dset_loc, dxpl_id)) == NULL) { + ent_found = FALSE; /* Reset this, since H5D_open 'owns' it and then free's it on failure */ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't open dataset") + } /* end if */ /* Register an atom for the dataset */ - if((ret_value=H5I_register(H5I_DATASET, dset)) <0) + if((ret_value = H5I_register(H5I_DATASET, dset)) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "can't register dataset atom") done: @@ -1264,12 +1273,13 @@ done: HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataset") } /* end if */ else { - if(ent_found && ent.header) - H5G_free_ent_name(&ent); + if(ent_found) + H5G_name_free(&path); } /* end else */ } /* end if */ + FUNC_LEAVE_API(ret_value) -} +} /* end H5Dopen() */ /*------------------------------------------------------------------------- @@ -1289,28 +1299,26 @@ done: herr_t H5Dclose(hid_t dset_id) { - H5D_t *dset = NULL; /* Dataset object to release */ - herr_t ret_value=SUCCEED; /* Return value */ + H5D_t *dset; /* Dataset object to release */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(H5Dclose, FAIL) H5TRACE1("e","i",dset_id); /* Check args */ - if (NULL == (dset = H5I_object_verify(dset_id, H5I_DATASET))) + if(NULL == (dset = H5I_object_verify(dset_id, H5I_DATASET))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") - if (NULL == dset->ent.file) - HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, FAIL, "not a dataset") /* * Decrement the counter on the dataset. It will be freed if the count * reaches zero. */ - if (H5I_dec_ref(dset_id) < 0) + if(H5I_dec_ref(dset_id) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't free") done: FUNC_LEAVE_API(ret_value) -} +} /* end H5Dclose() */ /*------------------------------------------------------------------------- @@ -1466,9 +1474,9 @@ done: /*------------------------------------------------------------------------- * Function: H5Dget_type * - * Purpose: Returns a copy of the file data type for a dataset. + * Purpose: Returns a copy of the file datatype for a dataset. * - * Return: Success: ID for a copy of the data type. The data + * Return: Success: ID for a copy of the datatype. The data * type should be released by calling * H5Tclose(). * @@ -1494,9 +1502,9 @@ H5Dget_type(hid_t dset_id) if (NULL==(dset=H5I_object_verify(dset_id, H5I_DATASET))) HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") - /* Copy the data type and mark it read-only */ + /* Copy the datatype and mark it read-only */ if (NULL==(copied_type=H5T_copy (dset->shared->type, H5T_COPY_REOPEN))) - HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to copy the data type") + HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to copy the datatype") /* Mark any datatypes as being in memory now */ if (H5T_set_loc(copied_type, NULL, H5T_LOC_MEMORY)<0) @@ -1504,11 +1512,11 @@ H5Dget_type(hid_t dset_id) /* Unlock copied type */ if (H5T_lock (copied_type, FALSE)<0) - HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to lock transient data type") + HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to lock transient datatype") /* Create an atom */ if ((ret_value=H5I_register (H5I_DATATYPE, copied_type))<0) - HGOTO_ERROR (H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register data type") + HGOTO_ERROR (H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register datatype") done: if(ret_value<0) { @@ -1570,7 +1578,7 @@ H5Dget_create_plist(hid_t dset_id) /* Copy the dataset type into the fill value message */ if(copied_fill.type==NULL) if(NULL==(copied_fill.type=H5T_copy(dset->shared->type, H5T_COPY_TRANSIENT))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to copy dataset data type for fill value") + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to copy dataset datatype for fill value") /* Set back the fill value property to property list */ if(H5P_set(new_plist, H5D_CRT_FILL_VALUE_NAME, &copied_fill) < 0) @@ -1777,7 +1785,7 @@ static herr_t H5D_update_entry_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset, H5P_genplist_t *plist) { size_t ohdr_size = H5D_MINHDR_SIZE; /* Size of dataset's object header */ - H5G_entry_t *ent=NULL; /* Dataset's group entry */ + H5O_loc_t *oloc = NULL; /* Dataset's object location */ H5O_layout_t *layout; /* Dataset's layout information */ H5T_t *type; /* Dataset's datatype */ H5S_t *space; /* Dataset's dataspace */ @@ -1799,45 +1807,45 @@ H5D_update_entry_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset, H5P_genplist_t *p FUNC_ENTER_NOAPI(H5D_update_entry_info, FAIL) /* Sanity checking */ - assert(file); - assert(dset); + HDassert(file); + HDassert(dset); /* Pick up former parameters */ - ent=&dset->ent; - layout=&dset->shared->layout; - type=dset->shared->type; - space=dset->shared->space; - alloc_time=dset->shared->alloc_time; - efl=&dset->shared->efl; + oloc = &dset->oloc; + layout = &dset->shared->layout; + type = dset->shared->type; + space = dset->shared->space; + alloc_time = dset->shared->alloc_time; + efl = &dset->shared->efl; /* Add the dataset's raw data size to the size of the header, if the raw data will be stored as compact */ - if (layout->type == H5D_COMPACT) + if(layout->type == H5D_COMPACT) ohdr_size += layout->u.compact.size; /* Create (open for write access) an object header */ - if (H5O_create(file, dxpl_id, ohdr_size, ent) < 0) + if(H5O_create(file, dxpl_id, ohdr_size, oloc) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create dataset object header") /* Get a pointer to the object header itself */ - if((oh=H5O_protect(ent, dxpl_id))==NULL) + if((oh = H5O_protect(oloc, dxpl_id)) == NULL) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to protect dataset object header") /* Point at dataset's copy, to cache it for later */ - fill_prop=&dset->shared->fill; - fill_time=dset->shared->fill_time; + fill_prop = &dset->shared->fill; + fill_time = dset->shared->fill_time; /* Check if dataset has non-default creation property list */ - if(dset->shared->dcpl_id!=H5P_DATASET_CREATE_DEFAULT) { + if(dset->shared->dcpl_id != H5P_DATASET_CREATE_DEFAULT) { /* * Retrieve properties of fill value and others. Copy them into new fill * value struct. */ - if (H5P_get(plist, H5D_CRT_FILL_TIME_NAME, &fill_time) < 0) + if(H5P_get(plist, H5D_CRT_FILL_TIME_NAME, &fill_time) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't retrieve fill time") dset->shared->fill_time=fill_time; /* Cache this for later */ /* Get the fill value information from the property list */ - if (H5P_get(plist, H5D_CRT_FILL_VALUE_NAME, fill_prop) < 0) + if(H5P_get(plist, H5D_CRT_FILL_VALUE_NAME, fill_prop) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't retrieve fill value") } /* end if */ @@ -1966,9 +1974,9 @@ H5D_update_entry_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset, H5P_genplist_t *p #ifdef H5O_ENABLE_BOGUS /* - * Add a "bogus" message. + * Add a "bogus" message (for error testing). */ - if (H5O_bogus_oh(file, dxpl_id, oh))<0) + if(H5O_bogus_oh(file, dxpl_id, oh)) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to update 'bogus' message") #endif /* H5O_ENABLE_BOGUS */ @@ -1982,8 +1990,8 @@ done: HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "unable to release fill-value info") /* Release pointer to object header itself */ - if(ent!=NULL && oh!=NULL) - if(H5O_unprotect(ent,oh, dxpl_id, oh_flags)<0) + if(oloc != NULL && oh != NULL) + if(H5O_unprotect(oloc, oh, dxpl_id, oh_flags) < 0) HDONE_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to unprotect dataset object header") FUNC_LEAVE_NOAPI(ret_value) @@ -2011,7 +2019,7 @@ done: *------------------------------------------------------------------------- */ static H5D_t * -H5D_create(H5G_entry_t *loc, const char *name, hid_t type_id, const H5S_t *space, +H5D_create(H5G_loc_t *loc, const char *name, hid_t type_id, const H5S_t *space, hid_t dcpl_id, hid_t dxpl_id) { const H5T_t *type; /* Datatype for dataset */ @@ -2023,17 +2031,18 @@ H5D_create(H5G_entry_t *loc, const char *name, hid_t type_id, const H5S_t *space H5P_genplist_t *dc_plist=NULL; /* New Property list */ hbool_t has_vl_type=FALSE; /* Flag to indicate a VL-type for dataset */ hbool_t chunk_init=FALSE; /* Flag to indicate that chunk information was initialized */ + H5G_loc_t dset_loc; /* Dataset location */ H5D_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5D_create, NULL) /* check args */ - assert (loc); - assert (name && *name); - assert (H5I_DATATYPE==H5I_get_type(type_id)); - assert (space); - assert (H5I_GENPROP_LST==H5I_get_type(dcpl_id)); - assert (H5I_GENPROP_LST==H5I_get_type(dxpl_id)); + HDassert(loc); + HDassert(name && *name); + HDassert(H5I_DATATYPE==H5I_get_type(type_id)); + HDassert(space); + HDassert(H5I_GENPROP_LST==H5I_get_type(dcpl_id)); + HDassert(H5I_GENPROP_LST==H5I_get_type(dxpl_id)); /* Get the dataset's datatype */ if (NULL == (type = H5I_object(type_id))) @@ -2055,14 +2064,17 @@ H5D_create(H5G_entry_t *loc, const char *name, hid_t type_id, const H5S_t *space if (NULL==(new_dset = H5FL_CALLOC(H5D_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - H5G_ent_reset(&(new_dset->ent)); + /* Set up & reset dataset location */ + dset_loc.oloc = &(new_dset->oloc); + dset_loc.path = &(new_dset->path); + H5G_loc_reset(&dset_loc); /* Initialize the shared dataset space */ if(NULL == (new_dset->shared = H5D_new(dcpl_id,TRUE,has_vl_type))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* What file is the dataset being added to? */ - if(NULL==(file=H5G_insertion_file(loc, name, dxpl_id))) + if(NULL == (file = H5G_insertion_file(loc, name, dxpl_id))) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to locate insertion point") /* Copy datatype for dataset */ @@ -2189,7 +2201,7 @@ H5D_create(H5G_entry_t *loc, const char *name, hid_t type_id, const H5S_t *space H5_ASSIGN_OVERFLOW(new_dset->shared->layout.u.contig.size,tmp_size,hssize_t,hsize_t); /* Get the sieve buffer size for this dataset */ - new_dset->shared->cache.contig.sieve_buf_size = H5F_SIEVE_BUF_SIZE(loc->file); + new_dset->shared->cache.contig.sieve_buf_size = H5F_SIEVE_BUF_SIZE(file); } /* end case */ break; @@ -2287,50 +2299,50 @@ H5D_create(H5G_entry_t *loc, const char *name, hid_t type_id, const H5S_t *space * Give the dataset a name. That is, create and add a new object to the * group this dataset is being initially created in. */ - if (H5G_insert(loc, name, &new_dset->ent, dxpl_id, dc_plist) < 0) + if(H5G_insert(loc, name, &dset_loc, dxpl_id, dc_plist) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to name dataset") /* Add the dataset to the list of opened objects in the file */ - if(H5FO_top_incr(new_dset->ent.file, new_dset->ent.header)<0) + if(H5FO_top_incr(new_dset->oloc.file, new_dset->oloc.addr) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINC, NULL, "can't incr object ref. count") - if(H5FO_insert(new_dset->ent.file,new_dset->ent.header,new_dset->shared)<0) + if(H5FO_insert(new_dset->oloc.file, new_dset->oloc.addr, new_dset->shared) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, NULL, "can't insert dataset into list of open objects") - new_dset->shared->fo_count=1; + new_dset->shared->fo_count = 1; /* Success */ ret_value = new_dset; done: - if (!ret_value && new_dset && new_dset->shared) { - if( new_dset->shared) { - if(new_dset->shared->layout.type==H5D_CHUNKED && chunk_init) { - if(H5D_istore_dest(new_dset,H5AC_dxpl_id)<0) + if(!ret_value && new_dset && new_dset->shared) { + if(new_dset->shared) { + if(new_dset->shared->layout.type == H5D_CHUNKED && chunk_init) { + if(H5D_istore_dest(new_dset,H5AC_dxpl_id) < 0) HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, NULL, "unable to destroy chunk cache") } /* end if */ - if (new_dset->shared->space) { - if(H5S_close(new_dset->shared->space)<0) + if(new_dset->shared->space) { + if(H5S_close(new_dset->shared->space) < 0) HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, NULL, "unable to release dataspace") } /* end if */ - if (new_dset->shared->type) { - if(H5I_dec_ref(new_dset->shared->type_id)<0) + if(new_dset->shared->type) { + if(H5I_dec_ref(new_dset->shared->type_id) < 0) HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, NULL, "unable to release datatype") } /* end if */ - if (H5F_addr_defined(new_dset->ent.header)) { - if(H5O_close(&(new_dset->ent))<0) + if(H5F_addr_defined(new_dset->oloc.addr)) { + if(H5O_close(&(new_dset->oloc)) < 0) HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, NULL, "unable to release object header") if(file) { - if(H5O_delete(file, dxpl_id,new_dset->ent.header)<0) + if(H5O_delete(file, dxpl_id, new_dset->oloc.addr) < 0) HDONE_ERROR(H5E_DATASET, H5E_CANTDELETE, NULL, "unable to delete object header") } /* end if */ } /* end if */ - if(new_dset->shared->dcpl_id!=0) { - if(H5I_dec_ref(new_dset->shared->dcpl_id)<0) + if(new_dset->shared->dcpl_id != 0) { + if(H5I_dec_ref(new_dset->shared->dcpl_id) < 0) HDONE_ERROR(H5E_DATASET, H5E_CANTDEC, NULL, "unable to decrement ref count on property list") } /* end if */ - H5FL_FREE(H5D_shared_t,new_dset->shared); + H5FL_FREE(H5D_shared_t, new_dset->shared); } /* end if */ - new_dset->ent.file = NULL; + new_dset->oloc.file = NULL; H5FL_FREE(H5D_t, new_dset); } /* end if */ @@ -2356,33 +2368,30 @@ done: *------------------------------------------------------------------------- */ htri_t -H5D_isa(H5G_entry_t *ent, hid_t dxpl_id) +H5D_isa(H5O_loc_t *loc, hid_t dxpl_id) { htri_t exists; - htri_t ret_value=TRUE; /* Return value */ + htri_t ret_value = TRUE; /* Return value */ FUNC_ENTER_NOAPI(H5D_isa, FAIL) - assert(ent); + HDassert(loc); - /* Data type */ - if ((exists=H5O_exists(ent, H5O_DTYPE_ID, 0, dxpl_id))<0) { + /* Datatype */ + if((exists = H5O_exists(loc, H5O_DTYPE_ID, 0, dxpl_id)) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to read object header") - } else if (!exists) { + else if(!exists) HGOTO_DONE(FALSE) - } /* Layout */ - if ((exists=H5O_exists(ent, H5O_LAYOUT_ID, 0, dxpl_id))<0) { + if((exists = H5O_exists(loc, H5O_SDSPACE_ID, 0, dxpl_id)) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to read object header") - } else if (!exists) { + else if(!exists) HGOTO_DONE(FALSE) - } - done: FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5D_isa() */ /* @@ -2400,67 +2409,78 @@ done: * *------------------------------------------------------------------------- */ -H5D_t* -H5D_open(const H5G_entry_t *ent, hid_t dxpl_id) +H5D_t * +H5D_open(const H5G_loc_t *loc, hid_t dxpl_id) { - H5D_shared_t *shared_fo=NULL; - H5D_t *dataset=NULL; + H5D_shared_t *shared_fo = NULL; + H5D_t *dataset = NULL; H5D_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5D_open, NULL) /* check args */ - assert (ent); + HDassert(loc); + + /* Allocate the dataset structure */ + if(NULL == (dataset = H5FL_CALLOC(H5D_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* Shallow copy (take ownership) of the object location object */ + if(H5O_loc_copy(&(dataset->oloc), loc->oloc, H5O_COPY_SHALLOW) < 0) + HGOTO_ERROR (H5E_DATASET, H5E_CANTCOPY, NULL, "can't copy object location") + + /* Shallow copy (take ownership) of the group hier. path */ + if(H5G_name_copy(&(dataset->path), loc->path, H5G_COPY_SHALLOW) < 0) + HGOTO_ERROR (H5E_DATASET, H5E_CANTCOPY, NULL, "can't copy path") /* Check if dataset was already open */ - if((shared_fo=H5FO_opened(ent->file,ent->header))==NULL) { + if((shared_fo = H5FO_opened(dataset->oloc.file, dataset->oloc.addr)) == NULL) { /* Clear any errors from H5FO_opened() */ H5E_clear_stack(NULL); /* Open the dataset object */ - if ((dataset=H5D_open_oid(ent, dxpl_id)) ==NULL) + if(H5D_open_oid(dataset, dxpl_id) < 0) HGOTO_ERROR(H5E_DATASET, H5E_NOTFOUND, NULL, "not found") /* Add the dataset to the list of opened objects in the file */ - if(H5FO_insert(dataset->ent.file,dataset->ent.header,dataset->shared)<0) + if(H5FO_insert(dataset->oloc.file, dataset->oloc.addr, dataset->shared) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, NULL, "can't insert dataset into list of open objects") /* Increment object count for the object in the top file */ - if(H5FO_top_incr(dataset->ent.file, dataset->ent.header) < 0) + if(H5FO_top_incr(dataset->oloc.file, dataset->oloc.addr) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINC, NULL, "can't increment object count") + /* We're the first dataset to use the the shared info */ dataset->shared->fo_count = 1; } /* end if */ else { - if(NULL == (dataset = H5FL_CALLOC(H5D_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate space for dataset") - - /* Shallow copy (take ownership) of the group entry object */ - if(H5G_ent_copy(&(dataset->ent),ent,H5G_COPY_SHALLOW)<0) - HGOTO_ERROR (H5E_DATASET, H5E_CANTCOPY, NULL, "can't copy group entry") - - dataset->shared=shared_fo; + /* Point to shared info */ + dataset->shared = shared_fo; + /* Increment # of datasets using shared information */ shared_fo->fo_count++; /* Check if the object has been opened through the top file yet */ - if(H5FO_top_count(dataset->ent.file, dataset->ent.header) == 0) { + if(H5FO_top_count(dataset->oloc.file, dataset->oloc.addr) == 0) { /* Open the object through this top file */ - if(H5O_open(&(dataset->ent)) < 0) + if(H5O_open(&(dataset->oloc)) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, NULL, "unable to open object header") } /* end if */ /* Increment object count for the object in the top file */ - if(H5FO_top_incr(dataset->ent.file, dataset->ent.header) < 0) + if(H5FO_top_incr(dataset->oloc.file, dataset->oloc.addr) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINC, NULL, "can't increment object count") } /* end else */ ret_value = dataset; done: - if(ret_value==NULL) { + if(ret_value == NULL) { if(dataset) { - if(shared_fo==NULL) /* Need to free shared fo */ + /* Free the dataset's group hier. path */ + H5G_name_free(&dataset->path); + + if(shared_fo == NULL) /* Need to free shared fo */ H5FL_FREE(H5D_shared_t, dataset->shared); H5FL_FREE(H5D_t, dataset); } @@ -2469,7 +2489,7 @@ done: } /* end if */ FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5D_open() */ /*------------------------------------------------------------------------- @@ -2484,59 +2504,50 @@ done: * *------------------------------------------------------------------------- */ -static H5D_t * -H5D_open_oid(const H5G_entry_t *ent, hid_t dxpl_id) +static herr_t +H5D_open_oid(H5D_t *dataset, hid_t dxpl_id) { - H5D_t *dataset = NULL; /*new dataset struct */ H5O_fill_new_t fill = {NULL, 0, NULL, H5D_ALLOC_TIME_LATE, H5D_CRT_FILL_TIME_DEF, TRUE}; unsigned alloc_time_state; /* Allocation time state */ H5O_fill_t *fill_prop; /* Pointer to dataset's fill value area */ H5O_pline_t pline; /* I/O pipeline information */ H5P_genplist_t *plist; /* Property list */ - H5D_t *ret_value = NULL; /*return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5D_open_oid, NULL) + FUNC_ENTER_NOAPI(H5D_open_oid, FAIL) /* check args */ - assert (ent); - - /* Allocate the dataset structure */ - if(NULL==(dataset=H5FL_CALLOC(H5D_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + HDassert(dataset); /* (Set the 'vl_type' parameter to FALSE since it doesn't matter from here) */ if(NULL==(dataset->shared = H5D_new(H5P_DATASET_CREATE_DEFAULT,FALSE,FALSE))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") - /* Shallow copy (take ownership) of the group entry object */ - if(H5G_ent_copy(&(dataset->ent),ent,H5G_COPY_SHALLOW)<0) - HGOTO_ERROR (H5E_DATASET, H5E_CANTCOPY, NULL, "can't copy group entry") - - /* Find the dataset object */ - if (H5O_open(&(dataset->ent)) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, NULL, "unable to open") + /* Open the dataset object */ + if(H5O_open(&(dataset->oloc)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "unable to open") /* Get the type and space */ - if (NULL==(dataset->shared->type=H5O_read(&(dataset->ent), H5O_DTYPE_ID, 0, NULL, dxpl_id))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to load type info from dataset header") + if(NULL == (dataset->shared->type = H5O_read(&(dataset->oloc), H5O_DTYPE_ID, 0, NULL, dxpl_id))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to load type info from dataset header") /* Get a datatype ID for the dataset's datatype */ if((dataset->shared->type_id = H5I_register(H5I_DATATYPE, dataset->shared->type))<0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, NULL, "unable to register type") + HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register type") - if (NULL==(dataset->shared->space=H5S_read(&(dataset->ent),dxpl_id))) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to load space info from dataset header") + if(NULL == (dataset->shared->space = H5S_read(&(dataset->oloc), dxpl_id))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to load space info from dataset header") /* Get dataset creation property list object */ - if (NULL == (plist = H5I_object(dataset->shared->dcpl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "can't get dataset creation property list") + if(NULL == (plist = H5I_object(dataset->shared->dcpl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get dataset creation property list") /* Get the optional filters message */ - if(NULL == H5O_read(&(dataset->ent), H5O_PLINE_ID, 0, &pline, dxpl_id)) { + if(NULL == H5O_read(&(dataset->oloc), H5O_PLINE_ID, 0, &pline, dxpl_id)) { H5E_clear_stack(NULL); HDmemset(&pline, 0, sizeof(pline)); - } + } /* end if */ if(H5P_set(plist, H5D_CRT_DATA_PIPELINE_NAME, &pline) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set pipeline") + HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set pipeline") /* * Get the raw data layout info. It's actually stored in two locations: @@ -2544,10 +2555,10 @@ H5D_open_oid(const H5G_entry_t *ent, hid_t dxpl_id) * values are copied to the dataset create plist so the user can query * them. */ - if (NULL==H5O_read(&(dataset->ent), H5O_LAYOUT_ID, 0, &(dataset->shared->layout), dxpl_id)) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to read data layout message") + if(NULL == H5O_read(&(dataset->oloc), H5O_LAYOUT_ID, 0, &(dataset->shared->layout), dxpl_id)) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to read data layout message") if(H5P_set(plist, H5D_CRT_LAYOUT_NAME, &dataset->shared->layout.type) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set layout") + HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set layout") switch (dataset->shared->layout.type) { case H5D_CONTIGUOUS: /* Compute the size of the contiguous storage for versions of the @@ -2567,14 +2578,14 @@ H5D_open_oid(const H5G_entry_t *ent, hid_t dxpl_id) dataset->shared->io_ops.writevv=H5D_contig_writevv; /* Get the sieve buffer size for this dataset */ - dataset->shared->cache.contig.sieve_buf_size = H5F_SIEVE_BUF_SIZE(dataset->ent.file); + dataset->shared->cache.contig.sieve_buf_size = H5F_SIEVE_BUF_SIZE(dataset->oloc.file); break; case H5D_CHUNKED: /* * Chunked storage. The creation plist's dimension is one less than * the chunk dimension because the chunk includes a dimension for the - * individual bytes of the data type. + * individual bytes of the datatype. */ { unsigned chunk_ndims; /* Dimensionality of chunk */ @@ -2582,13 +2593,13 @@ H5D_open_oid(const H5G_entry_t *ent, hid_t dxpl_id) chunk_ndims = dataset->shared->layout.u.chunk.ndims - 1; if(H5P_set(plist, H5D_CRT_CHUNK_DIM_NAME, &chunk_ndims) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set chunk dimensions") + HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set chunk dimensions") if(H5P_set(plist, H5D_CRT_CHUNK_SIZE_NAME, dataset->shared->layout.u.chunk.dim) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set chunk size") + HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set chunk size") /* Initialize the chunk cache for the dataset */ - if(H5D_istore_init(dataset->ent.file,dataset)<0) - HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, NULL, "can't initialize chunk cache") + if(H5D_istore_init(dataset->oloc.file, dataset)<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize chunk cache") } /* Set the I/O functions for this layout type */ @@ -2603,7 +2614,7 @@ H5D_open_oid(const H5G_entry_t *ent, hid_t dxpl_id) break; default: - HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, NULL, "not implemented yet") + HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "not implemented yet") } /* end switch */ /*lint !e788 All appropriate cases are covered */ /* Point at dataset's copy, to cache it for later */ @@ -2611,12 +2622,12 @@ H5D_open_oid(const H5G_entry_t *ent, hid_t dxpl_id) /* Retrieve & release the previous fill-value settings */ if(H5P_get(plist, H5D_CRT_FILL_VALUE_NAME, fill_prop) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't get fill value") + HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't get fill value") if(H5O_reset(H5O_FILL_ID, fill_prop)<0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, NULL, "can't release fill info") + HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "can't release fill info") /* Get the new fill value message */ - if(NULL == H5O_read(&(dataset->ent), H5O_FILL_NEW_ID, 0, &fill, dxpl_id)) { + if(NULL == H5O_read(&(dataset->oloc), H5O_FILL_NEW_ID, 0, &fill, dxpl_id)) { H5E_clear_stack(NULL); HDmemset(&fill, 0, sizeof(fill)); @@ -2635,7 +2646,7 @@ H5D_open_oid(const H5G_entry_t *ent, hid_t dxpl_id) break; default: - HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, NULL, "not implemented yet") + HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "not implemented yet") } /* end switch */ /*lint !e788 All appropriate cases are covered */ /* Set the default fill time */ @@ -2643,18 +2654,18 @@ H5D_open_oid(const H5G_entry_t *ent, hid_t dxpl_id) } /* end if */ if(fill.fill_defined) { if(NULL==H5O_copy(H5O_FILL_ID, &fill, fill_prop)) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "can't copy fill value") + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't copy fill value") } else { /* For compatibility with v1.4. Retrieve the old fill value message. * If size is 0, make it -1 for undefined. */ - if(NULL == H5O_read(&(dataset->ent), H5O_FILL_ID, 0, fill_prop, dxpl_id)) { + if(NULL == H5O_read(&(dataset->oloc), H5O_FILL_ID, 0, fill_prop, dxpl_id)) { H5E_clear_stack(NULL); HDmemset(fill_prop, 0, sizeof(H5O_fill_t)); - } + } /* end if */ if(fill_prop->size == 0) { fill_prop->type = fill_prop->buf = NULL; fill_prop->size = (size_t)-1; - } + } /* end if */ } /* end else */ alloc_time_state=0; if( (dataset->shared->layout.type==H5D_COMPACT && fill.alloc_time==H5D_ALLOC_TIME_EARLY) @@ -2664,24 +2675,24 @@ H5D_open_oid(const H5G_entry_t *ent, hid_t dxpl_id) /* Set revised fill value properties */ if(H5P_set(plist, H5D_CRT_FILL_VALUE_NAME, fill_prop) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set fill value") + HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set fill value") dataset->shared->alloc_time=fill.alloc_time; /* Cache this for later */ if(H5P_set(plist, H5D_CRT_ALLOC_TIME_NAME, &fill.alloc_time) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set allocation time") + HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set allocation time") if(H5P_set(plist, H5D_CRT_ALLOC_TIME_STATE_NAME, &alloc_time_state) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set allocation time state") + HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set allocation time state") dataset->shared->fill_time=fill.fill_time; /* Cache this for later */ if(H5P_set(plist, H5D_CRT_FILL_TIME_NAME, &fill.fill_time) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set fill time") + HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set fill time") /* Get the external file list message, which might not exist. Space is * also undefined when space allocate time is H5D_ALLOC_TIME_LATE. */ if((dataset->shared->layout.type==H5D_CONTIGUOUS && !H5F_addr_defined(dataset->shared->layout.u.contig.addr)) || (dataset->shared->layout.type==H5D_CHUNKED && !H5F_addr_defined(dataset->shared->layout.u.chunk.addr))) { HDmemset(&dataset->shared->efl,0,sizeof(H5O_efl_t)); - if(NULL != H5O_read(&(dataset->ent), H5O_EFL_ID, 0, &dataset->shared->efl, dxpl_id)) { + if(NULL != H5O_read(&(dataset->oloc), H5O_EFL_ID, 0, &dataset->shared->efl, dxpl_id)) { if(H5P_set(plist, H5D_CRT_EXT_FILE_LIST_NAME, &dataset->shared->efl) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set external file list") + HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set external file list") /* Override the I/O functions for this layout type */ dataset->shared->io_ops.readvv=H5D_efl_readvv; @@ -2694,42 +2705,38 @@ H5D_open_oid(const H5G_entry_t *ent, hid_t dxpl_id) * This is important only for parallel I/O where the space must * be fully allocated before I/O can happen. */ - if ((H5F_get_intent(dataset->ent.file) & H5F_ACC_RDWR) + if((H5F_get_intent(dataset->oloc.file) & H5F_ACC_RDWR) && ((dataset->shared->layout.type==H5D_CONTIGUOUS && !H5F_addr_defined(dataset->shared->layout.u.contig.addr)) || (dataset->shared->layout.type==H5D_CHUNKED && !H5F_addr_defined(dataset->shared->layout.u.chunk.addr))) - && IS_H5FD_MPI(dataset->ent.file)) { - if (H5D_alloc_storage(dataset->ent.file, dxpl_id, dataset,H5D_ALLOC_OPEN, TRUE, FALSE)<0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to initialize file storage") - } + && IS_H5FD_MPI(dataset->oloc.file)) { + if(H5D_alloc_storage(dataset->oloc.file, dxpl_id, dataset,H5D_ALLOC_OPEN, TRUE, FALSE)<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize file storage") + } /* end if */ /* Get the dataset's DCPL cache info */ - if (H5D_get_dcpl_cache(dataset->shared->dcpl_id,&dataset->shared->dcpl_cache)<0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, NULL, "can't fill DCPL cache") - - /* Success */ - ret_value = dataset; + if(H5D_get_dcpl_cache(dataset->shared->dcpl_id,&dataset->shared->dcpl_cache)<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill DCPL cache") done: /* Release fill value information */ - if (H5O_reset(H5O_FILL_ID, &fill) <0) - HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, NULL, "unable to release fill-value info") + if(H5O_reset(H5O_FILL_ID, &fill) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "unable to release fill-value info") - if (ret_value==NULL && dataset) { - if (H5F_addr_defined(dataset->ent.header)) { - if(H5O_close(&(dataset->ent))<0) - HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, NULL, "unable to release object header") + if(ret_value < 0) { + if(H5F_addr_defined(dataset->oloc.addr)) { + if(H5O_close(&(dataset->oloc)) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release object header") } /* end if */ - if (dataset->shared->space) { - if(H5S_close(dataset->shared->space)<0) - HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, NULL, "unable to release dataspace") + if(dataset->shared->space) { + if(H5S_close(dataset->shared->space) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataspace") } /* end if */ - if (dataset->shared->type) { - if(H5I_dec_ref(dataset->shared->type_id)<0) - HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, NULL, "unable to release datatype") + if(dataset->shared->type) { + if(H5I_dec_ref(dataset->shared->type_id) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release datatype") } /* end if */ - dataset->ent.file = NULL; - H5FL_FREE(H5D_t,dataset); } /* end if */ + FUNC_LEAVE_NOAPI(ret_value) } /* end H5D_open_oid() */ @@ -2757,7 +2764,7 @@ H5D_close(H5D_t *dataset) FUNC_ENTER_NOAPI(H5D_close, FAIL) /* check args */ - assert(dataset && dataset->ent.file && dataset->shared); + assert(dataset && dataset->oloc.file && dataset->shared); assert(dataset->shared->fo_count >0); /* Dump debugging info */ @@ -2775,7 +2782,7 @@ H5D_close(H5D_t *dataset) /* Flush the raw data buffer, if its dirty */ if (dataset->shared->cache.contig.sieve_dirty) { /* Write dirty data sieve buffer to file */ - if (H5F_block_write(dataset->ent.file, H5FD_MEM_DRAW, dataset->shared->cache.contig.sieve_loc, + if (H5F_block_write(dataset->oloc.file, H5FD_MEM_DRAW, dataset->shared->cache.contig.sieve_loc, dataset->shared->cache.contig.sieve_size, H5AC_dxpl_id, dataset->shared->cache.contig.sieve_buf) < 0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed") @@ -2800,7 +2807,7 @@ H5D_close(H5D_t *dataset) case H5D_COMPACT: /* Update header message of layout for compact dataset. */ if(dataset->shared->layout.u.compact.dirty) { - if(H5O_modify(&(dataset->ent), H5O_LAYOUT_ID, 0, 0, H5O_UPDATE_TIME, &(dataset->shared->layout), H5AC_dxpl_id)<0) + if(H5O_modify(&(dataset->oloc), H5O_LAYOUT_ID, 0, 0, H5O_UPDATE_TIME, &(dataset->shared->layout), H5AC_dxpl_id)<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "unable to update layout message") dataset->shared->layout.u.compact.dirty = FALSE; } /* end if */ @@ -2824,15 +2831,15 @@ H5D_close(H5D_t *dataset) H5I_dec_ref(dataset->shared->dcpl_id) < 0); /* Remove the dataset from the list of opened objects in the file */ - if(H5FO_top_decr(dataset->ent.file, dataset->ent.header) < 0) + if(H5FO_top_decr(dataset->oloc.file, dataset->oloc.addr) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "can't decrement count for object") - if(H5FO_delete(dataset->ent.file, H5AC_dxpl_id, dataset->ent.header)<0) + if(H5FO_delete(dataset->oloc.file, H5AC_dxpl_id, dataset->oloc.addr) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "can't remove dataset from list of open objects") /* Close the dataset object */ /* (This closes the file, if this is the last object open) */ - if(H5O_close(&(dataset->ent))<0) - HGOTO_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release object header"); + if(H5O_close(&(dataset->oloc)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release object header") /* * Free memory. Before freeing the memory set the file pointer to NULL. @@ -2840,25 +2847,25 @@ H5D_close(H5D_t *dataset) * sure we're not accessing an already freed dataset (see the assert() * above). */ - dataset->ent.file = NULL; + dataset->oloc.file = NULL; H5FL_FREE(H5D_shared_t,dataset->shared); } /* end if */ else { /* Decrement the ref. count for this object in the top file */ - if(H5FO_top_decr(dataset->ent.file, dataset->ent.header) < 0) + if(H5FO_top_decr(dataset->oloc.file, dataset->oloc.addr) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "can't decrement count for object") /* Check reference count for this object in the top file */ - if(H5FO_top_count(dataset->ent.file, dataset->ent.header) == 0) - if(H5O_close(&(dataset->ent)) < 0) + if(H5FO_top_count(dataset->oloc.file, dataset->oloc.addr) == 0) + if(H5O_close(&(dataset->oloc)) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to close") - - if(H5G_free_ent_name(&dataset->ent)<0) - free_failed=TRUE; } /* end else */ + if(H5G_name_free(&(dataset->path)) < 0) + free_failed=TRUE; + H5FL_FREE(H5D_t,dataset); if (free_failed) @@ -2903,12 +2910,12 @@ H5D_extend (H5D_t *dataset, const hsize_t *size, hid_t dxpl_id) if(! dataset->shared->checked_filters) { if(H5P_is_fill_value_defined(&(dataset->shared->fill), &fill_status) < 0) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Couldn't retrieve fill value from dataset."); + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Couldn't retrieve fill value from dataset.") if(fill_status == H5D_FILL_VALUE_DEFAULT || fill_status == H5D_FILL_VALUE_USER_DEFINED) { if( H5Pget_fill_time(dataset->shared->dcpl_id, &fill_time) < 0) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Couldn't retrieve fill time from dataset."); + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Couldn't retrieve fill time from dataset.") if(fill_time == H5D_FILL_TIME_ALLOC || (fill_time == H5D_FILL_TIME_IFSET && fill_status == H5D_FILL_VALUE_USER_DEFINED) ) @@ -2935,8 +2942,8 @@ H5D_extend (H5D_t *dataset, const hsize_t *size, hid_t dxpl_id) if (changed>0){ /* Save the new dataspace in the file if necessary */ - if (H5S_modify (&(dataset->ent), space, TRUE, dxpl_id)<0) - HGOTO_ERROR (H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to update file with new dataspace") + if(H5S_modify (&(dataset->oloc), space, TRUE, dxpl_id) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to update file with new dataspace") /* Update the index values for the cached chunks for this dataset */ if(H5D_CHUNKED == dataset->shared->layout.type) @@ -2944,8 +2951,8 @@ H5D_extend (H5D_t *dataset, const hsize_t *size, hid_t dxpl_id) HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to update cached chunk indices") /* Allocate space for the new parts of the dataset, if appropriate */ - if(dataset->shared->alloc_time==H5D_ALLOC_TIME_EARLY || IS_H5FD_MPI(dataset->ent.file)) - if (H5D_alloc_storage(dataset->ent.file, dxpl_id, dataset, H5D_ALLOC_EXTEND, TRUE, FALSE)<0) + if(dataset->shared->alloc_time == H5D_ALLOC_TIME_EARLY || IS_H5FD_MPI(dataset->oloc.file)) + if(H5D_alloc_storage(dataset->oloc.file, dxpl_id, dataset, H5D_ALLOC_EXTEND, TRUE, FALSE) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize dataset with fill value") } /* end if */ @@ -2955,12 +2962,11 @@ done: /*------------------------------------------------------------------------- - * Function: H5D_entof + * Function: H5D_oloc * - * Purpose: Returns a pointer to the entry for a dataset. - * - * Return: Success: Ptr to entry + * Purpose: Returns a pointer to the object location for a dataset. * + * Return: Success: Ptr to location * Failure: NULL * * Programmer: Robb Matzke @@ -2968,23 +2974,46 @@ done: * *------------------------------------------------------------------------- */ -H5G_entry_t * -H5D_entof (H5D_t *dataset) +H5O_loc_t * +H5D_oloc(H5D_t *dataset) { /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_entof) + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_oloc) - FUNC_LEAVE_NOAPI( dataset ? &(dataset->ent) : (H5G_entry_t *)NULL) -} + FUNC_LEAVE_NOAPI(dataset ? &(dataset->oloc) : (H5O_loc_t *)NULL) +} /* end H5D_oloc() */ + + +/*------------------------------------------------------------------------- + * Function: H5D_nameof + * + * Purpose: Returns a pointer to the group hier. path for a dataset. + * + * Return: Success: Ptr to entry + * Failure: NULL + * + * Programmer: Quincey Koziol + * Monday, September 12, 2005 + * + *------------------------------------------------------------------------- + */ +H5G_name_t * +H5D_nameof(H5D_t *dataset) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_nameof) + + FUNC_LEAVE_NOAPI(dataset ? &(dataset->path) : (H5G_name_t *)NULL) +} /* end H5D_nameof() */ /*------------------------------------------------------------------------- * Function: H5D_typeof * - * Purpose: Returns a pointer to the dataset's data type. The data type + * Purpose: Returns a pointer to the dataset's datatype. The datatype * is not copied. * - * Return: Success: Ptr to the dataset's data type, uncopied. + * Return: Success: Ptr to the dataset's datatype, uncopied. * * Failure: NULL * @@ -3026,11 +3055,11 @@ H5D_get_file (const H5D_t *dset) /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_get_file) - assert (dset); - assert (dset->ent.file); + HDassert(dset); + HDassert(dset->oloc.file); - FUNC_LEAVE_NOAPI(dset->ent.file) -} + FUNC_LEAVE_NOAPI(dset->oloc.file) +} /* end H5D_get_file() */ /*------------------------------------------------------------------------- @@ -3101,9 +3130,9 @@ H5D_alloc_storage (H5F_t *f, hid_t dxpl_id, H5D_t *dset/*in,out*/, H5D_time_allo * indicate that space should be allocated, so the * B-tree gets expanded. -QAK */ - if((dset->shared->alloc_time==H5D_ALLOC_TIME_EARLY || - IS_H5FD_MPI(dset->ent.file)) && - time_alloc==H5D_ALLOC_EXTEND) + if((dset->shared->alloc_time == H5D_ALLOC_TIME_EARLY || + IS_H5FD_MPI(dset->oloc.file)) && + time_alloc == H5D_ALLOC_EXTEND) { init_space=1; } @@ -3170,9 +3199,9 @@ H5D_alloc_storage (H5F_t *f, hid_t dxpl_id, H5D_t *dset/*in,out*/, H5D_time_allo /* Also update header message for layout with new address, if we * set the address. (this is improves forward compatibility). */ - if(time_alloc!=H5D_ALLOC_CREATE && addr_set) - if (H5O_modify (&(dset->ent), H5O_LAYOUT_ID, 0, H5O_FLAG_CONSTANT, update_time, &(dset->shared->layout), dxpl_id) < 0) - HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update layout message") + if(time_alloc != H5D_ALLOC_CREATE && addr_set) + if(H5O_modify(&(dset->oloc), H5O_LAYOUT_ID, 0, H5O_FLAG_CONSTANT, update_time, &(dset->shared->layout), dxpl_id) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update layout message") } /* end if */ done: @@ -3508,18 +3537,18 @@ H5Diterate(void *buf, hid_t type_id, hid_t space_id, H5D_operator_t op, H5TRACE5("e","xiixx",buf,type_id,space_id,op,operator_data); /* Check args */ - if (NULL==op) + if(NULL==op) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid operator") - if (buf==NULL) + if(buf==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid buffer") - if (H5I_DATATYPE != H5I_get_type(type_id)) + if(H5I_DATATYPE != H5I_get_type(type_id)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid datatype") - if (NULL == (space = H5I_object_verify(space_id, H5I_DATASPACE))) + if(NULL == (space = H5I_object_verify(space_id, H5I_DATASPACE))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataspace") - if( !(H5S_has_extent(space)) ) + if(!(H5S_has_extent(space)) ) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspace does not have extent set") - ret_value=H5S_select_iterate(buf,type_id,space,op,operator_data); + ret_value = H5S_select_iterate(buf,type_id,space,op,operator_data); done: FUNC_LEAVE_API(ret_value) @@ -3565,7 +3594,7 @@ H5Dvlen_reclaim(hid_t type_id, hid_t space_id, hid_t plist_id, void *buf) /* Get the allocation info */ if(H5T_vlen_get_alloc_info(plist_id,&vl_alloc_info)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to retrieve VL allocation info"); + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to retrieve VL allocation info") /* Call H5Diterate with args, etc. */ ret_value=H5Diterate(buf,type_id,space_id,H5T_vlen_reclaim,vl_alloc_info); @@ -3639,29 +3668,29 @@ done: static herr_t H5D_vlen_get_buf_size(void UNUSED *elem, hid_t type_id, unsigned UNUSED ndim, const hsize_t *point, void *op_data) { - H5D_vlen_bufsize_t *vlen_bufsize=(H5D_vlen_bufsize_t *)op_data; + H5D_vlen_bufsize_t *vlen_bufsize = (H5D_vlen_bufsize_t *)op_data; H5T_t *dt = NULL; - herr_t ret_value=0; /* The correct return value, if this function succeeds */ + herr_t ret_value = 0; /* The correct return value, if this function succeeds */ FUNC_ENTER_NOAPI(H5D_vlen_get_buf_size, FAIL) - assert(op_data); - assert(H5I_DATATYPE == H5I_get_type(type_id)); + HDassert(op_data); + HDassert(H5I_DATATYPE == H5I_get_type(type_id)); /* Check args */ - if (NULL==(dt=H5I_object(type_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type") + if(NULL == (dt = H5I_object(type_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype") /* Make certain there is enough fixed-length buffer available */ - if ((vlen_bufsize->fl_tbuf=H5FL_BLK_REALLOC(vlen_fl_buf,vlen_bufsize->fl_tbuf,H5T_get_size(dt)))==NULL) + if((vlen_bufsize->fl_tbuf=H5FL_BLK_REALLOC(vlen_fl_buf, vlen_bufsize->fl_tbuf, H5T_get_size(dt))) == NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't resize tbuf") /* Select point to read in */ - if (H5Sselect_elements(vlen_bufsize->fspace_id,H5S_SELECT_SET,1,(const hsize_t **)point)<0) + if(H5Sselect_elements(vlen_bufsize->fspace_id, H5S_SELECT_SET, 1, (const hsize_t **)point)<0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't select point") /* Read in the point (with the custom VL memory allocator) */ - if(H5Dread(vlen_bufsize->dataset_id,type_id,vlen_bufsize->mspace_id,vlen_bufsize->fspace_id,vlen_bufsize->xfer_pid,vlen_bufsize->fl_tbuf)<0) + if(H5Dread(vlen_bufsize->dataset_id, type_id, vlen_bufsize->mspace_id, vlen_bufsize->fspace_id, vlen_bufsize->xfer_pid, vlen_bufsize->fl_tbuf)<0) HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read point") done: @@ -3786,12 +3815,9 @@ done: * Return: Success: SUCCEED, Failure: FAIL * * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu - * Robb Matzke * * Date: April 9, 2002 * - * Comments: Public function, calls private H5D_set_extent - * *------------------------------------------------------------------------- */ herr_t @@ -3831,8 +3857,6 @@ done: * * Date: April 9, 2002 * - * Comments: Private function - * *------------------------------------------------------------------------- */ static herr_t @@ -3887,7 +3911,7 @@ H5D_set_extent(H5D_t *dset, const hsize_t *size, hid_t dxpl_id) *------------------------------------------------------------------------- */ /* Save the new dataspace in the file if necessary */ - if(H5S_modify(&(dset->ent), space, TRUE, dxpl_id) < 0) + if(H5S_modify(&(dset->oloc), space, TRUE, dxpl_id) < 0) HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to update file with new dataspace") /* Update the index values for the cached chunks for this dataset */ @@ -3897,7 +3921,7 @@ H5D_set_extent(H5D_t *dset, const hsize_t *size, hid_t dxpl_id) /* Allocate space for the new parts of the dataset, if appropriate */ if(expand && dset->shared->alloc_time==H5D_ALLOC_TIME_EARLY) - if(H5D_alloc_storage(dset->ent.file, dxpl_id, dset, H5D_ALLOC_EXTEND, TRUE, FALSE) < 0) + if(H5D_alloc_storage(dset->oloc.file, dxpl_id, dset, H5D_ALLOC_EXTEND, TRUE, FALSE) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize dataset storage") @@ -4002,7 +4026,7 @@ H5D_flush(const H5F_t *f, hid_t dxpl_id, unsigned flags) case H5D_COMPACT: if(dataset->shared->layout.u.compact.dirty) { - if(H5O_modify(&(dataset->ent), H5O_LAYOUT_ID, 0, 0, H5O_UPDATE_TIME, &(dataset->shared->layout), dxpl_id)<0) + if(H5O_modify(&(dataset->oloc), H5O_LAYOUT_ID, 0, 0, H5O_UPDATE_TIME, &(dataset->shared->layout), dxpl_id)<0) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to update layout message") dataset->shared->layout.u.compact.dirty = FALSE; } /* end if */ @@ -4043,23 +4067,23 @@ done: herr_t H5Ddebug(hid_t dset_id) { - H5D_t *dset=NULL; - herr_t ret_value=SUCCEED; /* Return value */ + H5D_t *dset = NULL; + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(H5Ddebug, FAIL) H5TRACE1("e","i",dset_id); /* Check args */ - if (NULL==(dset=H5I_object_verify(dset_id, H5I_DATASET))) + if(NULL == (dset = H5I_object_verify(dset_id, H5I_DATASET))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") /* Print B-tree information */ - if (H5D_CHUNKED==dset->shared->layout.type) { - (void)H5D_istore_dump_btree(dset->ent.file, H5AC_dxpl_id, stdout, dset->shared->layout.u.chunk.ndims, dset->shared->layout.u.chunk.addr); - } else if (H5D_CONTIGUOUS==dset->shared->layout.type) { + if(H5D_CHUNKED == dset->shared->layout.type) + (void)H5D_istore_dump_btree(dset->oloc.file, H5AC_dxpl_id, stdout, dset->shared->layout.u.chunk.ndims, dset->shared->layout.u.chunk.addr); + else if(H5D_CONTIGUOUS == dset->shared->layout.type) HDfprintf(stdout, " %-10s %a\n", "Address:", dset->shared->layout.u.contig.addr); - } done: FUNC_LEAVE_API(ret_value) -} +} /* end H5Ddebug() */ + diff --git a/src/H5Dcontig.c b/src/H5Dcontig.c index bd3b358..fd05e8c 100644 --- a/src/H5Dcontig.c +++ b/src/H5Dcontig.c @@ -155,13 +155,13 @@ H5D_contig_fill(H5D_t *dset, hid_t dxpl_id) #ifdef H5_HAVE_PARALLEL /* Retrieve MPI parameters */ - if(IS_H5FD_MPI(dset->ent.file)) { + if(IS_H5FD_MPI(dset->oloc.file)) { /* Get the MPI communicator */ - if (MPI_COMM_NULL == (mpi_comm=H5F_mpi_get_comm(dset->ent.file))) + if(MPI_COMM_NULL == (mpi_comm = H5F_mpi_get_comm(dset->oloc.file))) HGOTO_ERROR(H5E_INTERNAL, H5E_MPI, FAIL, "Can't retrieve MPI communicator") /* Get the MPI rank */ - if ((mpi_rank=H5F_mpi_get_rank(dset->ent.file))<0) + if((mpi_rank = H5F_mpi_get_rank(dset->oloc.file)) < 0) HGOTO_ERROR(H5E_INTERNAL, H5E_MPI, FAIL, "Can't retrieve MPI rank") /* Set the MPI-capable file driver flag */ @@ -421,7 +421,7 @@ H5D_contig_readvv(const H5D_io_info_t *io_info, size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[], void *_buf) { - H5F_t *file=io_info->dset->ent.file; /* File for dataset */ + H5F_t *file = io_info->dset->oloc.file; /* File for dataset */ H5D_rdcdc_t *dset_contig=&(io_info->dset->shared->cache.contig); /* Cached information about contiguous data */ const H5D_contig_storage_t *store_contig=&(io_info->store->contig); /* Contiguous storage info for this I/O operation */ unsigned char *buf=(unsigned char *)_buf; /* Pointer to buffer to fill */ @@ -686,7 +686,7 @@ H5D_contig_writevv(const H5D_io_info_t *io_info, size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[], const void *_buf) { - H5F_t *file=io_info->dset->ent.file; /* File for dataset */ + H5F_t *file = io_info->dset->oloc.file; /* File for dataset */ H5D_rdcdc_t *dset_contig=&(io_info->dset->shared->cache.contig); /* Cached information about contiguous data */ const H5D_contig_storage_t *store_contig=&(io_info->store->contig); /* Contiguous storage info for this I/O operation */ const unsigned char *buf=_buf; /* Pointer to buffer to fill */ @@ -750,6 +750,10 @@ H5D_contig_writevv(const H5D_io_info_t *io_info, /* Allocate room for the data sieve buffer */ if (NULL==(dset_contig->sieve_buf=H5FL_BLK_MALLOC(sieve_buf,dset_contig->sieve_buf_size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") +#ifdef H5_USING_PURIFY +if(dset_contig->sieve_size > size) + HDmemset(dset_contig->sieve_buf + size, 0, (dset_contig->sieve_size - size)); +#endif /* H5_USING_PURIFY */ /* Determine the new sieve buffer size & location */ dset_contig->sieve_loc=addr; diff --git a/src/H5Dio.c b/src/H5Dio.c index fdbfd0e..21face4 100644 --- a/src/H5Dio.c +++ b/src/H5Dio.c @@ -466,20 +466,20 @@ H5Dread(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, plist_id,buf); /* check arguments */ - if (NULL == (dset = H5I_object_verify(dset_id, H5I_DATASET))) + if(NULL == (dset = H5I_object_verify(dset_id, H5I_DATASET))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") - if (NULL == dset->ent.file) + if(NULL == dset->oloc.file) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") - if (H5S_ALL != mem_space_id) { - if (NULL == (mem_space = H5I_object_verify(mem_space_id, H5I_DATASPACE))) + if(H5S_ALL != mem_space_id) { + if(NULL == (mem_space = H5I_object_verify(mem_space_id, H5I_DATASPACE))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space") /* Check for valid selection */ if(H5S_SELECT_VALID(mem_space)!=TRUE) HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "selection+offset not within extent") - } - if (H5S_ALL != file_space_id) { - if (NULL == (file_space = H5I_object_verify(file_space_id, H5I_DATASPACE))) + } /* end if */ + if(H5S_ALL != file_space_id) { + if(NULL == (file_space = H5I_object_verify(file_space_id, H5I_DATASPACE))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space") /* Check for valid selection */ @@ -550,38 +550,38 @@ H5Dwrite(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, plist_id,buf); /* check arguments */ - if (NULL == (dset = H5I_object_verify(dset_id, H5I_DATASET))) + if(NULL == (dset = H5I_object_verify(dset_id, H5I_DATASET))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") - if (NULL == dset->ent.file) + if(NULL == dset->oloc.file) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") - if (H5S_ALL != mem_space_id) { - if (NULL == (mem_space = H5I_object_verify(mem_space_id, H5I_DATASPACE))) + if(H5S_ALL != mem_space_id) { + if(NULL == (mem_space = H5I_object_verify(mem_space_id, H5I_DATASPACE))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space") /* Check for valid selection */ if (H5S_SELECT_VALID(mem_space)!=TRUE) HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "memory selection+offset not within extent") - } - if (H5S_ALL != file_space_id) { - if (NULL == (file_space = H5I_object_verify(file_space_id, H5I_DATASPACE))) + } /* end if */ + if(H5S_ALL != file_space_id) { + if(NULL == (file_space = H5I_object_verify(file_space_id, H5I_DATASPACE))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space") /* Check for valid selection */ - if (H5S_SELECT_VALID(file_space)!=TRUE) + if(H5S_SELECT_VALID(file_space)!=TRUE) HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "file selection+offset not within extent") - } + } /* end if */ /* Get the default dataset transfer property list if the user didn't provide one */ - if (H5P_DEFAULT == plist_id) + if(H5P_DEFAULT == plist_id) plist_id= H5P_DATASET_XFER_DEFAULT; else - if (TRUE!=H5P_isa_class(plist_id,H5P_DATASET_XFER)) + if(TRUE!=H5P_isa_class(plist_id,H5P_DATASET_XFER)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms") - if (!buf && H5S_GET_SELECT_NPOINTS(file_space)!=0) + if(!buf && H5S_GET_SELECT_NPOINTS(file_space)!=0) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no output buffer") /* write raw data */ - if (H5D_write(dset, mem_type_id, mem_space, file_space, plist_id, buf) < 0) + if(H5D_write(dset, mem_type_id, mem_space, file_space, plist_id, buf) < 0) HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data") done: @@ -611,7 +611,9 @@ H5D_read(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, H5T_path_t *tpath = NULL; /*type conversion info */ const H5T_t *mem_type = NULL; /* Memory datatype */ H5D_io_info_t io_info; /* Dataset I/O info */ +#ifdef H5_HAVE_PARALLEL hbool_t io_info_init = FALSE; /* Whether the I/O info has been initialized */ +#endif /*H5_HAVE_PARALLEL*/ H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */ H5D_dxpl_cache_t *dxpl_cache=&_dxpl_cache; /* Data transfer property cache */ herr_t ret_value = SUCCEED; /* Return value */ @@ -619,27 +621,27 @@ H5D_read(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, FUNC_ENTER_NOAPI_NOINIT(H5D_read) /* check args */ - assert(dataset && dataset->ent.file); + HDassert(dataset && dataset->oloc.file); /* Get memory datatype */ - if (NULL == (mem_type = H5I_object_verify(mem_type_id, H5I_DATATYPE))) + if(NULL == (mem_type = H5I_object_verify(mem_type_id, H5I_DATATYPE))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type") - if (!file_space) + if(!file_space) file_space = dataset->shared->space; - if (!mem_space) + if(!mem_space) mem_space = file_space; if((snelmts = H5S_GET_SELECT_NPOINTS(mem_space))<0) HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "src dataspace has invalid selection") H5_ASSIGN_OVERFLOW(nelmts,snelmts,hssize_t,hsize_t); /* Fill the DXPL cache values for later use */ - if (H5D_get_dxpl_cache(dxpl_id,&dxpl_cache)<0) + if(H5D_get_dxpl_cache(dxpl_id,&dxpl_cache)<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache") #ifdef H5_HAVE_PARALLEL /* Collective access is not permissible without a MPI based VFD */ - if (dxpl_cache->xfer_mode==H5FD_MPIO_COLLECTIVE && !IS_H5FD_MPI(dataset->ent.file)) + if (dxpl_cache->xfer_mode==H5FD_MPIO_COLLECTIVE && !IS_H5FD_MPI(dataset->oloc.file)) HGOTO_ERROR (H5E_DATASET, H5E_UNSUPPORTED, FAIL, "collective access for MPI-based drivers only") #endif /*H5_HAVE_PARALLEL*/ @@ -701,7 +703,9 @@ H5D_read(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, /* Set up I/O operation */ if(H5D_ioinfo_init(dataset,dxpl_cache,dxpl_id,mem_space,file_space,tpath,&io_info)<0) HGOTO_ERROR (H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to set up I/O operation") +#ifdef H5_HAVE_PARALLEL io_info_init = TRUE; +#endif /*H5_HAVE_PARALLEL*/ /* Determine correct I/O routine to invoke */ if(dataset->shared->layout.type!=H5D_CHUNKED) { @@ -749,7 +753,9 @@ H5D_write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, H5T_path_t *tpath = NULL; /*type conversion info */ const H5T_t *mem_type = NULL; /* Memory datatype */ H5D_io_info_t io_info; /* Dataset I/O info */ +#ifdef H5_HAVE_PARALLEL hbool_t io_info_init = FALSE; /* Whether the I/O info has been initialized */ +#endif /*H5_HAVE_PARALLEL*/ H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */ H5D_dxpl_cache_t *dxpl_cache=&_dxpl_cache; /* Data transfer property cache */ herr_t ret_value = SUCCEED; /* Return value */ @@ -757,31 +763,30 @@ H5D_write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, FUNC_ENTER_NOAPI_NOINIT(H5D_write) /* check args */ - assert(dataset && dataset->ent.file); + HDassert(dataset && dataset->oloc.file); /* Get the memory datatype */ - if (NULL == (mem_type = H5I_object_verify(mem_type_id, H5I_DATATYPE))) + if(NULL == (mem_type = H5I_object_verify(mem_type_id, H5I_DATATYPE))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type") /* All filters in the DCPL must have encoding enabled. */ - if(! dataset->shared->checked_filters) - { + if(!dataset->shared->checked_filters) { if(H5Z_can_apply(dataset->shared->dcpl_id, dataset->shared->type_id) <0) HGOTO_ERROR(H5E_PLINE, H5E_CANAPPLY, FAIL, "can't apply filters") dataset->shared->checked_filters = TRUE; - } + } /* end if */ /* Check if we are allowed to write to this file */ - if (0==(H5F_get_intent(dataset->ent.file) & H5F_ACC_RDWR)) + if(0==(H5F_get_intent(dataset->oloc.file) & H5F_ACC_RDWR)) HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "no write intent on file") /* Fill the DXPL cache values for later use */ - if (H5D_get_dxpl_cache(dxpl_id,&dxpl_cache)<0) + if(H5D_get_dxpl_cache(dxpl_id,&dxpl_cache) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache") /* Various MPI based checks */ - if (IS_H5FD_MPI(dataset->ent.file)) { + if(IS_H5FD_MPI(dataset->oloc.file)) { /* If MPI based VFD is used, no VL datatype support yet. */ /* This is because they use the global heap in the file and we don't */ /* support parallel access of that yet */ @@ -835,17 +840,17 @@ H5D_write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, hbool_t full_overwrite; /* Whether we are over-writing all the elements */ /* Get the number of elements in file dataset's dataspace */ - if((file_nelmts=H5S_GET_EXTENT_NPOINTS(file_space))<0) + if((file_nelmts = H5S_GET_EXTENT_NPOINTS(file_space)) < 0) HGOTO_ERROR (H5E_DATASET, H5E_BADVALUE, FAIL, "can't retrieve number of elements in file dataset") /* Always allow fill values to be written if the dataset has a VL datatype */ if(H5T_detect_class(dataset->shared->type, H5T_VLEN)) - full_overwrite=FALSE; + full_overwrite = FALSE; else - full_overwrite=(hsize_t)file_nelmts==nelmts ? TRUE : FALSE; + full_overwrite = (hsize_t)file_nelmts==nelmts ? TRUE : FALSE; /* Allocate storage */ - if(H5D_alloc_storage(dataset->ent.file,dxpl_id,dataset,H5D_ALLOC_WRITE, TRUE, full_overwrite)<0) + if(H5D_alloc_storage(dataset->oloc.file, dxpl_id, dataset, H5D_ALLOC_WRITE, TRUE, full_overwrite)<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize storage") } /* end if */ @@ -863,7 +868,9 @@ H5D_write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, /* Set up I/O operation */ if(H5D_ioinfo_init(dataset,dxpl_cache,dxpl_id,mem_space,file_space,tpath,&io_info)<0) HGOTO_ERROR (H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to set up I/O operation") +#ifdef H5_HAVE_PARALLEL io_info_init = TRUE; +#endif /*H5_HAVE_PARALLEL*/ /* Determine correct I/O routine to invoke */ if(dataset->shared->layout.type!=H5D_CHUNKED) { @@ -888,7 +895,7 @@ H5D_write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, * Update modification time. We have to do this explicitly because * writing to a dataset doesn't necessarily change the object header. */ - if (H5O_touch(&(dataset->ent), FALSE, dxpl_id)<0) + if (H5O_touch(&(dataset->oloc), FALSE, dxpl_id)<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update modification time") #endif /* OLD_WAY */ @@ -3020,7 +3027,7 @@ H5D_ioinfo_init(H5D_t *dset, const H5D_dxpl_cache_t *dxpl_cache, hid_t dxpl_id, /* check args */ HDassert(dset); - HDassert(dset->ent.file); + HDassert(dset->oloc.file); HDassert(mem_space); HDassert(file_space); HDassert(tpath); @@ -3039,11 +3046,11 @@ H5D_ioinfo_init(H5D_t *dset, const H5D_dxpl_cache_t *dxpl_cache, hid_t dxpl_id, /* Start in the "not modified" xfer_mode state */ io_info->xfer_mode_changed = FALSE; - if(IS_H5FD_MPI(dset->ent.file)) { + if(IS_H5FD_MPI(dset->oloc.file)) { htri_t opt; /* Flag whether a selection is optimizable */ /* Get MPI communicator */ - if((io_info->comm = H5F_mpi_get_comm(dset->ent.file)) == MPI_COMM_NULL) + if((io_info->comm = H5F_mpi_get_comm(dset->oloc.file)) == MPI_COMM_NULL) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't retrieve MPI communicator") /* diff --git a/src/H5Distore.c b/src/H5Distore.c index b0d60d6..54fd2a1 100644 --- a/src/H5Distore.c +++ b/src/H5Distore.c @@ -1069,9 +1069,9 @@ H5D_istore_flush_entry(const H5D_io_info_t *io_info, H5D_rdcc_ent_t *ent, hbool_ * Create the chunk it if it doesn't exist, or reallocate the chunk if * its size changed. Then write the data into the file. */ - if (H5B_insert(io_info->dset->ent.file, io_info->dxpl_id, H5B_ISTORE, io_info->dset->shared->layout.u.chunk.addr, &udata)<0) + if(H5B_insert(io_info->dset->oloc.file, io_info->dxpl_id, H5B_ISTORE, io_info->dset->shared->layout.u.chunk.addr, &udata)<0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to allocate chunk") - if (H5F_block_write(io_info->dset->ent.file, H5FD_MEM_DRAW, udata.addr, udata.common.key.nbytes, io_info->dxpl_id, buf)<0) + if(H5F_block_write(io_info->dset->oloc.file, H5FD_MEM_DRAW, udata.addr, udata.common.key.nbytes, io_info->dxpl_id, buf) < 0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write raw data to file") /* Mark cache entry as clean */ @@ -1416,7 +1416,7 @@ H5D_istore_prune (const H5D_io_info_t *io_info, size_t size) * begins. The pointers participating in the list traversal are each * given a chance at preemption before any of the pointers are advanced. */ - w[0] = (int)(rdcc->nused * H5F_RDCC_W0(io_info->dset->ent.file)); + w[0] = (int)(rdcc->nused * H5F_RDCC_W0(io_info->dset->oloc.file)); p[0] = rdcc->head; p[1] = NULL; @@ -1613,16 +1613,16 @@ H5D_istore_lock(const H5D_io_info_t *io_info, /* Chunk size on disk isn't [likely] the same size as the final chunk * size in memory, so allocate memory big enough. */ chunk_alloc = udata->common.key.nbytes; - if (NULL==(chunk = H5D_istore_chunk_alloc (chunk_alloc,pline))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for raw data chunk") - if (H5F_block_read(dset->ent.file, H5FD_MEM_DRAW, chunk_addr, udata->common.key.nbytes, io_info->dxpl_id, chunk)<0) - HGOTO_ERROR (H5E_IO, H5E_READERROR, NULL, "unable to read raw data chunk") - - if (pline->nused) - if (H5Z_pipeline(pline, H5Z_FLAG_REVERSE, &(udata->common.key.filter_mask), io_info->dxpl_cache->err_detect, - io_info->dxpl_cache->filter_cb, &(udata->common.key.nbytes), &chunk_alloc, &chunk)<0) { + if(NULL == (chunk = H5D_istore_chunk_alloc (chunk_alloc, pline))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for raw data chunk") + if(H5F_block_read(dset->oloc.file, H5FD_MEM_DRAW, chunk_addr, udata->common.key.nbytes, io_info->dxpl_id, chunk) < 0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, NULL, "unable to read raw data chunk") + + if(pline->nused) { + if(H5Z_pipeline(pline, H5Z_FLAG_REVERSE, &(udata->common.key.filter_mask), io_info->dxpl_cache->err_detect, + io_info->dxpl_cache->filter_cb, &(udata->common.key.nbytes), &chunk_alloc, &chunk) < 0) HGOTO_ERROR(H5E_PLINE, H5E_READERROR, NULL, "data pipeline read failed") - } + } /* end if */ #ifdef H5D_ISTORE_DEBUG rdcc->nmisses++; #endif /* H5D_ISTORE_DEBUG */ @@ -1923,7 +1923,7 @@ HDfprintf(stderr,"%s: buf=%p\n",FUNC,buf); * read-through of only the elements requested. */ if (dset->shared->dcpl_cache.pline.nused==0 && ((dset->shared->layout.u.chunk.size>dset->shared->cache.chunk.nbytes && chunk_addr!=HADDR_UNDEF) - || (IS_H5FD_MPI(dset->ent.file) && (H5F_ACC_RDWR & H5F_get_intent(dset->ent.file))))) { + || (IS_H5FD_MPI(dset->oloc.file) && (H5F_ACC_RDWR & H5F_get_intent(dset->oloc.file))))) { H5D_io_info_t chk_io_info; /* Temporary I/O info object */ H5D_storage_t chk_store; /* Chunk storage information */ @@ -1960,7 +1960,7 @@ HDfprintf(stderr,"%s: buf=%p\n",FUNC,buf); /* Check if the chunk is in the cache (but hasn't been written to disk yet) */ if (rdcc->nslots>0) { - unsigned idx=H5D_HASH(dset->shared,io_info->store->chunk.index); /* Cache entry index */ + unsigned idx=H5D_HASH(dset->shared, io_info->store->chunk.index); /* Cache entry index */ H5D_rdcc_ent_t *ent = rdcc->slot[idx]; /* Cache entry */ /* Potential match... */ @@ -2114,7 +2114,7 @@ HDfprintf(stderr,"%s: mem_offset_arr[%Zu]=%Hu\n",FUNC,*mem_curr_seq,mem_offset_a */ #ifdef H5_HAVE_PARALLEL /* Additional sanity checks when operating in parallel */ - if(IS_H5FD_MPI(dset->ent.file)) { + if(IS_H5FD_MPI(dset->oloc.file)) { if (chunk_addr==HADDR_UNDEF) HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "unable to locate raw data chunk") if (dset->shared->dcpl_cache.pline.nused>0) @@ -2123,7 +2123,7 @@ HDfprintf(stderr,"%s: mem_offset_arr[%Zu]=%Hu\n",FUNC,*mem_curr_seq,mem_offset_a #endif /* H5_HAVE_PARALLEL */ if (dset->shared->dcpl_cache.pline.nused==0 && ((dset->shared->layout.u.chunk.size>dset->shared->cache.chunk.nbytes && chunk_addr!=HADDR_UNDEF) - || (IS_H5FD_MPI(dset->ent.file) && (H5F_ACC_RDWR & H5F_get_intent(dset->ent.file))))) { + || (IS_H5FD_MPI(dset->oloc.file) && (H5F_ACC_RDWR & H5F_get_intent(dset->oloc.file))))) { H5D_io_info_t chk_io_info; /* Temporary I/O info object */ H5D_storage_t chk_store; /* Chunk storage information */ @@ -2291,7 +2291,7 @@ H5D_istore_allocated(H5D_t *dset, hid_t dxpl_id) HDmemset(&udata, 0, sizeof udata); udata.common.mesg = &dset->shared->layout; - if (H5B_iterate(dset->ent.file, dxpl_id, H5B_ISTORE, H5D_istore_iter_allocated, dset->shared->layout.u.chunk.addr, &udata)<0) + if(H5B_iterate(dset->oloc.file, dxpl_id, H5B_ISTORE, H5D_istore_iter_allocated, dset->shared->layout.u.chunk.addr, &udata) < 0) HGOTO_ERROR(H5E_IO, H5E_CANTINIT, 0, "unable to iterate over chunk B-tree") /* Set return value */ @@ -2341,7 +2341,7 @@ H5D_istore_get_addr(const H5D_io_info_t *io_info, H5D_istore_ud1_t *_udata) udata->addr = HADDR_UNDEF; /* Go get the chunk information */ - if (H5B_find (io_info->dset->ent.file, io_info->dxpl_id, H5B_ISTORE, io_info->dset->shared->layout.u.chunk.addr, udata)<0) { + if (H5B_find (io_info->dset->oloc.file, io_info->dxpl_id, H5B_ISTORE, io_info->dset->shared->layout.u.chunk.addr, udata)<0) { /* Note: don't push error on stack, leave that to next higher level, * since many times the B-tree is searched in order to determine * if a chunk exists in the B-tree or not. -QAK @@ -2516,13 +2516,13 @@ H5D_istore_allocate(H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite) #ifdef H5_HAVE_PARALLEL /* Retrieve MPI parameters */ - if(IS_H5FD_MPI(dset->ent.file)) { + if(IS_H5FD_MPI(dset->oloc.file)) { /* Get the MPI communicator */ - if (MPI_COMM_NULL == (mpi_comm=H5F_mpi_get_comm(dset->ent.file))) + if(MPI_COMM_NULL == (mpi_comm = H5F_mpi_get_comm(dset->oloc.file))) HGOTO_ERROR(H5E_INTERNAL, H5E_MPI, FAIL, "Can't retrieve MPI communicator") /* Get the MPI rank */ - if ((mpi_rank=H5F_mpi_get_rank(dset->ent.file))<0) + if((mpi_rank = H5F_mpi_get_rank(dset->oloc.file))<0) HGOTO_ERROR(H5E_INTERNAL, H5E_MPI, FAIL, "Can't retrieve MPI rank") /* Set the MPI-capable file driver flag */ @@ -2627,7 +2627,7 @@ H5D_istore_allocate(H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite) udata.common.key.offset[u] = chunk_offset[u]; /* Allocate the chunk with all processes */ - if (H5B_insert(dset->ent.file, dxpl_id, H5B_ISTORE, dset->shared->layout.u.chunk.addr, &udata)<0) + if(H5B_insert(dset->oloc.file, dxpl_id, H5B_ISTORE, dset->shared->layout.u.chunk.addr, &udata)<0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to allocate chunk") /* Check if fill values should be written to blocks */ @@ -2638,7 +2638,7 @@ H5D_istore_allocate(H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite) /* Write the chunks out from only one process */ /* !! Use the internal "independent" DXPL!! -QAK */ if(H5_PAR_META_WRITE==mpi_rank) { - if (H5F_block_write(dset->ent.file, H5FD_MEM_DRAW, udata.addr, udata.common.key.nbytes, H5AC_ind_dxpl_id, chunk)<0) + if(H5F_block_write(dset->oloc.file, H5FD_MEM_DRAW, udata.addr, udata.common.key.nbytes, H5AC_ind_dxpl_id, chunk) < 0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write raw data to file") } /* end if */ @@ -2647,7 +2647,7 @@ H5D_istore_allocate(H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite) } /* end if */ else { #endif /* H5_HAVE_PARALLEL */ - if (H5F_block_write(dset->ent.file, H5FD_MEM_DRAW, udata.addr, udata.common.key.nbytes, dxpl_id, chunk)<0) + if(H5F_block_write(dset->oloc.file, H5FD_MEM_DRAW, udata.addr, udata.common.key.nbytes, dxpl_id, chunk) < 0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write raw data to file") #ifdef H5_HAVE_PARALLEL } /* end else */ @@ -2852,7 +2852,7 @@ H5D_istore_prune_by_extent(const H5D_io_info_t *io_info) udata.common.mesg = &dset->shared->layout; udata.dims = curr_dims; - if(H5B_iterate(dset->ent.file, io_info->dxpl_id, H5B_ISTORE, H5D_istore_prune_extent, dset->shared->layout.u.chunk.addr, &udata) < 0) + if(H5B_iterate(dset->oloc.file, io_info->dxpl_id, H5B_ISTORE, H5D_istore_prune_extent, dset->shared->layout.u.chunk.addr, &udata) < 0) HGOTO_ERROR(H5E_IO, H5E_CANTINIT, 0, "unable to iterate over B-tree") done: diff --git a/src/H5Dmpio.c b/src/H5Dmpio.c index f4b3450..9d8821a 100644 --- a/src/H5Dmpio.c +++ b/src/H5Dmpio.c @@ -106,7 +106,7 @@ H5D_mpio_opt_possible( const H5D_io_info_t *io_info, /* Optimized MPI types flag must be set and it is must be collective IO */ /* (Don't allow parallel I/O for the MPI-posix driver, since it doesn't do real collective I/O) */ - if (!(H5S_mpi_opt_types_g && io_info->dxpl_cache->xfer_mode==H5FD_MPIO_COLLECTIVE && !IS_H5FD_MPIPOSIX(io_info->dset->ent.file))) { + if (!(H5S_mpi_opt_types_g && io_info->dxpl_cache->xfer_mode==H5FD_MPIO_COLLECTIVE && !IS_H5FD_MPIPOSIX(io_info->dset->oloc.file))) { local_opinion = FALSE; goto broadcast; } /* end if */ @@ -230,7 +230,7 @@ H5D_mpio_spaces_xfer(H5D_io_info_t *io_info, size_t elmt_size, assert (file_space); assert (mem_space); assert (buf); - assert (IS_H5FD_MPIO(io_info->dset->ent.file)); + assert (IS_H5FD_MPIO(io_info->dset->oloc.file)); /* Make certain we have the correct type of property list */ assert(TRUE==H5P_isa_class(io_info->dxpl_id,H5P_DATASET_XFER)); @@ -260,7 +260,7 @@ H5D_mpio_spaces_xfer(H5D_io_info_t *io_info, size_t elmt_size, assert(io_info->dset->shared->layout.type == H5D_CHUNKED); chunk_addr=H5D_istore_get_addr(io_info,NULL); - addr = H5F_BASE_ADDR(io_info->dset->ent.file) + chunk_addr + mpi_file_offset; + addr = H5F_BASE_ADDR(io_info->dset->oloc.file) + chunk_addr + mpi_file_offset; } /* @@ -276,10 +276,10 @@ H5D_mpio_spaces_xfer(H5D_io_info_t *io_info, size_t elmt_size, /* transfer the data */ if (do_write) { - if (H5F_block_write(io_info->dset->ent.file, H5FD_MEM_DRAW, addr, mpi_buf_count, io_info->dxpl_id, buf) <0) + if (H5F_block_write(io_info->dset->oloc.file, H5FD_MEM_DRAW, addr, mpi_buf_count, io_info->dxpl_id, buf) <0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL,"MPI write failed"); } else { - if (H5F_block_read (io_info->dset->ent.file, H5FD_MEM_DRAW, addr, mpi_buf_count, io_info->dxpl_id, buf) <0) + if (H5F_block_read (io_info->dset->oloc.file, H5FD_MEM_DRAW, addr, mpi_buf_count, io_info->dxpl_id, buf) <0) HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL,"MPI read failed"); } diff --git a/src/H5Dpkg.h b/src/H5Dpkg.h index 651f2b8..30efde1 100644 --- a/src/H5Dpkg.h +++ b/src/H5Dpkg.h @@ -174,7 +174,8 @@ typedef struct H5D_shared_t { } H5D_shared_t; struct H5D_t { - H5G_entry_t ent; /* cached object header stuff */ + H5O_loc_t oloc; /* Object header location */ + H5G_name_t path; /* Group hierarchy path */ H5D_shared_t *shared; /* cached information from file */ }; diff --git a/src/H5Dprivate.h b/src/H5Dprivate.h index dcd7f86..a9367dc 100644 --- a/src/H5Dprivate.h +++ b/src/H5Dprivate.h @@ -221,10 +221,11 @@ typedef struct H5D_dcpl_cache_t { /* Library Private Prototypes */ /******************************/ H5_DLL herr_t H5D_init(void); -H5_DLL H5D_t *H5D_open(const H5G_entry_t *ent, hid_t dxpl_id); +H5_DLL H5D_t *H5D_open(const H5G_loc_t *loc, hid_t dxpl_id); H5_DLL herr_t H5D_close(H5D_t *dataset); -H5_DLL htri_t H5D_isa(H5G_entry_t *ent, hid_t dxpl_id); -H5_DLL H5G_entry_t *H5D_entof(H5D_t *dataset); +H5_DLL htri_t H5D_isa(H5O_loc_t *loc, hid_t dxpl_id); +H5_DLL H5O_loc_t *H5D_oloc(H5D_t *dataset); +H5_DLL H5G_name_t *H5D_nameof(H5D_t *dataset); H5_DLL H5T_t *H5D_typeof(const H5D_t *dset); H5_DLL herr_t H5D_crt_copy(hid_t new_plist_t, hid_t old_plist_t, void *copy_data); diff --git a/src/H5Edefin.h b/src/H5Edefin.h index 03065e6..12582f4 100644 --- a/src/H5Edefin.h +++ b/src/H5Edefin.h @@ -89,6 +89,7 @@ hid_t H5E_ALIGNMENT_g = FAIL; /* Alignment error */ hid_t H5E_BADMESG_g = FAIL; /* Unrecognized message */ hid_t H5E_CANTDELETE_g = FAIL; /* Can't delete message */ hid_t H5E_BADITER_g = FAIL; /* Iteration failed */ +hid_t H5E_CANTPACK_g = FAIL; /* Can't pack messages */ /* FPHDF5 errors */ hid_t H5E_CANTRECV_g = FAIL; /* Can't receive messages from processes */ diff --git a/src/H5Einit.h b/src/H5Einit.h index 0efa7e6..bf31088 100644 --- a/src/H5Einit.h +++ b/src/H5Einit.h @@ -315,6 +315,11 @@ if((msg = H5E_create_msg(cls, H5E_MINOR, "Iteration failed"))==NULL) HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") if((H5E_BADITER_g = H5I_register(H5I_ERROR_MSG, msg))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") +assert(H5E_CANTPACK_g==(-1)); +if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't pack messages"))==NULL) + HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") +if((H5E_CANTPACK_g = H5I_register(H5I_ERROR_MSG, msg))<0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") /* FPHDF5 errors */ assert(H5E_CANTRECV_g==(-1)); diff --git a/src/H5Epubgen.h b/src/H5Epubgen.h index f694109..4245a5c 100644 --- a/src/H5Epubgen.h +++ b/src/H5Epubgen.h @@ -143,12 +143,14 @@ H5_DLLVAR hid_t H5E_DUPCLASS_g; /* Duplicate class name in parent class */ #define H5E_BADMESG (H5OPEN H5E_BADMESG_g) #define H5E_CANTDELETE (H5OPEN H5E_CANTDELETE_g) #define H5E_BADITER (H5OPEN H5E_BADITER_g) +#define H5E_CANTPACK (H5OPEN H5E_CANTPACK_g) H5_DLLVAR hid_t H5E_LINKCOUNT_g; /* Bad object header link count */ H5_DLLVAR hid_t H5E_VERSION_g; /* Wrong version number */ H5_DLLVAR hid_t H5E_ALIGNMENT_g; /* Alignment error */ H5_DLLVAR hid_t H5E_BADMESG_g; /* Unrecognized message */ H5_DLLVAR hid_t H5E_CANTDELETE_g; /* Can't delete message */ H5_DLLVAR hid_t H5E_BADITER_g; /* Iteration failed */ +H5_DLLVAR hid_t H5E_CANTPACK_g; /* Can't pack messages */ /* FPHDF5 errors */ #define H5E_CANTRECV (H5OPEN H5E_CANTRECV_g) diff --git a/src/H5Eterm.h b/src/H5Eterm.h index e36a5ab..00eee70 100644 --- a/src/H5Eterm.h +++ b/src/H5Eterm.h @@ -90,7 +90,8 @@ H5E_VERSION_g= H5E_ALIGNMENT_g= H5E_BADMESG_g= H5E_CANTDELETE_g= -H5E_BADITER_g= +H5E_BADITER_g= +H5E_CANTPACK_g= /* FPHDF5 errors */ H5E_CANTRECV_g= @@ -28,8 +28,8 @@ #include "H5FDprivate.h" /* File drivers */ #include "H5FLprivate.h" /* Free lists */ #include "H5FPprivate.h" /* Flexible parallel */ -#include "H5Iprivate.h" /* IDs */ #include "H5Gprivate.h" /* Groups */ +#include "H5Iprivate.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ #include "H5Pprivate.h" /* Property lists */ #include "H5Tprivate.h" /* Datatypes */ @@ -1157,23 +1157,23 @@ H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key) HGOTO_DONE(TRUE) /* Indicate that the iterator should stop */ } } else { /* either count opened object IDs or put the IDs on the list */ - H5G_entry_t *ent; /* Group entry info for object */ + H5O_loc_t *oloc; /* Group entry info for object */ switch(olist->obj_type) { case H5I_ATTR: - ent = H5A_entof((H5A_t*)obj_ptr); + oloc = H5A_oloc((H5A_t*)obj_ptr); break; case H5I_GROUP: - ent = H5G_entof((H5G_t*)obj_ptr); + oloc = H5G_oloc((H5G_t*)obj_ptr); break; case H5I_DATASET: - ent = H5D_entof((H5D_t*)obj_ptr); + oloc = H5D_oloc((H5D_t*)obj_ptr); break; case H5I_DATATYPE: if(H5T_is_named((H5T_t*)obj_ptr)==TRUE) - ent = H5T_entof((H5T_t*)obj_ptr); + oloc = H5T_oloc((H5T_t*)obj_ptr); else - ent = NULL; + oloc = NULL; break; default: HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "unknown data object") @@ -1182,11 +1182,11 @@ H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key) if((olist->file_info.local && ( (!olist->file_info.ptr.file && olist->obj_type==H5I_DATATYPE && H5T_is_immutable((H5T_t*)obj_ptr)==FALSE) || (!olist->file_info.ptr.file && olist->obj_type!=H5I_DATATYPE) - || (ent && ent->file == olist->file_info.ptr.file) )) + || (oloc && oloc->file == olist->file_info.ptr.file) )) || (!olist->file_info.local && ((!olist->file_info.ptr.shared && olist->obj_type==H5I_DATATYPE && H5T_is_immutable((H5T_t*)obj_ptr)==FALSE) || (!olist->file_info.ptr.shared && olist->obj_type!=H5I_DATATYPE) - || (ent && ent->file && ent->file->shared == olist->file_info.ptr.shared) ))) { + || (oloc && oloc->file && oloc->file->shared == olist->file_info.ptr.shared) ))) { /* Add the object's ID to the ID list, if appropriate */ if(olist->obj_id_list) { olist->obj_id_list[olist->list_index] = obj_id; @@ -1749,7 +1749,9 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t d H5F_t *file = NULL; /*the success return value */ H5F_file_t *shared = NULL; /*shared part of `file' */ H5FD_t *lf = NULL; /*file driver part of `shared' */ - H5G_entry_t root_ent; /*root symbol table entry */ + H5G_loc_t root_loc; /*root location */ + H5O_loc_t root_oloc; /*root object location */ + H5G_name_t root_path; /*root group hier. path */ unsigned tent_flags; /*tentative flags */ H5FD_class_t *drvr; /*file driver class info */ hbool_t driver_has_cmp; /*`cmp' callback defined? */ @@ -1760,6 +1762,10 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t d FUNC_ENTER_NOAPI(H5F_open, NULL) + /* Set up root location to fill in */ + root_loc.oloc = &root_oloc; + root_loc.path = &root_path; + /* * If the driver has a `cmp' method then the driver is capable of * determining when two file handles refer to the same file and the @@ -1951,7 +1957,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t d if (!H5FD_fphdf5_is_captain(lf)) { /* Allocate room for the superblock buffer */ H5_CHECK_OVERFLOW(super_info.size, hsize_t, size_t); - if((buf=H5MM_malloc((size_t)super_info.size))==NULL) + if((buf = H5MM_malloc((size_t)super_info.size))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for superblock buffer") } /* end if */ @@ -1962,7 +1968,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t d HMPI_GOTO_ERROR(NULL, "MPI_Bcast failed", mrc) if (!H5FD_fphdf5_is_captain(lf)) { - if (H5F_read_superblock(file, dxpl_id, &root_ent, super_info.addr, + if (H5F_read_superblock(file, dxpl_id, &root_loc, super_info.addr, buf, (size_t)super_info.size) < 0) HGOTO_ERROR(H5E_FILE, H5E_READERROR, NULL, "unable to read superblock") } @@ -1973,12 +1979,10 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t d * JRM - 4/13/04 */ if ( (mrc = MPI_Barrier(H5FP_SAP_BARRIER_COMM)) != MPI_SUCCESS ) - { HMPI_GOTO_ERROR(NULL, "MPI_Barrier failed", mrc) - } if (!H5FD_fphdf5_is_captain(lf)) { - if (H5G_mkroot(file, dxpl_id, &root_ent) < 0) + if (H5G_mkroot(file, dxpl_id, &root_loc) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create/open root group") } @@ -1992,7 +1996,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t d #endif /* H5_HAVE_FPHDF5 */ /* Read the superblock if it hasn't been read before. */ - if (H5F_read_superblock(file, dxpl_id, &root_ent, HADDR_UNDEF, NULL, (size_t)0) < 0) + if(H5F_read_superblock(file, dxpl_id, &root_loc, HADDR_UNDEF, NULL, (size_t)0) < 0) HGOTO_ERROR(H5E_FILE, H5E_READERROR, NULL, "unable to read superblock") #ifdef H5_HAVE_FPHDF5 @@ -2001,14 +2005,13 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t d * race conditions with allocations, make sure that everyone is done * reading the superblock before we proceed. */ - if ( (mrc = MPI_Barrier(H5FP_SAP_BARRIER_COMM)) != MPI_SUCCESS ) { + if ( (mrc = MPI_Barrier(H5FP_SAP_BARRIER_COMM)) != MPI_SUCCESS ) HMPI_GOTO_ERROR(NULL, "MPI_Barrier failed", mrc) - } - } + } /* end if */ #endif /* H5_HAVE_FPHDF5 */ /* Make sure we can open the root group */ - if (H5G_mkroot(file, dxpl_id, &root_ent)<0) + if (H5G_mkroot(file, dxpl_id, &root_loc)<0) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to read root group") } @@ -2270,61 +2273,61 @@ H5Fflush(hid_t object_id, H5F_scope_t scope) H5T_t *type = NULL; H5D_t *dset = NULL; H5A_t *attr = NULL; - H5G_entry_t *ent = NULL; + H5O_loc_t *oloc = NULL; herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_API(H5Fflush, FAIL) H5TRACE2("e","iFs",object_id,scope); - switch (H5I_get_type(object_id)) { + switch(H5I_get_type(object_id)) { case H5I_FILE: - if (NULL==(f=H5I_object(object_id))) + if(NULL == (f = H5I_object(object_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") break; case H5I_GROUP: - if (NULL==(grp=H5I_object(object_id))) + if(NULL == (grp = H5I_object(object_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid group identifier") - ent = H5G_entof(grp); + oloc = H5G_oloc(grp); break; case H5I_DATATYPE: - if (NULL==(type=H5I_object(object_id))) + if(NULL == (type = H5I_object(object_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid type identifier") - ent = H5T_entof(type); + oloc = H5T_oloc(type); break; case H5I_DATASET: - if (NULL==(dset=H5I_object(object_id))) + if(NULL == (dset = H5I_object(object_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataset identifier") - ent = H5D_entof(dset); + oloc = H5D_oloc(dset); break; case H5I_ATTR: - if (NULL==(attr=H5I_object(object_id))) + if(NULL == (attr = H5I_object(object_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid attribute identifier") - ent = H5A_entof(attr); + oloc = H5A_oloc(attr); break; default: HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object") - } + } /* end switch */ - if (!f) { - if (!ent) + if(!f) { + if(!oloc) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "object is not assocated with a file") - f = ent->file; - } - if (!f) + f = oloc->file; + } /* end if */ + if(!f) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "object is not associated with a file") /* Flush the file */ - if (H5F_flush(f, H5AC_dxpl_id, scope, H5F_FLUSH_NONE) < 0) + if(H5F_flush(f, H5AC_dxpl_id, scope, H5F_FLUSH_NONE) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "flush failed") done: FUNC_LEAVE_API(ret_value) -} +} /* end H5Fflush() */ /*------------------------------------------------------------------------- @@ -3245,7 +3248,6 @@ done: * Programmer: Raymond Lu * Oct 29, 2003 * - * Modifications: *------------------------------------------------------------------------- */ hid_t @@ -3255,17 +3257,17 @@ H5F_get_id(H5F_t *file) FUNC_ENTER_NOAPI_NOINIT(H5F_get_id) - assert(file); + HDassert(file); if(file->file_id == -1) { /* Get an atom for the file */ - if ((file->file_id = H5I_register(H5I_FILE, file))<0) + if((file->file_id = H5I_register(H5I_FILE, file)) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize file") } else { /* Increment reference count on atom. */ - if (H5I_inc_ref(file->file_id)<0) - HGOTO_ERROR (H5E_ATOM, H5E_CANTSET, FAIL, "incrementing file ID failed") - } + if(H5I_inc_ref(file->file_id)<0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTSET, FAIL, "incrementing file ID failed") + } /* end else */ ret_value = file->file_id; @@ -3507,6 +3509,37 @@ H5F_sieve_buf_size(const H5F_t *f) /*------------------------------------------------------------------------- + * Function: H5F_gc_ref + * + * Purpose: Replaced a macro to retrieve the "garbage collect + * references flag" now that the generic properties are being used + * to store the values. + * + * Return: Success: The "garbage collect references flag" + * is returned. + * + * Failure: (should not happen) + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Jul 8 2005 + * + *------------------------------------------------------------------------- + */ +unsigned +H5F_gc_ref(const H5F_t *f) +{ + /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_gc_ref) + + HDassert(f); + HDassert(f->shared); + + FUNC_LEAVE_NOAPI(f->shared->gc_ref) +} /* end H5F_gc_ref() */ + + +/*------------------------------------------------------------------------- * Function: H5F_get_fcpl * * Purpose: Retrieve the value of a file's FCPL. @@ -4148,9 +4181,8 @@ done: ssize_t H5Fget_name(hid_t obj_id, char *name/*out*/, size_t size) { - H5G_entry_t *ent; /*symbol table entry */ - H5F_t *f; /* Top file in mount hierarchy */ - size_t len=0; + H5F_t *f; /* Top file in mount hierarchy */ + size_t len; ssize_t ret_value; FUNC_ENTER_API (H5Fget_name, FAIL) @@ -4161,14 +4193,16 @@ H5Fget_name(hid_t obj_id, char *name/*out*/, size_t size) * the top file in a mount hierarchy) */ if(H5I_get_type(obj_id) == H5I_FILE ) { - if (NULL==(f=H5I_object(obj_id))) + if(NULL == (f = H5I_object(obj_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file") } /* end if */ else { + H5G_loc_t loc; /* Object location */ + /* Get symbol table entry */ - if((ent = H5G_loc(obj_id))==NULL) + if(H5G_loc(obj_id, &loc) < 0) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a valid object ID") - f = ent->file; + f = loc.oloc->file; } /* end else */ len = HDstrlen(f->name); diff --git a/src/H5FDcore.c b/src/H5FDcore.c index 492e06f..713a3ff 100644 --- a/src/H5FDcore.c +++ b/src/H5FDcore.c @@ -776,6 +776,9 @@ H5FD_core_write(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, had x = H5MM_malloc(new_eof); else x = H5MM_realloc(file->mem, new_eof); +#ifdef H5_USING_PURIFY +HDmemset(x + file->eof, 0, (size_t)(new_eof - file->eof)); +#endif /* H5_USING_PURIFY */ if (!x) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory block") file->mem = x; diff --git a/src/H5FDmulti.c b/src/H5FDmulti.c index a1a065e..652bd53 100644 --- a/src/H5FDmulti.c +++ b/src/H5FDmulti.c @@ -779,8 +779,8 @@ H5FD_multi_sb_encode(H5FD_t *_file, char *name/*out*/, assert(7==H5FD_MEM_NTYPES); for (m=H5FD_MEM_SUPER; m<H5FD_MEM_NTYPES; m=(H5FD_mem_t)(m+1)) buf[m-1] = (unsigned char)file->fa.memb_map[m]; + buf[6] = 0; buf[7] = 0; - buf[8] = 0; /* * Copy the starting addresses and EOA values into the buffer in order of diff --git a/src/H5Fdbg.c b/src/H5Fdbg.c index 4048ba0..3700067 100644 --- a/src/H5Fdbg.c +++ b/src/H5Fdbg.c @@ -19,11 +19,13 @@ */ #define H5F_PACKAGE /*suppress error about including H5Fpkg */ +#define H5G_PACKAGE /*suppress error about including H5Gpkg */ #include "H5private.h" /* Generic Functions */ #include "H5Eprivate.h" /* Error handling */ #include "H5Fpkg.h" /* File access */ +#include "H5Gpkg.h" /* Groups */ #include "H5Iprivate.h" /* ID Functions */ #include "H5Pprivate.h" /* Property lists */ @@ -132,7 +134,20 @@ H5F_debug(H5F_t *f, hid_t dxpl_id, FILE * stream, int indent, int fwidth) "Root group symbol table entry:", f->shared->root_grp ? "" : "(none)"); if (f->shared->root_grp) { - H5G_ent_debug(f, dxpl_id, H5G_entof(f->shared->root_grp), stream, + H5O_loc_t *root_oloc; /* Root object location */ + H5G_entry_t root_ent; /* Constructed root symbol table entry */ + + /* Reset the root group entry */ + H5G_ent_reset(&root_ent); + + /* Build up a simulated root group symbol table entry */ + root_oloc = H5G_oloc(f->shared->root_grp); + HDassert(root_oloc); + root_ent.type = H5G_NOTHING_CACHED; + root_ent.header = root_oloc->addr; + root_ent.file = f; + + H5G_ent_debug(f, dxpl_id, &root_ent, stream, indent+3, MAX(0, fwidth-3), HADDR_UNDEF); } diff --git a/src/H5Fmount.c b/src/H5Fmount.c index c876b15..ebb76fb 100644 --- a/src/H5Fmount.c +++ b/src/H5Fmount.c @@ -28,6 +28,10 @@ #include "H5MMprivate.h" /* Memory management */ /* PRIVATE PROTOTYPES */ +static herr_t H5F_mount(H5G_loc_t *loc, const char *name, H5F_t *child, + hid_t plist_id, hid_t dxpl_id); +static herr_t H5F_unmount(H5G_loc_t *loc, const char *name, hid_t dxpl_id); +static void H5F_mount_count_ids_recurse(H5F_t *f, unsigned *nopen_files, unsigned *nopen_objs); /*-------------------------------------------------------------------------- @@ -62,8 +66,6 @@ H5F_init_mount_interface(void) * Programmer: Quincey Koziol * Saturday, July 2, 2005 * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t @@ -108,56 +110,54 @@ done: * Programmer: Robb Matzke * Tuesday, October 6, 1998 * - * Modifications: - * - * Robb Matzke, 1998-10-14 - * The reference count for the mounted H5F_t is incremented. - * - * Pedro Vicente, <pvn@ncsa.uiuc.edu> 22 Aug 2002 - * Added `id to name' support. - * *------------------------------------------------------------------------- */ static herr_t -H5F_mount(H5G_entry_t *loc, const char *name, H5F_t *child, +H5F_mount(H5G_loc_t *loc, const char *name, H5F_t *child, hid_t UNUSED plist_id, hid_t dxpl_id) { H5G_t *mount_point = NULL; /*mount point group */ - H5G_entry_t *mp_ent = NULL; /*mount point symbol table entry*/ H5F_t *ancestor = NULL; /*ancestor files */ H5F_t *parent = NULL; /*file containing mount point */ unsigned lt, rt, md; /*binary search indices */ int cmp; /*binary search comparison value*/ - H5G_entry_t *ent = NULL; /*temporary symbol table entry */ - H5G_entry_t mp_open_ent; /* entry of moint point to be opened */ + H5G_loc_t mp_loc; /* entry of moint point to be opened */ + H5G_name_t mp_path; /* Mount point group hier. path */ + H5O_loc_t mp_oloc; /* Mount point object location */ + H5O_loc_t *mnt_oloc; /* Mount point object location */ H5RS_str_t *name_r; /* Ref-counted version of name */ herr_t ret_value = SUCCEED; /*return value */ FUNC_ENTER_NOAPI_NOINIT(H5F_mount) - assert(loc); - assert(name && *name); - assert(child); - assert(TRUE==H5P_isa_class(plist_id,H5P_MOUNT)); + HDassert(loc); + HDassert(name && *name); + HDassert(child); + HDassert(TRUE == H5P_isa_class(plist_id,H5P_MOUNT)); + + /* Set up dataset location to fill in */ + mp_loc.oloc = &mp_oloc; + mp_loc.path = &mp_path; + H5G_loc_reset(&mp_loc); /* * Check that the child isn't mounted, that the mount point exists, that * the parent & child files have the same file close degree, and * that the mount wouldn't introduce a cycle in the mount tree. */ - if (child->mtab.parent) + if(child->mtab.parent) HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "file is already mounted") - if (H5G_find(loc, name, &mp_open_ent/*out*/, H5AC_dxpl_id) < 0) + if(H5G_loc_find(loc, name, &mp_loc/*out*/, dxpl_id) < 0) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "group not found") - if (NULL==(mount_point=H5G_open(&mp_open_ent, dxpl_id))) + if(NULL == (mount_point = H5G_open(&mp_loc, dxpl_id))) HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "mount point not found") parent = H5G_fileof(mount_point); - mp_ent = H5G_entof(mount_point); - for (ancestor=parent; ancestor; ancestor=ancestor->mtab.parent) { - if (ancestor==child) + mnt_oloc = H5G_oloc(mount_point); + for(ancestor = parent; ancestor; ancestor = ancestor->mtab.parent) { + if(ancestor == child) HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "mount would introduce a cycle") - } + } /* end for */ if(parent->shared->fc_degree != child->shared->fc_degree) HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "mounted file has different file close degree than parent") @@ -168,62 +168,63 @@ H5F_mount(H5G_entry_t *loc, const char *name, H5F_t *child, * `md' will be the index where the child should be inserted. */ lt = md = 0; - rt=parent->mtab.nmounts; + rt = parent->mtab.nmounts; cmp = -1; - while (lt<rt && cmp) { - md = (lt+rt)/2; - ent = H5G_entof(parent->mtab.child[md].group); - cmp = H5F_addr_cmp(mp_ent->header, ent->header); - if (cmp<0) { + while(lt < rt && cmp) { + H5O_loc_t *oloc; /*temporary symbol table entry */ + + md = (lt + rt) / 2; + oloc = H5G_oloc(parent->mtab.child[md].group); + cmp = H5F_addr_cmp(mnt_oloc->addr, oloc->addr); + if(cmp < 0) rt = md; - } else if (cmp>0) { - lt = md+1; - } - } - if (cmp>0) + else if(cmp > 0) + lt = md + 1; + } /* end while */ + if(cmp > 0) md++; - if (!cmp) + if(!cmp) HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "mount point is already in use") /* Make room in the table */ - if (parent->mtab.nmounts>=parent->mtab.nalloc) { + if(parent->mtab.nmounts>=parent->mtab.nalloc) { unsigned n = MAX(16, 2*parent->mtab.nalloc); H5F_mount_t *x = H5MM_realloc(parent->mtab.child, - n*sizeof(parent->mtab.child[0])); + n * sizeof(parent->mtab.child[0])); if (!x) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for mount table") parent->mtab.child = x; parent->mtab.nalloc = n; - } + } /* end if */ /* Insert into table */ - HDmemmove(parent->mtab.child+md+1, parent->mtab.child+md, - (parent->mtab.nmounts-md)*sizeof(parent->mtab.child[0])); + HDmemmove(parent->mtab.child + md + 1, parent->mtab.child + md, + (parent->mtab.nmounts-md) * sizeof(parent->mtab.child[0])); parent->mtab.nmounts++; parent->mtab.child[md].group = mount_point; parent->mtab.child[md].file = child; child->mtab.parent = parent; /* Set the group's mountpoint flag */ - if(H5G_mount(parent->mtab.child[md].group)<0) + if(H5G_mount(parent->mtab.child[md].group) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to set group mounted flag") /* Search the open IDs and replace names for mount operation */ /* We pass H5G_UNKNOWN as object type; search all IDs */ - name_r=H5RS_wrap(name); - assert(name_r); - if (H5G_replace_name( H5G_UNKNOWN, loc, name_r, NULL, NULL, NULL, OP_MOUNT )<0) + name_r = H5RS_wrap(name); + HDassert(name_r); + if(H5G_name_replace(H5G_UNKNOWN, loc, name_r, NULL, NULL, NULL, OP_MOUNT) < 0) HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "unable to replace name") - if(H5RS_decr(name_r)<0) + if(H5RS_decr(name_r) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTDEC, FAIL, "unable to decrement name string") done: - if (ret_value<0 && mount_point) - if(H5G_close(mount_point)<0) + if(ret_value < 0 && mount_point) + if(H5G_close(mount_point) < 0) HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to close mounted group") FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5F_mount() */ /*------------------------------------------------------------------------- @@ -242,50 +243,46 @@ done: * Programmer: Robb Matzke * Tuesday, October 6, 1998 * - * Modifications: - * - * Robb Matzke, 1998-10-14 - * The ref count for the child is decremented by calling H5F_close(). - * - * Pedro Vicente, <pvn@ncsa.uiuc.edu> 22 Aug 2002 - * Added `id to name' support. - * *------------------------------------------------------------------------- */ static herr_t -H5F_unmount(H5G_entry_t *loc, const char *name, hid_t dxpl_id) +H5F_unmount(H5G_loc_t *loc, const char *name, hid_t dxpl_id) { - H5G_t *mounted = NULL; /*mount point group */ H5G_t *child_group = NULL; /* Child's group in parent mtab */ H5F_t *child_file = NULL; /* Child's file in parent mtab */ - H5G_entry_t *mnt_ent = NULL; /*mounted symbol table entry */ H5F_t *child = NULL; /*mounted file */ H5F_t *parent = NULL; /*file where mounted */ - H5G_entry_t *ent = NULL; /*temporary symbol table entry */ - H5G_entry_t mnt_open_ent; /* entry used to open mount point*/ + H5O_loc_t *mnt_oloc; /* symbol table entry for root of mounted file */ + H5G_name_t mp_path; /* Mount point group hier. path */ + H5O_loc_t mp_oloc; /* Mount point object location */ + H5G_loc_t mp_loc; /* entry used to open mount point*/ + hbool_t mp_loc_setup = FALSE; /* Whether mount point location is set up */ int child_idx; /* Index of child in parent's mtab */ herr_t ret_value = SUCCEED; /*return value */ FUNC_ENTER_NOAPI_NOINIT(H5F_unmount) - assert(loc); - assert(name && *name); + HDassert(loc); + HDassert(name && *name); + + /* Set up mount point location to fill in */ + mp_loc.oloc = &mp_oloc; + mp_loc.path = &mp_path; + H5G_loc_reset(&mp_loc); /* * Get the mount point, or more precisely the root of the mounted file. * If we get the root group and the file has a parent in the mount tree, * then we must have found the mount point. */ - if (H5G_find(loc, name, &mnt_open_ent/*out*/, H5AC_dxpl_id) < 0) + if(H5G_loc_find(loc, name, &mp_loc/*out*/, dxpl_id) < 0) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "group not found") - if (NULL==(mounted=H5G_open(&mnt_open_ent, dxpl_id))) - HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "mount point not found") - child = H5G_fileof(mounted); - mnt_ent = H5G_entof(mounted); - ent = H5G_entof(child->shared->root_grp); + mp_loc_setup = TRUE; + child = mp_loc.oloc->file; + mnt_oloc = H5G_oloc(child->shared->root_grp); child_idx = -1; - if (child->mtab.parent && H5F_addr_eq(mnt_ent->header, ent->header)) { + if(child->mtab.parent && H5F_addr_eq(mp_oloc.addr, mnt_oloc->addr)) { unsigned u; /*counters */ /* @@ -293,15 +290,15 @@ H5F_unmount(H5G_entry_t *loc, const char *name, hid_t dxpl_id) * lookup in the parent's mount table to find the correct entry. */ parent = child->mtab.parent; - for (u=0; u<parent->mtab.nmounts; u++) { - if (parent->mtab.child[u].file==child) { + for(u = 0; u < parent->mtab.nmounts; u++) { + if(parent->mtab.child[u].file == child) { /* Found the correct index */ child_idx = u; break; - } - } + } /* end if */ + } /* end for */ } else { - unsigned lt, rt, md=0; /*binary search indices */ + unsigned lt, rt, md = 0; /*binary search indices */ int cmp; /*binary search comparison value*/ /* @@ -312,130 +309,58 @@ H5F_unmount(H5G_entry_t *loc, const char *name, hid_t dxpl_id) lt = 0; rt = parent->mtab.nmounts; cmp = -1; - while (lt<rt && cmp) { - md = (lt+rt)/2; - ent = H5G_entof(parent->mtab.child[md].group); - cmp = H5F_addr_cmp(mnt_ent->header, ent->header); - if (cmp<0) { + while(lt < rt && cmp) { + md = (lt + rt) / 2; + mnt_oloc = H5G_oloc(parent->mtab.child[md].group); + cmp = H5F_addr_cmp(mp_oloc.addr, mnt_oloc->addr); + if (cmp<0) rt = md; - } else { - lt = md+1; - } - } - if (cmp) + else + lt = md + 1; + } /* end while */ + if(cmp) HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "not a mount point") - /* Found the correct index */ + /* Found the correct index, set the info about the child */ child_idx = md; - mnt_ent = ent; - } - + H5G_loc_free(&mp_loc); + mp_loc_setup = FALSE; + mp_loc.oloc = mnt_oloc; + mp_loc.path = H5G_nameof(parent->mtab.child[md].group); + } /* end else */ HDassert(child_idx >= 0); /* Search the open IDs replace names to reflect unmount operation */ - if (H5G_replace_name(H5G_UNKNOWN, mnt_ent, mnt_ent->user_path_r, NULL, NULL, NULL, OP_UNMOUNT )<0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to replace name ") + if(H5G_name_replace(H5G_UNKNOWN, &mp_loc, mp_loc.path->user_path_r, NULL, NULL, NULL, OP_UNMOUNT) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to replace name") /* Save the information about the child from the mount table */ child_group = parent->mtab.child[child_idx].group; child_file = parent->mtab.child[child_idx].file; /* Eliminate the mount point from the table */ - HDmemmove(parent->mtab.child+child_idx, parent->mtab.child+child_idx+1, - (parent->mtab.nmounts-child_idx)*sizeof(parent->mtab.child[0])); + HDmemmove(parent->mtab.child + child_idx, parent->mtab.child + child_idx + 1, + (parent->mtab.nmounts-child_idx) * sizeof(parent->mtab.child[0])); parent->mtab.nmounts -= 1; /* Unmount the child file from the parent file */ - if(H5G_unmount(child_group)<0) + if(H5G_unmount(child_group) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to reset group mounted flag") - if(H5G_close(child_group)<0) + if(H5G_close(child_group) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to close unmounted group") /* Detach child file from parent & see if it should close */ child_file->mtab.parent = NULL; - if(H5F_try_close(child_file)<0) + if(H5F_try_close(child_file) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close unmounted file") done: - if (mounted) - if(H5G_close(mounted)<0 && ret_value>=0) - HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "can't close group") + /* Free the mount point location's information, if it's been set up */ + if(mp_loc_setup) + H5G_loc_free(&mp_loc); FUNC_LEAVE_NOAPI(ret_value) -} - - -/*------------------------------------------------------------------------- - * Function: H5F_mountpoint - * - * Purpose: If ENT is a mount point then copy the entry for the root - * group of the mounted file into ENT. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Tuesday, October 6, 1998 - * - * Modifications: - * - * Pedro Vicente, <pvn@ncsa.uiuc.edu> 22 Aug 2002 - * Added `id to name' support. - * - *------------------------------------------------------------------------- - */ -herr_t -H5F_mountpoint(H5G_entry_t *find/*in,out*/) -{ - H5F_t *parent = find->file; - unsigned lt, rt, md=0; - int cmp; - H5G_entry_t *ent = NULL; - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5F_mountpoint, FAIL) - - assert(find); - - /* - * The loop is necessary because we might have file1 mounted at the root - * of file2, which is mounted somewhere in file3. - */ - do { - /* - * Use a binary search to find the potential mount point in the mount - * table for the parent - */ - lt = 0; - rt = parent->mtab.nmounts; - cmp = -1; - while (lt<rt && cmp) { - md = (lt+rt)/2; - ent = H5G_entof(parent->mtab.child[md].group); - cmp = H5F_addr_cmp(find->header, ent->header); - if (cmp<0) { - rt = md; - } else { - lt = md+1; - } - } - - /* Copy root info over to ENT */ - if (0==cmp) { - /* Get the entry for the root group in the child's file */ - ent = H5G_entof(parent->mtab.child[md].file->shared->root_grp); - - /* Don't lose the user path of the group when we copy the root group's entry */ - if(H5G_ent_copy(find,ent,H5G_COPY_LIMITED)<0) - HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, FAIL, "unable to copy group entry") - - /* Switch to child's file */ - parent = ent->file; - } - } while (!cmp); - -done: - FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5F_unmount() */ /*------------------------------------------------------------------------- @@ -444,30 +369,27 @@ done: * Purpose: Check if a file has mounted files within it. * * Return: Success: TRUE/FALSE - * Failure: Negative + * Failure: (can't happen) * * Programmer: Quincey Koziol * Thursday, January 2, 2002 * - * Modifications: - * *------------------------------------------------------------------------- */ -htri_t +hbool_t H5F_has_mount(const H5F_t *file) { - htri_t ret_value; /* Return value */ + hbool_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5F_has_mount, FAIL) + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_has_mount) - assert(file); + HDassert(file); - if(file->mtab.nmounts>0) - ret_value=TRUE; + if(file->mtab.nmounts > 0) + ret_value = TRUE; else - ret_value=FALSE; + ret_value = FALSE; -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5F_has_mount() */ @@ -478,30 +400,27 @@ done: * Purpose: Check if a file is mounted within another file. * * Return: Success: TRUE/FALSE - * Failure: Negative + * Failure: (can't happen) * * Programmer: Quincey Koziol * Thursday, January 2, 2002 * - * Modifications: - * *------------------------------------------------------------------------- */ -htri_t +hbool_t H5F_is_mount(const H5F_t *file) { - htri_t ret_value; /* Return value */ + hbool_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5F_is_mount, FAIL) + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_is_mount) - assert(file); + HDassert(file); - if(file->mtab.parent!=NULL) - ret_value=TRUE; + if(file->mtab.parent != NULL) + ret_value = TRUE; else - ret_value=FALSE; + ret_value = FALSE; -done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5F_is_mount() */ @@ -517,26 +436,24 @@ done: * Programmer: Robb Matzke * Tuesday, October 6, 1998 * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t H5Fmount(hid_t loc_id, const char *name, hid_t child_id, hid_t plist_id) { - H5G_entry_t *loc = NULL; - H5F_t *child = NULL; + H5G_loc_t loc; + H5F_t *child = NULL; herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_API(H5Fmount, FAIL) H5TRACE4("e","isii",loc_id,name,child_id,plist_id); /* Check arguments */ - if (NULL==(loc=H5G_loc(loc_id))) + if(H5G_loc(loc_id, &loc) < 0) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") - if (!name || !*name) + if(!name || !*name) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") - if (NULL==(child=H5I_object_verify(child_id,H5I_FILE))) + if(NULL == (child = H5I_object_verify(child_id,H5I_FILE))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file") if(H5P_DEFAULT == plist_id) plist_id = H5P_MOUNT_DEFAULT; @@ -545,12 +462,12 @@ H5Fmount(hid_t loc_id, const char *name, hid_t child_id, hid_t plist_id) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not property list") /* Do the mount */ - if (H5F_mount(loc, name, child, plist_id, H5AC_dxpl_id)<0) + if(H5F_mount(&loc, name, child, plist_id, H5AC_dxpl_id) < 0) HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "unable to mount file") done: FUNC_LEAVE_API(ret_value) -} +} /* end H5Fmount() */ /*------------------------------------------------------------------------- @@ -570,32 +487,30 @@ done: * Programmer: Robb Matzke * Tuesday, October 6, 1998 * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t H5Funmount(hid_t loc_id, const char *name) { - H5G_entry_t *loc = NULL; + H5G_loc_t loc; herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_API(H5Funmount, FAIL) H5TRACE2("e","is",loc_id,name); /* Check args */ - if (NULL==(loc=H5G_loc(loc_id))) + if(H5G_loc(loc_id, &loc) < 0) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") - if (!name || !*name) + if(!name || !*name) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") /* Unmount */ - if (H5F_unmount(loc, name, H5AC_dxpl_id)<0) + if (H5F_unmount(&loc, name, H5AC_dxpl_id) < 0) HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "unable to unmount file") done: FUNC_LEAVE_API(ret_value) -} +} /* end H5Funmount() */ /*------------------------------------------------------------------------- @@ -609,8 +524,6 @@ done: * Programmer: Quincey Koziol * Tuesday, July 19, 2005 * - * Modifications: - * *------------------------------------------------------------------------- */ static void @@ -658,8 +571,6 @@ H5F_mount_count_ids_recurse(H5F_t *f, unsigned *nopen_files, unsigned *nopen_obj * Programmer: Quincey Koziol * Tues, July 19, 2005 * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h index 4cac069..10facbf 100644 --- a/src/H5Fpkg.h +++ b/src/H5Fpkg.h @@ -58,7 +58,7 @@ #endif /* Maximum size of super-block buffer */ -#define H5F_SUPERBLOCK_SIZE 256 +#define H5F_SUPERBLOCK_SIZE 128 #define H5F_DRVINFOBLOCK_SIZE 1024 /* Define the HDF5 file signature */ @@ -169,7 +169,6 @@ H5_DLL herr_t H5F_try_close(H5F_t *f); H5_DLL haddr_t H5F_locate_signature(H5FD_t *file, hid_t dxpl_id); /* File mount related routines */ -H5_DLL herr_t H5F_mountpoint(struct H5G_entry_t *find/*in,out*/); H5_DLL herr_t H5F_close_mounts(H5F_t *f); H5_DLL int H5F_term_unmount_cb(void *obj_ptr, hid_t obj_id, void *key); H5_DLL herr_t H5F_mount_count_ids(H5F_t *f, unsigned *nopen_files, unsigned *nopen_objs); @@ -177,7 +176,7 @@ H5_DLL herr_t H5F_mount_count_ids(H5F_t *f, unsigned *nopen_files, unsigned *nop /* Superblock related routines */ H5_DLL hsize_t H5F_init_superblock(const H5F_t *f, hid_t dxpl_id); H5_DLL herr_t H5F_write_superblock(H5F_t *f, hid_t dxpl_id, uint8_t *buf); -H5_DLL herr_t H5F_read_superblock(H5F_t *f, hid_t dxpl_id, H5G_entry_t *root_ent, haddr_t addr, uint8_t *buf, size_t buf_size); +H5_DLL herr_t H5F_read_superblock(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc, haddr_t addr, uint8_t *buf, size_t buf_size); /* Shared file list related routines */ H5_DLL herr_t H5F_sfile_add(H5F_file_t *shared); diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index 53d3f05..2359cb9 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -218,6 +218,7 @@ typedef struct H5F_t H5F_t; #define H5F_BASE_ADDR(F) ((F)->shared->base_addr) /* Sieve buffer size for datasets */ #define H5F_SIEVE_BUF_SIZE(F) ((F)->shared->sieve_buf_size) +#define H5F_GC_REF(F) ((F)->shared->gc_ref) #else /* H5F_PACKAGE */ #define H5F_FCPL(F) (H5F_get_fcpl(F)) #define H5F_SIZEOF_ADDR(F) (H5F_sizeof_addr(F)) @@ -231,6 +232,7 @@ typedef struct H5F_t H5F_t; #define H5F_GRP_BTREE_SHARED(F) (H5F_grp_btree_shared(F)) #define H5F_BASE_ADDR(F) (H5F_get_base_addr(F)) #define H5F_SIEVE_BUF_SIZE(F) (H5F_sieve_buf_size(F)) +#define H5F_GC_REF(F) (H5F_gc_ref(F)) #endif /* H5F_PACKAGE */ @@ -452,8 +454,8 @@ H5_DLL int H5F_mpi_get_size(const H5F_t *f); #endif /* H5_HAVE_PARALLEL */ /* Functions than check file mounting information */ -H5_DLL htri_t H5F_is_mount(const H5F_t *file); -H5_DLL htri_t H5F_has_mount(const H5F_t *file); +H5_DLL hbool_t H5F_is_mount(const H5F_t *file); +H5_DLL hbool_t H5F_has_mount(const H5F_t *file); /* Functions than retrieve values set from the FCPL */ H5_DLL hid_t H5F_get_fcpl(const H5F_t *f); @@ -467,6 +469,7 @@ H5_DLL size_t H5F_rdcc_nelmts(const H5F_t *f); H5_DLL double H5F_rdcc_w0(const H5F_t *f); H5_DLL struct H5RC_t *H5F_grp_btree_shared(const H5F_t *f); H5_DLL size_t H5F_sieve_buf_size(const H5F_t *f); +H5_DLL unsigned H5F_gc_ref(const H5F_t *f); /* Functions that operate on blocks of bytes wrt super block */ H5_DLL herr_t H5F_block_read(const H5F_t *f, H5FD_mem_t type, haddr_t addr, diff --git a/src/H5Fsuper.c b/src/H5Fsuper.c index 1676fe3..d7d0e6e 100644 --- a/src/H5Fsuper.c +++ b/src/H5Fsuper.c @@ -66,17 +66,10 @@ H5F_init_super_interface(void) * wendling@ncsa.uiuc.edu * Sept 12, 2003 * - * Modifications: - * Raymond Lu - * May 24, 2005 - * Started to check if driver(only family and multi drivers) - * matches driver information saved in the superblock. Wrong - * driver will result in a failure. - * *------------------------------------------------------------------------- */ herr_t -H5F_read_superblock(H5F_t *f, hid_t dxpl_id, H5G_entry_t *root_ent, haddr_t addr, uint8_t *buf, size_t buf_size) +H5F_read_superblock(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc, haddr_t addr, uint8_t *buf, size_t buf_size) { haddr_t stored_eoa; /*relative end-of-addr in file */ haddr_t eof; /*end of file address */ @@ -248,7 +241,7 @@ H5F_read_superblock(H5F_t *f, hid_t dxpl_id, H5G_entry_t *root_ent, haddr_t addr H5F_addr_decode(f, (const uint8_t **)&p, &shared->freespace_addr/*out*/); H5F_addr_decode(f, (const uint8_t **)&p, &stored_eoa/*out*/); H5F_addr_decode(f, (const uint8_t **)&p, &shared->driver_addr/*out*/); - if (H5G_ent_decode(f, (const uint8_t **)&p, root_ent/*out*/) < 0) + if(H5G_obj_ent_decode(f, (const uint8_t **)&p, root_loc->oloc/*out*/) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read root symbol entry") /* @@ -490,8 +483,6 @@ done: * wendling@ncsa.uiuc.edu * Sept 12, 2003 * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t @@ -561,7 +552,7 @@ H5F_write_superblock(H5F_t *f, hid_t dxpl_id, uint8_t *buf) H5F_addr_encode(f, &p, f->shared->freespace_addr); H5F_addr_encode(f, &p, H5FD_get_eoa(f->shared->lf)); H5F_addr_encode(f, &p, f->shared->driver_addr); - if(H5G_ent_encode(f, &p, H5G_entof(f->shared->root_grp))<0) + if(H5G_obj_ent_encode(f, &p, H5G_oloc(f->shared->root_grp))<0) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to encode root group information") H5_ASSIGN_OVERFLOW(superblock_size, p - sbuf, int, size_t); @@ -71,30 +71,17 @@ * +--------------+------------+--------------------------------+ * * - * Modifications: - * - * Robb Matzke, 5 Aug 1997 - * Added calls to H5E. - * - * Robb Matzke, 30 Aug 1997 - * Added `Errors:' field to function prologues. - * - * Pedro Vicente, 22 Aug 2002 - * Added `id to name' support. - * *------------------------------------------------------------------------- */ -#define H5G_PACKAGE /*suppress error about including H5Gpkg */ #define H5F_PACKAGE /*suppress error about including H5Fpkg */ +#define H5G_PACKAGE /*suppress error about including H5Gpkg */ /* Interface initialization */ #define H5_INTERFACE_INIT_FUNC H5G_init_interface /* Packages needed by this file... */ #include "H5private.h" /* Generic Functions */ -#include "H5Aprivate.h" /* Attributes */ -#include "H5Dprivate.h" /* Datasets */ #include "H5Eprivate.h" /* Error handling */ #include "H5Fpkg.h" /* File access */ #include "H5FLprivate.h" /* Free Lists */ @@ -108,102 +95,93 @@ #define H5G_INIT_HEAP 8192 #define H5G_RESERVED_ATOMS 0 -/* - * During name lookups (see H5G_namei()) we sometimes want information about - * a symbolic link or a mount point. The normal operation is to follow the - * symbolic link or mount point and return information about its target. - */ -#define H5G_TARGET_NORMAL 0x0000 -#define H5G_TARGET_SLINK 0x0001 -#define H5G_TARGET_MOUNT 0x0002 -#define H5G_CRT_INTMD_GROUP 0x0004 - /* Local typedefs */ -/* Struct only used by change name callback function */ -typedef struct H5G_names_t { - H5G_entry_t *loc; - H5RS_str_t *src_name; - H5G_entry_t *src_loc; - H5RS_str_t *dst_name; - H5G_entry_t *dst_loc; - H5G_names_op_t op; -} H5G_names_t; - -/* Enum for H5G_namei actions */ -typedef enum { - H5G_NAMEI_TRAVERSE, /* Just traverse groups */ - H5G_NAMEI_INSERT /* Insert entry in group */ -} H5G_namei_act_t ; - -/* - * This table contains a list of object types, descriptions, and the - * functions that determine if some object is a particular type. The table - * is allocated dynamically. - */ -typedef struct H5G_typeinfo_t { - H5G_obj_t type; /*one of the public H5G_* types */ - htri_t (*isa)(H5G_entry_t*, hid_t); /*function to determine type */ - char *desc; /*description of object type */ -} H5G_typeinfo_t; +/* User data for path traversal routine for "insertion file" routine */ +typedef struct { + H5F_t *file; /* Pointer to the file for insertion */ +} H5G_trav_ud1_t; + +/* User data for path traversal routine for moving a link */ +typedef struct { + H5G_obj_t type; /* Type of object being moved */ + const char *src_name; /* Source name for moving object */ + H5G_loc_t *src_loc; /* Source location for moving object */ + const char *dst_name; /* Destination name for moving object */ + H5G_loc_t *dst_loc; /* Destination location for moving object */ +} H5G_trav_ud2_t; + +/* User data for path traversal callback to creating link */ +typedef struct { + H5F_t *file; /* Pointer to the file */ + hid_t dxpl_id; /* Dataset transfer property list */ + H5O_link_t *lnk; /* Pointer to link information to insert */ +} H5G_trav_ud3_t; + +/* User data for path traversal routine for getting object info */ +typedef struct { + H5G_stat_t *statbuf; /* Stat buffer about object */ + hbool_t follow_link; /* Whether we are following a link or not */ + hid_t dxpl_id; /* Dataset transfer property list */ +} H5G_trav_ud4_t; + +/* User data for path traversal routine for getting soft link value */ +typedef struct { + size_t size; /* Size of user buffer */ + char *buf; /* User buffer */ +} H5G_trav_ud5_t; + +/* User data for path traversal routine for removing link (i.e. unlink) */ +typedef struct { + hid_t dxpl_id; /* Dataset transfer property list */ +} H5G_trav_ud6_t; + +/* User data for path traversal routine for inserting object */ +typedef struct { + H5G_loc_t *obj_loc; /* Object location */ + hid_t dxpl_id; /* Dataset transfer property list */ +} H5G_trav_ud7_t; /* Package variables */ /* Local variables */ -static H5G_typeinfo_t *H5G_type_g = NULL; /*object typing info */ -static size_t H5G_ntypes_g = 0; /*entries in type table */ -static size_t H5G_atypes_g = 0; /*entries allocated */ -static char *H5G_comp_g = NULL; /*component buffer */ -static size_t H5G_comp_alloc_g = 0; /*sizeof component buffer */ /* Declare a free list to manage the H5G_t struct */ H5FL_DEFINE(H5G_t); H5FL_DEFINE(H5G_shared_t); -/* Declare extern the PQ free list for the wrapped strings */ -H5FL_BLK_EXTERN(str_buf); - -/* Declare a free list to manage haddr_t's */ -H5FL_DEFINE(haddr_t); - /* Private prototypes */ -static herr_t H5G_register_type(H5G_obj_t type, htri_t(*isa)(H5G_entry_t*, hid_t), - const char *desc); -static const char * H5G_component(const char *name, size_t *size_p); -static const char * H5G_basename(const char *name, size_t *size_p); static char * H5G_normalize(const char *name); -static herr_t H5G_namei(const H5G_entry_t *loc_ent, const char *name, - const char **rest/*out*/, H5G_entry_t *grp_ent/*out*/, H5G_entry_t *obj_ent/*out*/, - unsigned target, int *nlinks/*out*/, H5G_namei_act_t action, - H5G_entry_t *ent, hid_t dxpl_id); -static herr_t H5G_traverse_slink(H5G_entry_t *grp_ent/*in,out*/, - H5G_entry_t *obj_ent/*in,out*/, int *nlinks/*in,out*/, hid_t dxpl_id); -static H5G_t *H5G_create(H5G_entry_t *loc, const char *name, hid_t dxpl_id, +static H5G_t *H5G_create(H5G_loc_t *loc, const char *name, hid_t dxpl_id, hid_t gcpl_id, hid_t gapl_id); -static htri_t H5G_isa(H5G_entry_t *ent, hid_t dxpl_id); -static htri_t H5G_link_isa(H5G_entry_t *ent, hid_t dxpl_id); -static H5G_t * H5G_open_oid(H5G_entry_t *ent, hid_t dxpl_id); -static H5G_t *H5G_rootof(H5F_t *f); -static herr_t H5G_link(H5G_entry_t *cur_loc, const char *cur_name, - H5G_entry_t *new_loc, const char *new_name, H5G_link_t type, - unsigned namei_flags, hid_t dxpl_id); -static herr_t H5G_get_num_objs(H5G_entry_t *grp, hsize_t *num_objs, hid_t dxpl_id); -static ssize_t H5G_get_objname_by_idx(H5G_entry_t *loc, hsize_t idx, char* name, size_t size, hid_t dxpl_id); -static H5G_obj_t H5G_get_objtype_by_idx(H5G_entry_t *loc, hsize_t idx, hid_t dxpl_id); -static herr_t H5G_linkval(H5G_entry_t *loc, const char *name, size_t size, +static herr_t H5G_open_oid(H5G_t *grp, hid_t dxpl_id); +static herr_t H5G_insert_cb(H5G_loc_t *grp_loc/*in*/, const char *name, + const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/); +static herr_t H5G_link_cb(H5G_loc_t *grp_loc/*in*/, const char *name, + const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/); +static herr_t H5G_get_objinfo_cb(H5G_loc_t *grp_loc/*in*/, const char *name, + const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/); +static herr_t H5G_link(H5G_loc_t *cur_loc, const char *cur_name, + H5G_loc_t *new_loc, const char *new_name, H5G_link_t type, + unsigned traverse_flags, hid_t dxpl_id); +static herr_t H5G_linkval_cb(H5G_loc_t *grp_loc/*in*/, const char *name, + const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/); +static herr_t H5G_linkval(H5G_loc_t *loc, const char *name, size_t size, char *buf/*out*/, hid_t dxpl_id); -static herr_t H5G_set_comment(H5G_entry_t *loc, const char *name, +static herr_t H5G_set_comment(H5G_loc_t *loc, const char *name, const char *buf, hid_t dxpl_id); -static int H5G_get_comment(H5G_entry_t *loc, const char *name, +static int H5G_get_comment(H5G_loc_t *loc, const char *name, size_t bufsize, char *buf, hid_t dxpl_id); -static herr_t H5G_unlink(H5G_entry_t *loc, const char *name, hid_t dxpl_id); -static herr_t H5G_move(H5G_entry_t *src_loc, const char *src_name, - H5G_entry_t *dst_loc, const char *dst_name, hid_t dxpl_id); -static htri_t H5G_common_path(const H5RS_str_t *fullpath_r, - const H5RS_str_t *prefix_r); -static H5RS_str_t *H5G_build_fullpath(const H5RS_str_t *prefix_r, const H5RS_str_t *name_r); -static int H5G_replace_ent(void *obj_ptr, hid_t obj_id, void *key); -static herr_t H5G_copy(H5G_entry_t *ent_src, H5G_entry_t *loc_dst, +static herr_t H5G_unlink_cb(H5G_loc_t *grp_loc/*in*/, const char *name, + const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/); +static herr_t H5G_unlink(H5G_loc_t *loc, const char *name, hid_t dxpl_id); +static herr_t H5G_move_cb(H5G_loc_t *grp_loc/*in*/, const char *name, + const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/); +static herr_t H5G_move(H5G_loc_t *src_loc, const char *src_name, + H5G_loc_t *dst_loc, const char *dst_name, hid_t dxpl_id); +static herr_t H5G_insertion_file_cb(H5G_loc_t *grp_loc/*in*/, const char *name, + const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/); +static herr_t H5G_copy(H5G_loc_t *src_loc, H5G_loc_t *dst_loc, const char *name_dst, hid_t plist_id); @@ -239,19 +217,19 @@ static herr_t H5G_copy(H5G_entry_t *ent_src, H5G_entry_t *loc_dst, hid_t H5Gcreate(hid_t loc_id, const char *name, size_t size_hint) { - H5G_entry_t *loc = NULL; - H5G_t *grp = NULL; - hid_t tmp_gcpl = (-1); /* Temporary group creation property list */ - hid_t ret_value; + H5G_loc_t loc; + H5G_t *grp = NULL; + hid_t tmp_gcpl = (-1); /* Temporary group creation property list */ + hid_t ret_value; - FUNC_ENTER_API(H5Gcreate, FAIL); + FUNC_ENTER_API(H5Gcreate, FAIL) H5TRACE3("i","isz",loc_id,name,size_hint); /* Check arguments */ - if (NULL==(loc=H5G_loc (loc_id))) - HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a location"); - if (!name || !*name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name given"); + if(H5G_loc(loc_id, &loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + if(!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name given") /* Check if we need to create a non-standard GCPL */ if(size_hint > 0) { @@ -277,16 +255,16 @@ H5Gcreate(hid_t loc_id, const char *name, size_t size_hint) /* Set the non-default local heap size hint */ ginfo.lheap_size_hint = size_hint; if(H5P_set(gc_plist, H5G_CRT_GROUP_INFO_NAME, &ginfo) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set group info") + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set group info") } /* end if */ else tmp_gcpl = H5P_GROUP_CREATE_DEFAULT; /* Create the group */ - if (NULL == (grp = H5G_create(loc, name, H5AC_dxpl_id, tmp_gcpl, H5P_DEFAULT))) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create group"); - if ((ret_value = H5I_register(H5I_GROUP, grp)) < 0) - HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group"); + if(NULL == (grp = H5G_create(&loc, name, H5AC_dxpl_id, tmp_gcpl, H5P_DEFAULT))) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create group") + if((ret_value = H5I_register(H5I_GROUP, grp)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group") done: if(tmp_gcpl > 0 && tmp_gcpl != H5P_GROUP_CREATE_DEFAULT) @@ -298,8 +276,8 @@ done: H5G_close(grp); } /* end if */ - FUNC_LEAVE_API(ret_value); -} + FUNC_LEAVE_API(ret_value) +} /* end H5Gcreate() */ /*------------------------------------------------------------------------- @@ -334,16 +312,16 @@ done: hid_t H5Gcreate_expand(hid_t loc_id, const char *name, hid_t gcpl_id, hid_t gapl_id) { - H5G_entry_t *loc = NULL; - H5G_t *grp = NULL; - hid_t ret_value; + H5G_loc_t loc; + H5G_t *grp = NULL; + hid_t ret_value; FUNC_ENTER_API(H5Gcreate_expand, FAIL) /* Check arguments */ - if (NULL==(loc=H5G_loc (loc_id))) - HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") - if (!name || !*name) + if(H5G_loc(loc_id, &loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + if(!name || !*name) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name given") /* Check group creation property list */ @@ -362,13 +340,13 @@ H5Gcreate_expand(hid_t loc_id, const char *name, hid_t gcpl_id, hid_t gapl_id) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not group access property list") #endif /* LATER */ - if (NULL == (grp = H5G_create(loc, name, H5AC_dxpl_id, gcpl_id, gapl_id))) + if(NULL == (grp = H5G_create(&loc, name, H5AC_dxpl_id, gcpl_id, gapl_id))) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create group") - if ((ret_value = H5I_register(H5I_GROUP, grp)) < 0) + if((ret_value = H5I_register(H5I_GROUP, grp)) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group") done: - if(ret_value<0) { + if(ret_value < 0) { if(grp!=NULL) H5G_close(grp); } /* end if */ @@ -399,40 +377,57 @@ done: hid_t H5Gopen(hid_t loc_id, const char *name) { - hid_t ret_value = FAIL; H5G_t *grp = NULL; - H5G_entry_t *loc = NULL; - H5G_entry_t ent; + H5G_loc_t loc; + H5G_loc_t grp_loc; /* Location used to open group */ + H5G_name_t grp_path; /* Opened object group hier. path */ + H5O_loc_t grp_oloc; /* Opened object object location */ + hbool_t ent_found = FALSE; /* Entry at 'name' found */ + hid_t ret_value = FAIL; - FUNC_ENTER_API(H5Gopen, FAIL); + FUNC_ENTER_API(H5Gopen, FAIL) H5TRACE2("i","is",loc_id,name); /* Check args */ - if (NULL==(loc=H5G_loc(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location"); - if (!name || !*name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name"); + if(H5G_loc(loc_id, &loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + if(!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") + + /* Set up opened group location to fill in */ + grp_loc.oloc = &grp_oloc; + grp_loc.path = &grp_path; + H5G_loc_reset(&grp_loc); - /* Open the parent group, making sure it's a group */ - if (H5G_find(loc, name, &ent/*out*/, H5AC_dxpl_id) < 0) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "group not found"); + /* Find the group object */ + if(H5G_loc_find(&loc, name, &grp_loc/*out*/, H5AC_dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "group not found") + ent_found = TRUE; + + /* Check that the object found is the correct type */ + if(H5O_obj_type(&grp_oloc, H5AC_dxpl_id) != H5G_GROUP) + HGOTO_ERROR(H5E_SYM, H5E_BADTYPE, FAIL, "not a group") /* Open the group */ - if ((grp = H5G_open(&ent, H5AC_dxpl_id))==NULL) - HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group"); + if((grp = H5G_open(&grp_loc, H5AC_dxpl_id)) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group") /* Register an atom for the group */ - if ((ret_value = H5I_register(H5I_GROUP, grp)) < 0) - HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group"); + if((ret_value = H5I_register(H5I_GROUP, grp)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group") done: - if(ret_value<0) { - if(grp!=NULL) + if(ret_value < 0) { + if(grp != NULL) H5G_close(grp); + else { + if(ent_found) + H5G_name_free(&grp_path); + } /* end else */ } /* end if */ - FUNC_LEAVE_API(ret_value); -} + FUNC_LEAVE_API(ret_value) +} /* H5Gopen() */ /*------------------------------------------------------------------------- @@ -497,76 +492,47 @@ done: * Programmer: Robb Matzke * Monday, March 23, 1998 * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t H5Giterate(hid_t loc_id, const char *name, int *idx_p, H5G_iterate_t op, void *op_data) { - H5O_stab_t stab; /*info about B-tree */ - int idx; - H5G_bt_it_ud1_t udata; - H5G_t *grp = NULL; - herr_t ret_value; + int last_obj; /* Index of last object looked at */ + int idx; /* Internal location to hold index */ + herr_t ret_value; - FUNC_ENTER_API(H5Giterate, FAIL); + FUNC_ENTER_API(H5Giterate, FAIL) H5TRACE5("e","is*Isxx",loc_id,name,idx_p,op,op_data); /* Check args */ - if (!name || !*name) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified"); + if(!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified") idx = (idx_p == NULL ? 0 : *idx_p); - if (!idx_p) - idx_p = &idx; - if (idx<0) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified"); - if (!op) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "no operator specified"); - - /* - * Open the group on which to operate. We also create a group ID which - * we can pass to the application-defined operator. - */ - if ((udata.group_id = H5Gopen (loc_id, name)) <0) - HGOTO_ERROR (H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group"); - if ((grp=H5I_object(udata.group_id))==NULL) { - H5Gclose(udata.group_id); - HGOTO_ERROR (H5E_ATOM, H5E_BADATOM, FAIL, "bad group atom"); - } - - /* Get the B-tree info */ - if (NULL==H5O_read (&(grp->ent), H5O_STAB_ID, 0, &stab, H5AC_dxpl_id)) - HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "unable to determine local heap address") + if(idx < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified") + if(!op) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no operator specified") - /* Build udata to pass through H5B_iterate() to H5G_node_iterate() */ - udata.skip = idx; - udata.heap_addr = stab.heap_addr; - udata.op = op; - udata.op_data = op_data; + /* Set number of objects looked at to zero */ + last_obj = 0; - /* Set the number of entries looked at to zero */ - udata.final_ent = 0; - - /* Iterate over the group members */ - if ((ret_value = H5B_iterate (H5G_fileof(grp), H5AC_dxpl_id, H5B_SNODE, - H5G_node_iterate, stab.btree_addr, &udata))<0) - HERROR (H5E_SYM, H5E_CANTNEXT, "iteration operator failed"); - - H5I_dec_ref (udata.group_id); /*also closes 'grp'*/ + /* Call private function. */ + if((ret_value = H5G_obj_iterate(loc_id, name, idx, &last_obj, op, op_data, H5AC_ind_dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "group iteration failed") /* Check for too high of a starting index (ex post facto :-) */ /* (Skipping exactly as many entries as are in the group is currently an error) */ - if(idx>0 && idx>=udata.final_ent) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified"); + if(idx > 0 && idx >= last_obj) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified") /* Set the index we stopped at */ - *idx_p=udata.final_ent; + if(idx_p) + *idx_p=last_obj; done: - FUNC_LEAVE_API(ret_value); -} + FUNC_LEAVE_API(ret_value) +} /* end H5Giterate() */ /*------------------------------------------------------------------------- @@ -582,33 +548,32 @@ done: * Programmer: Raymond Lu * Nov 20, 2002 * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t H5Gget_num_objs(hid_t loc_id, hsize_t *num_objs) { - H5G_entry_t *loc = NULL; /* Pointer to symbol table entry */ + H5G_loc_t loc; /* Location of object */ herr_t ret_value; - FUNC_ENTER_API(H5Gget_num_objs, FAIL); + FUNC_ENTER_API(H5Gget_num_objs, FAIL) H5TRACE2("e","i*h",loc_id,num_objs); /* Check args */ - if (NULL==(loc=H5G_loc (loc_id))) - HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a location ID"); - if(H5G_get_type(loc,H5AC_ind_dxpl_id)!=H5G_GROUP) - HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a group"); - if (!num_objs) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "nil pointer"); + if(H5G_loc(loc_id, &loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location ID") + if(H5O_obj_type(loc.oloc, H5AC_ind_dxpl_id) != H5G_GROUP) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group") + if(!num_objs) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "nil pointer") /* Call private function. */ - ret_value = H5G_get_num_objs(loc, num_objs, H5AC_ind_dxpl_id); + if((ret_value = H5G_obj_count(loc.oloc, num_objs, H5AC_ind_dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOUNT, FAIL, "can't determine ") done: - FUNC_LEAVE_API(ret_value); -} + FUNC_LEAVE_API(ret_value) +} /* end H5Gget_num_objs() */ /*------------------------------------------------------------------------- @@ -638,24 +603,25 @@ done: ssize_t H5Gget_objname_by_idx(hid_t loc_id, hsize_t idx, char *name, size_t size) { - H5G_entry_t *loc = NULL; /* Pointer to symbol table entry */ - ssize_t ret_value = FAIL; + H5G_loc_t loc; /* Object location */ + ssize_t ret_value; - FUNC_ENTER_API(H5Gget_objname_by_idx, FAIL); + FUNC_ENTER_API(H5Gget_objname_by_idx, FAIL) H5TRACE4("Zs","ihsz",loc_id,idx,name,size); /* Check args */ - if (NULL==(loc=H5G_loc (loc_id))) - HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a location ID"); - if(H5G_get_type(loc,H5AC_ind_dxpl_id)!=H5G_GROUP) - HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a group"); + if(H5G_loc(loc_id, &loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location ID") + if(H5O_obj_type(loc.oloc, H5AC_ind_dxpl_id) != H5G_GROUP) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group") - /*call private function*/ - ret_value = H5G_get_objname_by_idx(loc, idx, name, size, H5AC_ind_dxpl_id); + /* Call internal function*/ + if((ret_value = H5G_obj_get_name_by_idx(loc.oloc, idx, name, size, H5AC_ind_dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_BADTYPE, FAIL, "can't get object name") done: - FUNC_LEAVE_API(ret_value); -} + FUNC_LEAVE_API(ret_value) +} /* end H5Gget_objname_by_idx() */ /*------------------------------------------------------------------------- @@ -678,25 +644,25 @@ done: H5G_obj_t H5Gget_objtype_by_idx(hid_t loc_id, hsize_t idx) { - H5G_entry_t *loc = NULL; /* Pointer to symbol table entry */ + H5G_loc_t loc; /* Object location */ H5G_obj_t ret_value; - FUNC_ENTER_API(H5Gget_objtype_by_idx, H5G_UNKNOWN); + FUNC_ENTER_API(H5Gget_objtype_by_idx, H5G_UNKNOWN) H5TRACE2("Go","ih",loc_id,idx); /* Check args */ - if (NULL==(loc=H5G_loc (loc_id))) - HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "not a location ID"); - if(H5G_get_type(loc,H5AC_ind_dxpl_id)!=H5G_GROUP) - HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "not a group"); + if(H5G_loc(loc_id, &loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "not a location ID") + if(H5O_obj_type(loc.oloc, H5AC_ind_dxpl_id) != H5G_GROUP) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "not a group") - /*call private function*/ - ret_value = H5G_get_objtype_by_idx(loc, idx, H5AC_ind_dxpl_id); + /* Call internal function*/ + if((ret_value = H5G_obj_get_type_by_idx(loc.oloc, idx, H5AC_ind_dxpl_id)) == H5G_UNKNOWN) + HGOTO_ERROR(H5E_SYM, H5E_BADTYPE, FAIL, "can't get object type") done: - FUNC_LEAVE_API(ret_value); - -} + FUNC_LEAVE_API(ret_value) +} /* end H5Gget_objtype_by_idx() */ /*------------------------------------------------------------------------- @@ -724,39 +690,40 @@ herr_t H5Gmove2(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id, const char *dst_name) { - H5G_entry_t *src_loc=NULL; - H5G_entry_t *dst_loc=NULL; + H5G_loc_t src_loc, *src_loc_p; + H5G_loc_t dst_loc, *dst_loc_p; herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_API(H5Gmove2, FAIL); + FUNC_ENTER_API(H5Gmove2, FAIL) H5TRACE4("e","isis",src_loc_id,src_name,dst_loc_id,dst_name); - if (src_loc_id != H5G_SAME_LOC && NULL==(src_loc=H5G_loc(src_loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location"); - if (dst_loc_id != H5G_SAME_LOC && NULL==(dst_loc=H5G_loc(dst_loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location"); - if (!src_name || !*src_name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no current name specified"); - if (!dst_name || !*dst_name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no new name specified"); - - if(src_loc_id == H5G_SAME_LOC && dst_loc_id == H5G_SAME_LOC) { - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "source and destination should not be both H5G_SAME_LOC"); - } else if(src_loc_id == H5G_SAME_LOC) { - src_loc = dst_loc; - } - else if(dst_loc_id == H5G_SAME_LOC) { - dst_loc = src_loc; - } - else if(src_loc->file != dst_loc->file) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "source and destination should be in the same file."); - - if (H5G_move(src_loc, src_name, dst_loc, dst_name, H5AC_dxpl_id)<0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to change object name"); + if(src_loc_id != H5G_SAME_LOC && H5G_loc(src_loc_id, &src_loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + if(dst_loc_id != H5G_SAME_LOC && H5G_loc(dst_loc_id, &dst_loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + if(!src_name || !*src_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no current name specified") + if(!dst_name || !*dst_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no new name specified") + + /* Set up src & dst location pointers */ + src_loc_p = &src_loc; + dst_loc_p = &dst_loc; + if(src_loc_id == H5G_SAME_LOC && dst_loc_id == H5G_SAME_LOC) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "source and destination should not be both H5G_SAME_LOC") + else if(src_loc_id == H5G_SAME_LOC) + src_loc_p = dst_loc_p; + else if(dst_loc_id == H5G_SAME_LOC) + dst_loc_p = src_loc_p; + else if(src_loc_p->oloc->file != dst_loc_p->oloc->file) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "source and destination should be in the same file.") + + if(H5G_move(src_loc_p, src_name, dst_loc_p, dst_name, H5AC_dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to change object name") done: - FUNC_LEAVE_API(ret_value); -} + FUNC_LEAVE_API(ret_value) +} /* end H5Gmove2() */ /*------------------------------------------------------------------------- @@ -790,43 +757,43 @@ herr_t H5Glink2(hid_t cur_loc_id, const char *cur_name, H5G_link_t type, hid_t new_loc_id, const char *new_name) { - H5G_entry_t *cur_loc = NULL; - H5G_entry_t *new_loc = NULL; + H5G_loc_t cur_loc, *cur_loc_p; + H5G_loc_t new_loc, *new_loc_p; herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_API(H5Glink2, FAIL); + FUNC_ENTER_API(H5Glink2, FAIL) H5TRACE5("e","isGlis",cur_loc_id,cur_name,type,new_loc_id,new_name); /* Check arguments */ - if (cur_loc_id != H5G_SAME_LOC && NULL==(cur_loc=H5G_loc(cur_loc_id))) - HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a location"); - if (new_loc_id != H5G_SAME_LOC && NULL==(new_loc=H5G_loc(new_loc_id))) - HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a location"); - if (type!=H5G_LINK_HARD && type!=H5G_LINK_SOFT) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "unrecognized link type"); - if (!cur_name || !*cur_name) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "no current name specified"); - if (!new_name || !*new_name) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "no new name specified"); - - if(cur_loc_id == H5G_SAME_LOC && new_loc_id == H5G_SAME_LOC) { - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "source and destination should not be both H5G_SAME_LOC"); - } - else if(cur_loc_id == H5G_SAME_LOC) { - cur_loc = new_loc; - } - else if(new_loc_id == H5G_SAME_LOC) { - new_loc = cur_loc; - } - else if(cur_loc->file != new_loc->file) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "source and destination should be in the same file."); - - if (H5G_link(cur_loc, cur_name, new_loc, new_name, type, H5G_TARGET_NORMAL, H5AC_dxpl_id) <0) - HGOTO_ERROR (H5E_SYM, H5E_LINK, FAIL, "unable to create link"); + if(cur_loc_id != H5G_SAME_LOC && H5G_loc(cur_loc_id, &cur_loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + if(new_loc_id != H5G_SAME_LOC && H5G_loc(new_loc_id, &new_loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + if(type != H5G_LINK_HARD && type != H5G_LINK_SOFT) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unrecognized link type") + if(!cur_name || !*cur_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no current name specified") + if(!new_name || !*new_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no new name specified") + + /* Set up current & new location pointers */ + cur_loc_p = &cur_loc; + new_loc_p = &new_loc; + if(cur_loc_id == H5G_SAME_LOC && new_loc_id == H5G_SAME_LOC) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "source and destination should not be both H5G_SAME_LOC") + else if(cur_loc_id == H5G_SAME_LOC) + cur_loc_p = new_loc_p; + else if(new_loc_id == H5G_SAME_LOC) + new_loc_p = cur_loc_p; + else if(cur_loc_p->oloc->file != new_loc_p->oloc->file) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "source and destination should be in the same file.") + + if(H5G_link(cur_loc_p, cur_name, new_loc_p, new_name, type, H5G_TARGET_NORMAL, H5AC_dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_LINK, FAIL, "unable to create link") done: - FUNC_LEAVE_API(ret_value); -} + FUNC_LEAVE_API(ret_value) +} /* end H5Glink2() */ /*------------------------------------------------------------------------- @@ -851,25 +818,25 @@ done: herr_t H5Gunlink(hid_t loc_id, const char *name) { - H5G_entry_t *loc = NULL; + H5G_loc_t loc; herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_API(H5Gunlink, FAIL); + FUNC_ENTER_API(H5Gunlink, FAIL) H5TRACE2("e","is",loc_id,name); /* Check arguments */ - if (NULL==(loc=H5G_loc(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location"); - if (!name || !*name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name"); + if(H5G_loc(loc_id, &loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + if(!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") /* Unlink */ - if (H5G_unlink(loc, name, H5AC_dxpl_id)<0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to unlink object"); + if(H5G_unlink(&loc, name, H5AC_dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to unlink object") done: - FUNC_LEAVE_API(ret_value); -} + FUNC_LEAVE_API(ret_value) +} /* end H5Gunlink() */ /*------------------------------------------------------------------------- @@ -893,25 +860,25 @@ herr_t H5Gget_objinfo(hid_t loc_id, const char *name, hbool_t follow_link, H5G_stat_t *statbuf/*out*/) { - H5G_entry_t *loc = NULL; - herr_t ret_value=SUCCEED; /* Return value */ + H5G_loc_t loc; + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API(H5Gget_objinfo, FAIL); + FUNC_ENTER_API(H5Gget_objinfo, FAIL) H5TRACE4("e","isbx",loc_id,name,follow_link,statbuf); /* Check arguments */ - if (NULL==(loc=H5G_loc (loc_id))) - HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a location"); - if (!name || !*name) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified"); + if(H5G_loc(loc_id, &loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + if(!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified") /* Get info */ - if (H5G_get_objinfo (loc, name, follow_link, statbuf, H5AC_ind_dxpl_id)<0) - HGOTO_ERROR (H5E_ARGS, H5E_CANTINIT, FAIL, "cannot stat object"); + if(H5G_get_objinfo(&loc, name, follow_link, statbuf, H5AC_ind_dxpl_id) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "cannot stat object") done: - FUNC_LEAVE_API(ret_value); -} + FUNC_LEAVE_API(ret_value) +} /* end H5Gget_objinfo() */ /*------------------------------------------------------------------------- @@ -935,25 +902,25 @@ done: herr_t H5Gget_linkval(hid_t loc_id, const char *name, size_t size, char *buf/*out*/) { - H5G_entry_t *loc = NULL; - herr_t ret_value=SUCCEED; /* Return value */ + H5G_loc_t loc; + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API(H5Gget_linkval, FAIL); + FUNC_ENTER_API(H5Gget_linkval, FAIL) H5TRACE4("e","iszx",loc_id,name,size,buf); /* Check arguments */ - if (NULL==(loc=H5G_loc (loc_id))) - HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a location"); - if (!name || !*name) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified"); + if(H5G_loc(loc_id, &loc)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + if(!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified") /* Get the link value */ - if (H5G_linkval (loc, name, size, buf, H5AC_ind_dxpl_id)<0) - HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "unable to get link value"); + if(H5G_linkval(&loc, name, size, buf, H5AC_ind_dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to get link value") done: - FUNC_LEAVE_API(ret_value); -} + FUNC_LEAVE_API(ret_value) +} /* end H5Gget_linkval() */ /*------------------------------------------------------------------------- @@ -969,30 +936,28 @@ done: * Programmer: Robb Matzke * Monday, July 20, 1998 * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t H5Gset_comment(hid_t loc_id, const char *name, const char *comment) { - H5G_entry_t *loc = NULL; - herr_t ret_value=SUCCEED; /* Return value */ + H5G_loc_t loc; + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_API(H5Gset_comment, FAIL); + FUNC_ENTER_API(H5Gset_comment, FAIL) H5TRACE3("e","iss",loc_id,name,comment); - if (NULL==(loc=H5G_loc(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location"); - if (!name || !*name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified"); + if(H5G_loc(loc_id, &loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + if(!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified") - if (H5G_set_comment(loc, name, comment, H5AC_dxpl_id)<0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to set comment value"); + if(H5G_set_comment(&loc, name, comment, H5AC_dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to set comment value") done: - FUNC_LEAVE_API(ret_value); -} + FUNC_LEAVE_API(ret_value) +} /* end H5Gset_comment() */ /*------------------------------------------------------------------------- @@ -1014,32 +979,99 @@ done: * Programmer: Robb Matzke * Monday, July 20, 1998 * - * Modifications: - * *------------------------------------------------------------------------- */ int H5Gget_comment(hid_t loc_id, const char *name, size_t bufsize, char *buf) { - H5G_entry_t *loc = NULL; + H5G_loc_t loc; int ret_value; - FUNC_ENTER_API(H5Gget_comment, FAIL); + FUNC_ENTER_API(H5Gget_comment, FAIL) H5TRACE4("Is","iszs",loc_id,name,bufsize,buf); - if (NULL==(loc=H5G_loc(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location"); - if (!name || !*name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified"); - if (bufsize>0 && !buf) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no buffer specified"); + if(H5G_loc(loc_id, &loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + if(!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified") + if(bufsize > 0 && !buf) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no buffer specified") - if ((ret_value=H5G_get_comment(loc, name, bufsize, buf, H5AC_ind_dxpl_id))<0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to get comment value"); + if((ret_value = H5G_get_comment(&loc, name, bufsize, buf, H5AC_ind_dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to get comment value") done: - FUNC_LEAVE_API(ret_value); -} + FUNC_LEAVE_API(ret_value) +} /* end H5Gget_comment() */ + + +/*------------------------------------------------------------------------- + * Function: H5Gget_create_plist + * + * Purpose: Returns a copy of the group creation property list. + * + * Return: Success: ID for a copy of the group creation + * property list. The property list ID should be + * released by calling H5Pclose(). + * + * Failure: FAIL + * + * Programmer: Quincey Koziol + * Tuesday, October 25, 2005 + * + *------------------------------------------------------------------------- + */ +hid_t +H5Gget_create_plist(hid_t group_id) +{ + htri_t ginfo_exists = 0; + H5G_t *grp = NULL; + H5P_genplist_t *gcpl_plist; + H5P_genplist_t *new_plist; + hid_t new_gcpl_id = FAIL; + hid_t ret_value = FAIL; + + FUNC_ENTER_API(H5Gget_create_plist, FAIL) + H5TRACE1("i","i", group_id); + + /* Check args */ + if(NULL == (grp = H5I_object_verify(group_id, H5I_GROUP))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group") + + /* Copy the default group creation property list */ + if(NULL == (gcpl_plist = H5I_object(H5P_LST_GROUP_CREATE_g))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get default group creation property list") + if((new_gcpl_id = H5P_copy_plist(gcpl_plist)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to copy the creation property list") + if(NULL == (new_plist = H5I_object(new_gcpl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list") + + /* Check for the group having a group info message */ + if((ginfo_exists = H5O_exists(&(grp->oloc), H5O_GINFO_ID, 0, H5AC_dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to read object header") + if(ginfo_exists) { + H5O_ginfo_t ginfo; /* Group info message */ + + /* Read the group info */ + if(NULL == H5O_read(&(grp->oloc), H5O_GINFO_ID, 0, &ginfo, H5AC_dxpl_id)) + HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't get group info") + + /* Set the group info for the property list */ + if(H5P_set(new_plist, H5G_CRT_GROUP_INFO_NAME, &ginfo) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set group info") + } /* end if */ + + /* Set the return value */ + ret_value = new_gcpl_id; + +done: + if(ret_value < 0) { + if(new_gcpl_id > 0) + (void)H5I_dec_ref(new_gcpl_id); + } /* end if */ + + FUNC_LEAVE_API(ret_value) +} /* end H5Gget_create_plist() */ /*------------------------------------------------------------------------- @@ -1055,18 +1087,19 @@ done: *------------------------------------------------------------------------- */ herr_t -H5Gcopy(hid_t id_src, hid_t loc_dst, const char *name_dst, hid_t plist_id) +H5Gcopy(hid_t src_id, hid_t dst_id, const char *name_dst, hid_t plist_id) { - H5G_entry_t *ent_src = NULL, *ent_dst=NULL; - herr_t ret_value = SUCCEED; /* Return value */ + H5G_loc_t src_loc; /* Source object group location */ + H5G_loc_t dst_loc; /* Destination group location */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(H5Gcopy, FAIL) /* Check arguments */ - if(NULL == (ent_src = H5G_loc(id_src))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") - if(NULL == (ent_dst = H5G_loc(loc_dst))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + if(H5G_loc(src_id, &src_loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + if(H5G_loc(dst_id, &dst_loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") if(!name_dst || !*name_dst) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified") @@ -1078,7 +1111,7 @@ else if(TRUE != H5P_isa_class(plist_id, H5P_DATATYPE_CREATE)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not object create property list") - if(H5G_copy(ent_src, ent_dst, name_dst, plist_id) < 0) + if(H5G_copy(&src_loc, &dst_loc, name_dst, plist_id) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object") done: @@ -1103,21 +1136,20 @@ done: * Programmer: Robb Matzke * Monday, January 5, 1998 * - * Modifications: + * Notes: The group creation properties are registered in the property + * list interface initialization routine (H5P_init_interface) + * so that the file creation property class can inherit from it + * correctly. (Which allows the file creation property list to + * control the group creation properties of the root group of + * a file) QAK - 24/10/2005 * *------------------------------------------------------------------------- */ static herr_t H5G_init_interface(void) { - /* Group creation property class variables. In sequence, they are, - * - Creation property list class to modify - * - Default value for "group info" - */ H5P_genclass_t *crt_pclass; - H5O_ginfo_t ginfo = H5G_CRT_GROUP_INFO_DEF; - size_t nprops; /* Number of properties */ - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5G_init_interface); @@ -1126,16 +1158,6 @@ H5G_init_interface(void) (H5I_free_t)H5G_close) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to initialize interface"); - /* - * Initialize the type info table. Begin with the most general types and - * end with the most specific. For instance, any object that has a data - * type message is a datatype but only some of them are datasets. - */ - H5G_register_type(H5G_TYPE, H5T_isa, "datatype"); - H5G_register_type(H5G_GROUP, H5G_isa, "group"); - H5G_register_type(H5G_DATASET, H5D_isa, "dataset"); - H5G_register_type(H5G_LINK, H5G_link_isa, "link"); - /* ========== group Creation Property Class Initialization ============*/ assert(H5P_CLS_GROUP_CREATE_g!=-1); @@ -1143,18 +1165,6 @@ H5G_init_interface(void) if(NULL == (crt_pclass = H5I_object(H5P_CLS_GROUP_CREATE_g))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list class") - /* Get the number of properties in the class */ - if(H5P_get_nprops_pclass(crt_pclass, &nprops, FALSE)<0) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "can't query number of properties") - - /* Assume that if there are properties in the class, they are the default ones */ - if(nprops==0) { - /* Register group info */ - if(H5P_register(crt_pclass,H5G_CRT_GROUP_INFO_NAME,H5G_CRT_GROUP_INFO_SIZE, - &ginfo,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") - } /* end if */ - /* Only register the default property list if it hasn't been created yet */ if(H5P_LST_GROUP_CREATE_g==(-1)) { /* Register the default group creation property list */ @@ -1180,118 +1190,33 @@ done: * Programmer: Robb Matzke * Monday, January 5, 1998 * - * Modifications: - * Robb Matzke, 2002-03-28 - * Free the global component buffer. *------------------------------------------------------------------------- */ int H5G_term_interface(void) { - size_t i; - int n=0; + int n = 0; - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_term_interface); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_term_interface) if (H5_interface_initialize_g) { - if ((n=H5I_nmembers(H5I_GROUP))) { + if ((n = H5I_nmembers(H5I_GROUP))) { H5I_clear_type(H5I_GROUP, FALSE); } else { - /* Empty the object type table */ - for (i=0; i<H5G_ntypes_g; i++) - H5MM_xfree(H5G_type_g[i].desc); - H5G_ntypes_g = H5G_atypes_g = 0; - H5G_type_g = H5MM_xfree(H5G_type_g); - /* Destroy the group object id group */ H5I_dec_type_ref(H5I_GROUP); /* Free the global component buffer */ - H5G_comp_g = H5MM_xfree(H5G_comp_g); - H5G_comp_alloc_g = 0; + H5G_traverse_term_interface(); /* Mark closed */ H5_interface_initialize_g = 0; n = 1; /*H5I*/ - } - } - - FUNC_LEAVE_NOAPI(n); -} - - -/*------------------------------------------------------------------------- - * Function: H5G_register_type - * - * Purpose: Register a new object type so H5G_get_type() can detect it. - * One should always register a general type before a more - * specific type. For instance, any object that has a datatype - * message is a datatype, but only some of those objects are - * datasets. - * - * Return: Success: Non-negative - * - * Failure: Negative - * - * Programmer: Robb Matzke - * Wednesday, November 4, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5G_register_type(H5G_obj_t type, htri_t(*isa)(H5G_entry_t*, hid_t), const char *_desc) -{ - char *desc = NULL; - size_t i; - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5G_register_type); - - assert(type>=0); - assert(isa); - assert(_desc); - - /* Copy the description */ - if (NULL==(desc=H5MM_strdup(_desc))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for object type description"); - - /* - * If the type is already registered then just update its entry without - * moving it to the end - */ - for (i=0; i<H5G_ntypes_g; i++) { - if (H5G_type_g[i].type==type) { - H5G_type_g[i].isa = isa; - H5MM_xfree(H5G_type_g[i].desc); - H5G_type_g[i].desc = desc; - HGOTO_DONE(SUCCEED); - } - } - - /* Increase table size */ - if (H5G_ntypes_g>=H5G_atypes_g) { - size_t n = MAX(32, 2*H5G_atypes_g); - H5G_typeinfo_t *x = H5MM_realloc(H5G_type_g, - n*sizeof(H5G_typeinfo_t)); - if (!x) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for objec type table"); - H5G_atypes_g = n; - H5G_type_g = x; - } - - /* Add a new entry */ - H5G_type_g[H5G_ntypes_g].type = type; - H5G_type_g[H5G_ntypes_g].isa = isa; - H5G_type_g[H5G_ntypes_g].desc = desc; /*already copied*/ - H5G_ntypes_g++; + } /* end else */ + } /* end if */ -done: - if (ret_value<0) - H5MM_xfree(desc); - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(n) +} /* end H5G_term_interface() */ /*------------------------------------------------------------------------- @@ -1302,8 +1227,6 @@ done: * the size in characters of the component through SIZE_P not * counting leading slashes or the null terminator. * - * Errors: - * * Return: Success: Ptr into NAME. * * Failure: Ptr to the null terminator of NAME. @@ -1312,15 +1235,13 @@ done: * matzke@llnl.gov * Aug 11 1997 * - * Modifications: - * *------------------------------------------------------------------------- */ -static const char * +const char * H5G_component(const char *name, size_t *size_p) { /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_component); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_component) assert(name); @@ -1329,54 +1250,8 @@ H5G_component(const char *name, size_t *size_p) if (size_p) *size_p = HDstrcspn(name, "/"); - FUNC_LEAVE_NOAPI(name); -} - - -/*------------------------------------------------------------------------- - * Function: H5G_basename - * - * Purpose: Returns a pointer to the last component of the specified - * name. The length of the component is returned through SIZE_P. - * The base name is followed by zero or more slashes and a null - * terminator, but SIZE_P does not count the slashes or the null - * terminator. - * - * Note: The base name of the root directory is a single slash. - * - * Return: Success: Ptr to base name. - * - * Failure: Ptr to the null terminator. - * - * Programmer: Robb Matzke - * Thursday, September 17, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static const char * -H5G_basename(const char *name, size_t *size_p) -{ - size_t i; - - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_basename); - - /* Find the end of the base name */ - i = HDstrlen(name); - while (i>0 && '/'==name[i-1]) - --i; - - /* Skip backward over base name */ - while (i>0 && '/'!=name[i-1]) - --i; - - /* Watch out for root special case */ - if ('/'==name[i] && size_p) - *size_p = 1; - - FUNC_LEAVE_NOAPI(name+i); -} + FUNC_LEAVE_NOAPI(name) +} /* end H5G_component() */ /*------------------------------------------------------------------------- @@ -1446,411 +1321,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5G_namei - * - * 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 bar, but bar is not - * a group, then the results will be that REST points to `baz', - * OBJ_ENT has an undefined object header address, and GRP_ENT - * is the symbol table entry for `bar' in `/foo'. - * - * Every file has a root group whose name is `/'. 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 group - * of the file containing LOC_ENT. Otherwise it begins at - * LOC_ENT. The component `.' is a no-op, but `..' is not - * understood by this function (unless it appears as an entry in - * the symbol table). - * - * Symbolic links are followed automatically, but if TARGET - * includes the H5G_TARGET_SLINK bit and the last component of - * the name is a symbolic link then that link is not followed. - * The *NLINKS value is decremented each time a link is followed - * and link traversal fails if the value would become negative. - * If NLINKS is the null pointer then a default value is used. - * - * Mounted files are handled by calling H5F_mountpoint() after - * each step of the translation. If the input argument to that - * function is a mount point then the argument shall be replaced - * with information about the root group of the mounted file. - * But if TARGET includes the H5G_TARGET_MOUNT bit and the last - * component of the name is a mount point then H5F_mountpoint() - * is not called and information about the mount point itself is - * returned. - * - * Errors: - * - * Return: Success: Non-negative if name can be fully resolved. - * See above for values of REST, GRP_ENT, and - * OBJ_ENT. NLINKS has been decremented for - * each symbolic link that was followed. - * - * Failure: Negative 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 - * Aug 11 1997 - * - * Modifications: - * Robb Matzke, 2002-03-28 - * The component name buffer on the stack has been replaced by - * a dynamically allocated buffer on the heap in order to - * remove limitations on the length of a name component. - * There are two reasons that the buffer pointer is global: - * (1) We want to be able to reuse the buffer without - * allocating and freeing it each time this function is - * called. - * (2) We need to be able to free it from H5G_term_interface() - * when the library terminates. - * - * Pedro Vicente, <pvn@ncsa.uiuc.edu> 22 Aug 2002 - * Modified to deep copies of symbol table entries - * Added `id to name' support. - * - * Quincey Koziol, 2003-01-06 - * Added "action" and "ent" parameters to allow different actions when - * working on the last component of a name. (Specifically, this allows - * inserting an entry into a group, instead of trying to look it up) - * - *------------------------------------------------------------------------- - */ -static herr_t -H5G_namei(const H5G_entry_t *loc_ent, const char *name, const char **rest/*out*/, - H5G_entry_t *grp_ent/*out*/, H5G_entry_t *obj_ent/*out*/, - unsigned target, int *nlinks/*out*/, H5G_namei_act_t action, - H5G_entry_t *ent, hid_t dxpl_id) -{ - H5G_entry_t _grp_ent; /*entry for current group */ - H5G_entry_t _obj_ent; /*entry found */ - size_t nchars; /*component name length */ - int _nlinks = H5G_NLINKS; - const char *s = NULL; - unsigned null_obj; /* Flag to indicate this function was called with obj_ent set to NULL */ - unsigned null_grp; /* Flag to indicate this function was called with grp_ent set to NULL */ - unsigned obj_copy = 0; /* Flag to indicate that the object entry is copied */ - unsigned group_copy = 0; /* Flag to indicate that the group entry is copied */ - unsigned last_comp = 0; /* Flag to indicate that a component is the last component in the name */ - unsigned did_insert = 0; /* Flag to indicate that H5G_stab_insert was called */ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5G_namei); - - /* Set up "out" parameters */ - if (rest) - *rest = name; - if (!grp_ent) { - grp_ent = &_grp_ent; - null_grp = 1; - } /* end if */ - else - null_grp = 0; - if (!obj_ent) { - obj_ent = &_obj_ent; - null_obj = 1; - } /* end if */ - else - null_obj = 0; - if (!nlinks) - nlinks = &_nlinks; - - /* Check args */ - if (!name || !*name) - HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "no name given"); - if (!loc_ent) - HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "no current working group"); - - /* - * Where does the searching start? For absolute names it starts at the - * root of the file; for relative names it starts at CWG. - */ - /* Check if we need to get the root group's entry */ - if ('/' == *name) { - H5G_t *tmp_grp; /* Temporary pointer to root group of file */ - - tmp_grp=H5G_rootof(loc_ent->file); - assert(tmp_grp); - - /* Set the location entry to the root group's entry*/ - loc_ent=&(tmp_grp->ent); - } /* end if */ - - /* Deep copy of the symbol table entry (duplicates strings) */ - if (H5G_ent_copy(obj_ent, loc_ent,H5G_COPY_DEEP)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, FAIL, "unable to copy entry"); - obj_copy = 1; - - H5G_ent_reset(grp_ent); - - /* traverse the name */ - while ((name = H5G_component(name, &nchars)) && *name) { - /* Update the "rest of name" pointer */ - if (rest) - *rest = name; - - /* - * Copy the component name into a null-terminated buffer so - * we can pass it down to the other symbol table functions. - */ - if (nchars+1 > H5G_comp_alloc_g) { - H5G_comp_alloc_g = MAX3(1024, 2*H5G_comp_alloc_g, nchars+1); - H5G_comp_g = H5MM_realloc(H5G_comp_g, H5G_comp_alloc_g); - if (!H5G_comp_g) { - H5G_comp_alloc_g = 0; - HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "unable to allocate component buffer"); - } - } - HDmemcpy(H5G_comp_g, name, nchars); - H5G_comp_g[nchars] = '\0'; - - /* - * The special name `.' is a no-op. - */ - if ('.' == H5G_comp_g[0] && !H5G_comp_g[1]) { - name += nchars; - continue; - } - - /* - * Advance to the next component of the name. - */ - /* If we've already copied a new entry into the group entry, - * it needs to be freed before overwriting it with another entry - */ - if(group_copy) - H5G_free_ent_name(grp_ent); - - /* Transfer "ownership" of the entry's information to the group entry */ - H5G_ent_copy(grp_ent,obj_ent,H5G_COPY_SHALLOW); - H5G_ent_reset(obj_ent); - - /* Set flag that we've copied a new entry into the group entry */ - group_copy =1; - - /* Check if this is the last component of the name */ - if(!((s=H5G_component(name+nchars, NULL)) && *s)) - last_comp=1; - - switch(action) { - case H5G_NAMEI_TRAVERSE: - if (H5G_stab_find(grp_ent, H5G_comp_g, obj_ent/*out*/, dxpl_id )<0) { - /* - * Component was not found in the current symbol table, possibly - * because GRP_ENT isn't a symbol table. - */ - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "component not found"); - } - break; - - case H5G_NAMEI_INSERT: - if(!last_comp) { - if (H5G_stab_find(grp_ent, H5G_comp_g, obj_ent/*out*/, dxpl_id )<0) { - /* If an intermediate group doesn't exist & flag is set, create the group */ - if (target & H5G_CRT_INTMD_GROUP) { - H5G_entry_t new_ent; - - /* Reset group entry */ - H5G_ent_reset(&new_ent); - - /* Create the intermediate group */ - if (H5G_stab_create(grp_ent->file, dxpl_id, 0, &new_ent/*out*/) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create grp"); - - /* Insert new group into current group's symbol table */ - if (H5G_stab_insert(grp_ent, H5G_comp_g, &new_ent, TRUE, dxpl_id)) - HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert intermediate group"); - - /* Keep newly created group's entry, so we can traverse into it */ - if (H5G_ent_copy(obj_ent, &new_ent, H5G_COPY_DEEP)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, FAIL, "unable to copy entry"); - - /* Close new group */ - if (H5O_close(&new_ent) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to close"); - } - else - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "component not found"); - } - } /* end if */ - else { - did_insert = 1; - if (H5G_stab_insert(grp_ent, H5G_comp_g, ent, TRUE, dxpl_id) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert name"); - HGOTO_DONE(SUCCEED); - } /* end else */ - break; - } /* end switch */ - - /* - * If we found a symbolic link then we should follow it. But if this - * is the last component of the name and the H5G_TARGET_SLINK bit of - * TARGET is set then we don't follow it. - */ - if(H5G_CACHED_SLINK==obj_ent->type && - (0==(target & H5G_TARGET_SLINK) || !last_comp)) { - if ((*nlinks)-- <= 0) - HGOTO_ERROR (H5E_SYM, H5E_SLINK, FAIL, "too many links"); - if (H5G_traverse_slink (grp_ent, obj_ent, nlinks, dxpl_id)<0) - HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "symbolic link traversal failed"); - } - - /* - * Resolve mount points to the mounted group. Do not do this step if - * the H5G_TARGET_MOUNT bit of TARGET is set and this is the last - * component of the name. - */ - if (0==(target & H5G_TARGET_MOUNT) || !last_comp) - H5F_mountpoint(obj_ent/*in,out*/); - - /* next component */ - name += nchars; - } /* end while */ - - /* Update the "rest of name" pointer */ - if (rest) - *rest = name; /*final null */ - - /* If this was an insert, make sure that the insert function was actually - * called (this catches no-op names like "." and "/") */ - if(action == H5G_NAMEI_INSERT && !did_insert) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "group already exists"); - -done: - /* If we started with a NULL obj_ent, free the entry information */ - if(null_obj || (ret_value < 0 && obj_copy)) - H5G_free_ent_name(obj_ent); - /* If we started with a NULL grp_ent and we copied something into it, free the entry information */ - if(null_grp && group_copy) - H5G_free_ent_name(grp_ent); - - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5G_traverse_slink - * - * Purpose: Traverses symbolic link. The link head appears in the group - * whose entry is GRP_ENT and the link head entry is OBJ_ENT. - * - * Return: Success: Non-negative, OBJ_ENT will contain information - * about the object to which the link points and - * GRP_ENT will contain the information about - * the group in which the link tail appears. - * - * Failure: Negative - * - * Programmer: Robb Matzke - * Friday, April 10, 1998 - * - * Modifications: - * - * Pedro Vicente, <pvn@ncsa.uiuc.edu> 22 Aug 2002 - * Added `id to name' support. - * - * John Mainzer - 6/8/05 - * Modified function to use the new dirtied parmeter of - * H5AC_unprotect(), which allows management of the is_dirty - * field of the cache info to be moved into the cache code. - * - *------------------------------------------------------------------------- - */ -static herr_t -H5G_traverse_slink (H5G_entry_t *grp_ent/*in,out*/, - H5G_entry_t *obj_ent/*in,out*/, - int *nlinks/*in,out*/, hid_t dxpl_id) -{ - H5O_stab_t stab_mesg; /*info about local heap */ - const char *clv = NULL; /*cached link value */ - char *linkval = NULL; /*the copied link value */ - H5G_entry_t tmp_grp_ent; /* Temporary copy of group entry */ - H5RS_str_t *tmp_user_path_r=NULL, *tmp_canon_path_r=NULL; /* Temporary pointer to object's user path & canonical path */ - const H5HL_t *heap; - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5G_traverse_slink); - - /* Portably initialize the temporary group entry */ - H5G_ent_reset(&tmp_grp_ent); - - /* Get the link value */ - if (NULL==H5O_read (grp_ent, H5O_STAB_ID, 0, &stab_mesg, dxpl_id)) - HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "unable to determine local heap address"); - - if (NULL == (heap = H5HL_protect(grp_ent->file, dxpl_id, stab_mesg.heap_addr))) - HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "unable to read protect link value") - - clv = H5HL_offset_into(grp_ent->file, heap, obj_ent->cache.slink.lval_offset); - - linkval = H5MM_xstrdup (clv); - assert(linkval); - - if (H5HL_unprotect(grp_ent->file, dxpl_id, heap, stab_mesg.heap_addr, H5AC__NO_FLAGS_SET) < 0) - HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "unable to read unprotect link value") - - /* Hold the entry's name (& old_name) to restore later */ - tmp_user_path_r=obj_ent->user_path_r; - obj_ent->user_path_r=NULL; - tmp_canon_path_r=obj_ent->canon_path_r; - obj_ent->canon_path_r=NULL; - - /* Free the names for the group entry */ - H5G_free_ent_name(grp_ent); - - /* Clone the group entry, so we can track the names properly */ - H5G_ent_copy(&tmp_grp_ent,grp_ent,H5G_COPY_DEEP); - - /* Traverse the link */ - if (H5G_namei (&tmp_grp_ent, linkval, NULL, grp_ent, obj_ent, H5G_TARGET_NORMAL, nlinks, H5G_NAMEI_TRAVERSE, NULL, dxpl_id)) - HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "unable to follow symbolic link"); - - /* Free the entry's names, we will use the original name for the object */ - H5G_free_ent_name(obj_ent); - - /* Restore previous name for object */ - obj_ent->user_path_r = tmp_user_path_r; - tmp_user_path_r=NULL; - obj_ent->canon_path_r = tmp_canon_path_r; - tmp_canon_path_r=NULL; - -done: - /* Error cleanup */ - if(tmp_user_path_r) - H5RS_decr(tmp_user_path_r); - if(tmp_canon_path_r) - H5RS_decr(tmp_canon_path_r); - - /* Release cloned copy of group entry */ - H5G_free_ent_name(&tmp_grp_ent); - - H5MM_xfree (linkval); - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- * Function: H5G_mkroot * * Purpose: Creates a root group in an empty file and opens it. If a @@ -1866,78 +1336,91 @@ done: * matzke@llnl.gov * Aug 11 1997 * - * Modifications: - * - * Pedro Vicente, <pvn@ncsa.uiuc.edu> 22 Aug 2002 - * Added `id to name' support. - * *------------------------------------------------------------------------- */ herr_t -H5G_mkroot (H5F_t *f, hid_t dxpl_id, H5G_entry_t *ent) +H5G_mkroot(H5F_t *f, hid_t dxpl_id, H5G_loc_t *loc) { - H5G_entry_t new_root; /*new root object */ - herr_t ret_value=SUCCEED; /* Return value */ + H5O_loc_t new_root_oloc; /* New root object location */ + H5G_name_t new_root_path; /* New root path */ + H5G_loc_t new_root_loc; /* New root location information */ + H5G_loc_t root_loc; /* Root location information */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5G_mkroot, FAIL); + FUNC_ENTER_NOAPI(H5G_mkroot, FAIL) /* check args */ - assert(f); - if (f->shared->root_grp) - HGOTO_DONE(SUCCEED); + HDassert(f); + if(f->shared->root_grp) + HGOTO_DONE(SUCCEED) /* Create information needed for group nodes */ - if(H5G_node_init(f)<0) + if(H5G_node_init(f) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create group node info") /* * If there is no root object then create one. The root group always starts * with a hard link count of one since it's pointed to by the boot block. */ - if (!ent) { - ent = &new_root; - H5G_ent_reset(ent); - if (H5G_stab_create (f, dxpl_id, (size_t)H5G_SIZE_HINT, ent/*out*/)<0) - HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, "unable to create root group"); - if (1 != H5O_link (ent, 1, dxpl_id)) - HGOTO_ERROR (H5E_SYM, H5E_LINK, FAIL, "internal error (wrong link count)"); + if (loc == NULL) { + H5P_genplist_t *fc_plist; /* File creation property list */ + H5O_ginfo_t ginfo; /* Group info parameters */ + + /* Get the file creation property list */ + /* (Which is a sub-class of the group creation property class) */ + if(NULL == (fc_plist = H5I_object(f->shared->fcpl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list") + + /* Get the group info property */ + if(H5P_get(fc_plist, H5G_CRT_GROUP_INFO_NAME, &ginfo) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get group info") + + /* Set up group location for root group */ + new_root_loc.oloc = &new_root_oloc; + new_root_loc.path = &new_root_path; + H5G_loc_reset(&new_root_loc); + loc = &new_root_loc; + + if(H5G_obj_create(f, dxpl_id, &ginfo, loc->oloc/*out*/) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create group entry") + if(1 != H5O_link(loc->oloc, 1, dxpl_id)) + HGOTO_ERROR(H5E_SYM, H5E_LINK, FAIL, "internal error (wrong link count)") } else { /* * Open the root object as a group. */ - if (H5O_open (ent)<0) - HGOTO_ERROR (H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open root group"); - } + if(H5O_open(loc->oloc) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open root group") + } /* end else */ /* Create the path names for the root group's entry */ - ent->user_path_r=H5RS_create("/"); - assert(ent->user_path_r); - ent->canon_path_r=H5RS_create("/"); - assert(ent->canon_path_r); - ent->user_path_hidden=0; + H5G_name_init(loc->path, "/"); /* * Create the group pointer. Also decrement the open object count so we * don't count the root group as an open object. The root group will * never be closed. */ - if (NULL==(f->shared->root_grp = H5FL_CALLOC (H5G_t))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - if (NULL==(f->shared->root_grp->shared = H5FL_CALLOC (H5G_shared_t))) { + if(NULL == (f->shared->root_grp = H5FL_CALLOC(H5G_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + if(NULL == (f->shared->root_grp->shared = H5FL_CALLOC(H5G_shared_t))) { H5FL_FREE(H5G_t, f->shared->root_grp); - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - } - /* Shallow copy (take ownership) of the group entry object */ - if(H5G_ent_copy(&(f->shared->root_grp->ent), ent, H5G_COPY_SHALLOW)<0) - HGOTO_ERROR (H5E_SYM, H5E_CANTCOPY, FAIL, "can't copy group entry") + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + } /* end if */ + + /* Shallow copy (take ownership) of the group object info */ + root_loc.oloc = &(f->shared->root_grp->oloc); + root_loc.path = &(f->shared->root_grp->path); + if(H5G_loc_copy(&root_loc, loc, H5G_COPY_SHALLOW) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, FAIL, "can't copy group object location") f->shared->root_grp->shared->fo_count = 1; - assert (1==f->nopen_objs); + HDassert(1 == f->nopen_objs); f->nopen_objs = 0; done: - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_mkroot() */ /*------------------------------------------------------------------------- @@ -1946,8 +1429,6 @@ done: * Purpose: Creates a new empty group with the specified name. The name * is either an absolute name or is relative to LOC. * - * Errors: - * * Return: Success: A handle for the group. The group is opened * and should eventually be close by calling * H5G_close(). @@ -1958,85 +1439,88 @@ done: * matzke@llnl.gov * Aug 11 1997 * - * Modifications: - * - * Pedro Vicente, <pvn@ncsa.uiuc.edu> 18 Sep 2002 - * Added `id to name' support. - * *------------------------------------------------------------------------- */ static H5G_t * -H5G_create(H5G_entry_t *loc, const char *name, +H5G_create(H5G_loc_t *loc, const char *name, hid_t dxpl_id, hid_t gcpl_id, hid_t UNUSED gapl_id) { H5G_t *grp = NULL; /*new group */ H5F_t *file = NULL; /* File new group will be in */ H5P_genplist_t *gc_plist; /* Property list created */ - unsigned stab_init=0; /* Flag to indicate that the symbol table was created successfully */ + H5O_ginfo_t ginfo; /* Group info */ + unsigned oloc_init = 0; /* Flag to indicate that the group object location was created successfully */ + H5G_loc_t grp_loc; /* Group location wrapper structure */ H5G_t *ret_value; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5G_create); + FUNC_ENTER_NOAPI_NOINIT(H5G_create) /* check args */ - assert(loc); - assert(name && *name); - assert(gcpl_id != H5P_DEFAULT); + HDassert(loc); + HDassert(name && *name); + HDassert(gcpl_id != H5P_DEFAULT); #ifdef LATER - assert(gapl_id != H5P_DEFAULT); + HDassert(gapl_id != H5P_DEFAULT); #endif /* LATER */ /* create an open group */ - if (NULL==(grp = H5FL_CALLOC(H5G_t))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - if (NULL==(grp->shared = H5FL_CALLOC(H5G_t))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + if(NULL == (grp = H5FL_CALLOC(H5G_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + if(NULL == (grp->shared = H5FL_CALLOC(H5G_shared_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* What file is the group being added to? */ - if (NULL==(file=H5G_insertion_file(loc, name, dxpl_id))) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "unable to locate insertion point"); - - /* Create the group entry */ - if (H5G_stab_create(file, dxpl_id, (size_t)H5G_SIZE_HINT, &(grp->ent)/*out*/) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "can't create grp"); - stab_init=1; /* Indicate that the symbol table information is valid */ + if(NULL == (file = H5G_insertion_file(loc, name, dxpl_id))) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "unable to locate insertion point") /* Get the property list */ - if (NULL == (gc_plist = H5I_object(gcpl_id))) + if(NULL == (gc_plist = H5I_object(gcpl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a property list") - /* insert child name into parent */ - if(H5G_insert(loc,name,&(grp->ent), dxpl_id, gc_plist)<0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, NULL, "can't insert group"); + /* Get the group info property */ + if(H5P_get(gc_plist, H5G_CRT_GROUP_INFO_NAME, &ginfo) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get group info") + + /* Create the group object header */ + if(H5G_obj_create(file, dxpl_id, &ginfo, &(grp->oloc)/*out*/) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "unable to create group object header") + oloc_init = 1; /* Indicate that the object location information is valid */ + + /* Insert child name into parent */ + grp_loc.oloc = &(grp->oloc); + grp_loc.path = &(grp->path); + if(H5G_insert(loc, name, &grp_loc, dxpl_id, gc_plist) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, NULL, "can't insert group") /* Add group to list of open objects in file */ - if(H5FO_top_incr(grp->ent.file, grp->ent.header)<0) + if(H5FO_top_incr(grp->oloc.file, grp->oloc.addr) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINC, NULL, "can't incr object ref. count") - if(H5FO_insert(grp->ent.file, grp->ent.header, grp->shared)<0) + if(H5FO_insert(grp->oloc.file, grp->oloc.addr, grp->shared) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, NULL, "can't insert group into list of open objects") grp->shared->fo_count = 1; /* Set return value */ - ret_value=grp; + ret_value = grp; done: - if(ret_value==NULL) { + if(ret_value == NULL) { /* Check if we need to release the file-oriented symbol table info */ - if(stab_init) { - if(H5O_close(&(grp->ent))<0) - HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, NULL, "unable to release object header"); - if(H5O_delete(file, dxpl_id,grp->ent.header)<0) - HDONE_ERROR(H5E_SYM, H5E_CANTDELETE, NULL, "unable to delete object header"); + if(oloc_init) { + if(H5O_close(&(grp->oloc)) < 0) + HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, NULL, "unable to release object header") + if(H5O_delete(file, dxpl_id, grp->oloc.addr) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTDELETE, NULL, "unable to delete object header") } /* end if */ - if(grp!=NULL) { + if(grp != NULL) { if(grp->shared != NULL) H5FL_FREE(H5G_shared_t, grp->shared); H5FL_FREE(H5G_t,grp); - } + } /* end if */ } /* end if */ - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_create() */ /*------------------------------------------------------------------------- @@ -2054,61 +1538,30 @@ done: * Programmer: Robb Matzke * Monday, November 2, 1998 * - * Modifications: - * *------------------------------------------------------------------------- */ -static htri_t -H5G_isa(H5G_entry_t *ent, hid_t dxpl_id) +htri_t +H5G_isa(H5O_loc_t *loc, hid_t dxpl_id) { + htri_t stab_exists; + htri_t linfo_exists; htri_t ret_value; - FUNC_ENTER_NOAPI_NOINIT(H5G_isa); - - assert(ent); - - if ((ret_value=H5O_exists(ent, H5O_STAB_ID, 0, dxpl_id))<0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to read object header"); - -done: - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5G_link_isa - * - * Purpose: Determines if an object has the requisite form for being - * a soft link. - * - * Return: Success: TRUE if the symbol table entry is of type - * H5G_LINK; FALSE otherwise. - * - * Failure: Shouldn't fail. - * - * Programmer: Quincey Koziol - * Wednesday, June 23, 2004 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static htri_t -H5G_link_isa(H5G_entry_t *ent, hid_t UNUSED dxpl_id) -{ - htri_t ret_value; + FUNC_ENTER_NOAPI_NOINIT(H5G_isa) - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_link_isa); + HDassert(loc); - assert(ent); + /* Check for any of the messages that indicate a group */ + if((stab_exists = H5O_exists(loc, H5O_STAB_ID, 0, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to read object header") + if((linfo_exists = H5O_exists(loc, H5O_LINFO_ID, 0, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to read object header") - if(ent->type == H5G_CACHED_SLINK) - ret_value=TRUE; - else - ret_value=FALSE; + ret_value = (stab_exists > 0 || linfo_exists > 0); - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5G_link_isa() */ +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_isa() */ /*------------------------------------------------------------------------- @@ -2124,58 +1577,54 @@ H5G_link_isa(H5G_entry_t *ent, hid_t UNUSED dxpl_id) * Programmer: Robb Matzke * Monday, January 5, 1998 * - * Modifications: - * Modified to call H5G_open_oid - QAK - 3/17/99 - * - * Pedro Vicente, <pvn@ncsa.uiuc.edu> 18 Sep 2002 - * Added `id to name' support. - * *------------------------------------------------------------------------- */ H5G_t * -H5G_open(H5G_entry_t *ent, hid_t dxpl_id) +H5G_open(H5G_loc_t *loc, hid_t dxpl_id) { H5G_t *grp = NULL; - H5G_shared_t *shared_fo=NULL; - H5G_t *ret_value=NULL; + H5G_shared_t *shared_fo = NULL; + H5G_t *ret_value = NULL; - FUNC_ENTER_NOAPI(H5G_open, NULL); + FUNC_ENTER_NOAPI(H5G_open, NULL) /* Check args */ - assert(ent); + HDassert(loc); + + /* Allocate the group structure */ + if(NULL == (grp = H5FL_CALLOC(H5G_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate space for group") + + /* Shallow copy (take ownership) of the group location object */ + if(H5O_loc_copy(&(grp->oloc), loc->oloc, H5O_COPY_SHALLOW) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "can't copy object location") + if(H5G_name_copy(&(grp->path), loc->path, H5G_COPY_SHALLOW) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "can't copy path") /* Check if group was already open */ - if((shared_fo=H5FO_opened(ent->file, ent->header))==NULL) { + if((shared_fo = H5FO_opened(grp->oloc.file, grp->oloc.addr)) == NULL) { /* Clear any errors from H5FO_opened() */ H5E_clear_stack(NULL); /* Open the group object */ - if ((grp=H5G_open_oid(ent, dxpl_id)) ==NULL) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, NULL, "not found"); + if(H5G_open_oid(grp, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, NULL, "not found") /* Add group to list of open objects in file */ - if(H5FO_insert(grp->ent.file, grp->ent.header, grp->shared)<0) - { + if(H5FO_insert(grp->oloc.file, grp->oloc.addr, grp->shared) < 0) { H5FL_FREE(H5G_shared_t, grp->shared); HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, NULL, "can't insert group into list of open objects") - } + } /* end if */ /* Increment object count for the object in the top file */ - if(H5FO_top_incr(grp->ent.file, grp->ent.header) < 0) + if(H5FO_top_incr(grp->oloc.file, grp->oloc.addr) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINC, NULL, "can't increment object count") /* Set open object count */ grp->shared->fo_count = 1; - } + } /* end if */ else { - if(NULL == (grp = H5FL_CALLOC(H5G_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate space for group") - - /* Shallow copy (take ownership) of the group entry object */ - if(H5G_ent_copy(&(grp->ent), ent, H5G_COPY_SHALLOW)<0) - HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "can't copy group entry") - /* Point to shared group info */ grp->shared = shared_fo; @@ -2183,16 +1632,16 @@ H5G_open(H5G_entry_t *ent, hid_t dxpl_id) shared_fo->fo_count++; /* Check if the object has been opened through the top file yet */ - if(H5FO_top_count(grp->ent.file, grp->ent.header) == 0) { + if(H5FO_top_count(grp->oloc.file, grp->oloc.addr) == 0) { /* Open the object through this top file */ - if(H5O_open(&(grp->ent)) < 0) + if(H5O_open(&(grp->oloc)) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, NULL, "unable to open object header") } /* end if */ /* Increment object count for the object in the top file */ - if(H5FO_top_incr(grp->ent.file, grp->ent.header) < 0) + if(H5FO_top_incr(grp->oloc.file, grp->oloc.addr) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINC, NULL, "can't increment object count") - } + } /* end else */ /* Set return value */ ret_value = grp; @@ -2201,8 +1650,8 @@ done: if (!ret_value && grp) H5FL_FREE(H5G_t,grp); - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_open() */ /*------------------------------------------------------------------------- @@ -2218,59 +1667,43 @@ done: * Programmer: Quincey Koziol * Wednesday, March 17, 1999 * - * Modifications: - * - * Pedro Vicente, <pvn@ncsa.uiuc.edu> 22 Aug 2002 - * Added a deep copy of the symbol table entry - * *------------------------------------------------------------------------- */ -static H5G_t * -H5G_open_oid(H5G_entry_t *ent, hid_t dxpl_id) +static herr_t +H5G_open_oid(H5G_t *grp, hid_t dxpl_id) { - H5G_t *grp = NULL; - H5G_t *ret_value = NULL; - hbool_t ent_opened = FALSE; + hbool_t obj_opened = FALSE; + herr_t ret_value = SUCCEED; - FUNC_ENTER_NOAPI_NOINIT(H5G_open_oid); + FUNC_ENTER_NOAPI_NOINIT(H5G_open_oid) /* Check args */ - assert(ent); - - /* Open the object, making sure it's a group */ - if (NULL==(grp = H5FL_CALLOC(H5G_t))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - if (NULL==(grp->shared = H5FL_CALLOC(H5G_shared_t))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + HDassert(grp); - /* Copy over (take ownership) of the group entry object */ - H5G_ent_copy(&(grp->ent),ent,H5G_COPY_SHALLOW); + /* Allocate the shared information for the group */ + if(NULL == (grp->shared = H5FL_CALLOC(H5G_shared_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") /* Grab the object header */ - if (H5O_open(&(grp->ent)) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, NULL, "unable to open group") - ent_opened = TRUE; + if(H5O_open(&(grp->oloc)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group") + obj_opened = TRUE; /* Check if this object has the right message(s) to be treated as a group */ - if(H5O_exists(&(grp->ent), H5O_STAB_ID, 0, dxpl_id) <= 0) - HGOTO_ERROR (H5E_SYM, H5E_CANTOPENOBJ, NULL, "not a group") - - /* Set return value */ - ret_value = grp; + if(H5O_exists(&(grp->oloc), H5O_STAB_ID, 0, dxpl_id) <= 0 + && H5O_exists(&(grp->oloc), H5O_LINFO_ID, 0, dxpl_id) <= 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "not a group") done: - if(!ret_value) { - if(grp) { - if(ent_opened) - H5O_close(&(grp->ent)); - if(grp->shared) - H5FL_FREE(H5G_shared_t, grp->shared); - H5FL_FREE(H5G_t,grp); - } /* end if */ + if(ret_value < 0) { + if(obj_opened) + H5O_close(&(grp->oloc)); + if(grp->shared) + H5FL_FREE(H5G_shared_t, grp->shared); } /* end if */ - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_open_oid() */ /*------------------------------------------------------------------------- @@ -2283,42 +1716,40 @@ done: * Programmer: Robb Matzke * Monday, January 5, 1998 * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t H5G_close(H5G_t *grp) { - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5G_close, FAIL); + FUNC_ENTER_NOAPI(H5G_close, FAIL) /* Check args */ - assert(grp && grp->shared); - assert(grp->shared->fo_count > 0); + HDassert(grp && grp->shared); + HDassert(grp->shared->fo_count > 0); --grp->shared->fo_count; - if (0 == grp->shared->fo_count) { - assert (grp!=H5G_rootof(H5G_fileof(grp))); + if(0 == grp->shared->fo_count) { + HDassert(grp != H5G_rootof(H5G_fileof(grp))); /* Remove the group from the list of opened objects in the file */ - if(H5FO_top_decr(grp->ent.file, grp->ent.header) < 0) + if(H5FO_top_decr(grp->oloc.file, grp->oloc.addr) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't decrement count for object") - if(H5FO_delete(grp->ent.file, H5AC_dxpl_id, grp->ent.header)<0) + if(H5FO_delete(grp->oloc.file, H5AC_dxpl_id, grp->oloc.addr) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't remove group from list of open objects") - if(H5O_close(&(grp->ent)) < 0) + if(H5O_close(&(grp->oloc)) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to close") - H5FL_FREE (H5G_shared_t, grp->shared); + H5FL_FREE(H5G_shared_t, grp->shared); } else { /* Decrement the ref. count for this object in the top file */ - if(H5FO_top_decr(grp->ent.file, grp->ent.header) < 0) + if(H5FO_top_decr(grp->oloc.file, grp->oloc.addr) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't decrement count for object") /* Check reference count for this object in the top file */ - if(H5FO_top_count(grp->ent.file, grp->ent.header) == 0) - if(H5O_close(&(grp->ent)) < 0) + if(H5FO_top_count(grp->oloc.file, grp->oloc.addr) == 0) + if(H5O_close(&(grp->oloc)) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to close") /* If this group is a mount point and the mount point is the last open @@ -2326,21 +1757,20 @@ H5G_close(H5G_t *grp) */ if(grp->shared->mounted && grp->shared->fo_count == 1) { /* Attempt to close down the file hierarchy */ - if(H5F_try_close(grp->ent.file) < 0) + if(H5F_try_close(grp->oloc.file) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "problem attempting file close") } /* end if */ + } /* end else */ - if(H5G_free_ent_name(&(grp->ent))<0) - { - H5FL_FREE (H5G_t,grp); - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't free group entry name"); - } - } + if(H5G_name_free(&(grp->path)) < 0) { + H5FL_FREE(H5G_t,grp); + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't free group entry name") + } /* end if */ - H5FL_FREE (H5G_t,grp); + H5FL_FREE(H5G_t,grp); done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5G_close() */ @@ -2364,18 +1794,18 @@ done: herr_t H5G_free(H5G_t *grp) { - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5G_free, FAIL); + FUNC_ENTER_NOAPI(H5G_free, FAIL) - assert(grp && grp->shared); + HDassert(grp && grp->shared); H5FL_FREE(H5G_shared_t, grp->shared); H5FL_FREE(H5G_t, grp); done: - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_free() */ /*------------------------------------------------------------------------- @@ -2398,275 +1828,238 @@ done: * *------------------------------------------------------------------------- */ -static H5G_t * +H5G_t * H5G_rootof(H5F_t *f) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_rootof); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_rootof) - while (f->mtab.parent) + while(f->mtab.parent) f = f->mtab.parent; - FUNC_LEAVE_NOAPI(f->shared->root_grp); -} + FUNC_LEAVE_NOAPI(f->shared->root_grp) +} /* end H5G_rootof() */ /*------------------------------------------------------------------------- - * Function: H5G_insert - * - * Purpose: Inserts a symbol table entry into the group graph. + * Function: H5G_oloc * - * Errors: + * Purpose: Returns a pointer to the object location for a group. * - * Return: Non-negative on success/Negative on failure + * Return: Success: Ptr to group entry + * Failure: NULL * * Programmer: Robb Matzke - * Friday, September 19, 1997 - * - * Modifications: - * - * Pedro Vicente, <pvn@ncsa.uiuc.edu> 18 Sep 2002 - * Added `id to name' support. - * - * Peter Cao - * May 09, 2005 - * Add flag 'crt_intmd_group' to support creating missing groups + * Tuesday, March 24, 1998 * *------------------------------------------------------------------------- */ -herr_t -H5G_insert(H5G_entry_t *loc, const char *name, H5G_entry_t *ent, hid_t dxpl_id, H5P_genplist_t *oc_plist) +H5O_loc_t * +H5G_oloc(H5G_t *grp) { - herr_t ret_value=SUCCEED; /* Return value */ - unsigned target=H5G_TARGET_NORMAL; - - FUNC_ENTER_NOAPI(H5G_insert, FAIL); - - /* Check args. */ - assert (loc); - assert (name && *name); - assert (ent); - - /* Check for intermediate group creation flag present */ - if(oc_plist != NULL) { - unsigned crt_intmd_group; - - if(H5P_get(oc_plist, H5G_CRT_INTERMEDIATE_GROUP_NAME, &crt_intmd_group) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for creating missing groups"); - - if (crt_intmd_group > 0) - target |= H5G_CRT_INTMD_GROUP; - } /* end if */ - - /* - * Lookup and insert the name -- it shouldn't exist yet. - */ - if (H5G_namei(loc, name, NULL, NULL, NULL, target, NULL, H5G_NAMEI_INSERT, ent, dxpl_id)<0) - HGOTO_ERROR(H5E_SYM, H5E_EXISTS, FAIL, "already exists"); + /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_oloc) -done: - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(grp ? &(grp->oloc) : NULL) +} /* end H5G_oloc() */ /*------------------------------------------------------------------------- - * Function: H5G_find - * - * Purpose: Finds an object with the specified NAME at location LOC. On - * successful return, GRP_ENT (if non-null) will be initialized - * with the symbol table information for the group in which 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). - * - * Errors: + * Function: H5G_nameof * - * Return: Success: Non-negative, see above for values of GRP_ENT - * and OBJ_ENT. + * Purpose: Returns a pointer to the hier. name for a group. * - * Failure: Negative - * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Aug 12 1997 + * Return: Success: Ptr to hier. name + * Failure: NULL * - * Modifications: - * Removed the "H5G_entry_t *grp_ent" parameter, since it was unused - * Quincey Koziol - * Aug 29 2005 + * Programmer: Quincey Koziol + * Monday, September 12, 2005 * *------------------------------------------------------------------------- */ -herr_t -H5G_find(H5G_entry_t *loc, const char *name, - H5G_entry_t *obj_ent/*out*/, hid_t dxpl_id) +H5G_name_t * +H5G_nameof(H5G_t *grp) { - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5G_find, FAIL); - - /* check args */ - assert (loc); - assert (name && *name); - - if (H5G_namei(loc, name, NULL, NULL, obj_ent, H5G_TARGET_NORMAL, NULL, H5G_NAMEI_TRAVERSE, NULL, dxpl_id)<0) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found"); + /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_nameof) -done: - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(grp ? &(grp->path) : NULL) +} /* end H5G_nameof() */ /*------------------------------------------------------------------------- - * Function: H5G_entof + * Function: H5G_fileof * - * Purpose: Returns a pointer to the entry for a group. + * Purpose: Returns the file to which the specified group belongs. * - * Return: Success: Ptr to group entry + * Return: Success: File pointer. * * Failure: NULL * * Programmer: Robb Matzke * Tuesday, March 24, 1998 * - * Modifications: - * *------------------------------------------------------------------------- */ -H5G_entry_t * -H5G_entof (H5G_t *grp) +H5F_t * +H5G_fileof(H5G_t *grp) { /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_entof); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_fileof) - FUNC_LEAVE_NOAPI(grp ? &(grp->ent) : NULL); -} + HDassert(grp); + + FUNC_LEAVE_NOAPI(grp->oloc.file) +} /* end H5G_fileof() */ /*------------------------------------------------------------------------- - * Function: H5G_fileof - * - * Purpose: Returns the file to which the specified group belongs. - * - * Return: Success: File pointer. + * Function: H5G_insert_cb * - * Failure: NULL + * Purpose: Path traversal callback for inserting an object in a group. * - * Programmer: Robb Matzke - * Tuesday, March 24, 1998 + * Return: Non-negative on success/Negative on failure * - * Modifications: + * Programmer: Quincey Koziol + * Tuesday, September 13, 2005 * *------------------------------------------------------------------------- */ -H5F_t * -H5G_fileof (H5G_t *grp) +static herr_t +H5G_insert_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t UNUSED *lnk, + H5G_loc_t *obj_loc, void *_udata/*in,out*/) { - /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_fileof); + H5G_trav_ud7_t *udata = (H5G_trav_ud7_t *)_udata; /* User data passed in */ + herr_t ret_value = SUCCEED; /* Return value */ - assert (grp); + FUNC_ENTER_NOAPI_NOINIT(H5G_insert_cb) - FUNC_LEAVE_NOAPI(grp->ent.file); -} + /* Check for object using name already */ + if(obj_loc != NULL) + HGOTO_ERROR(H5E_SYM, H5E_EXISTS, FAIL, "name already exists") + + /* Insert object into group */ + if(H5G_loc_insert(grp_loc, name, udata->obj_loc, TRUE, udata->dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert name") + +done: + if(ret_value < 0) { + /* Release the group location for the object */ + /* (Group traversal callbacks are responsible for either taking ownership + * of the group location for the object, or freeing it. - QAK) + */ + if(obj_loc) + H5G_loc_free(obj_loc); + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_insert_cb() */ /*------------------------------------------------------------------------- - * Function: H5G_loc - * - * Purpose: Given an object ID return a symbol table entry for the - * object. + * Function: H5G_insert * - * Return: Success: Group pointer. + * Purpose: Inserts a symbol table entry into the group graph. * - * Failure: NULL + * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke - * Tuesday, March 24, 1998 - * - * Modifications: + * Friday, September 19, 1997 * *------------------------------------------------------------------------- */ -H5G_entry_t * -H5G_loc (hid_t loc_id) +herr_t +H5G_insert(H5G_loc_t *loc, const char *name, H5G_loc_t *obj_loc, hid_t dxpl_id, H5P_genplist_t *oc_plist) { - H5F_t *f; - H5G_entry_t *ret_value=NULL; - H5G_t *group=NULL; - H5T_t *dt=NULL; - H5D_t *dset=NULL; - H5A_t *attr=NULL; - - FUNC_ENTER_NOAPI(H5G_loc, NULL); - - switch (H5I_get_type(loc_id)) { - case H5I_FILE: - if (NULL==(f=H5I_object (loc_id))) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, NULL, "invalid file ID"); - if (NULL==(ret_value=H5G_entof(H5G_rootof(f)))) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "unable to get symbol table entry for root group"); - - /* Patch up root group's symbol table entry to reflect this file */ - /* (Since the root group info is only stored once for files which - * share an underlying low-level file) - */ - /* (but only for non-mounted files) */ - if(!f->mtab.parent) - ret_value->file = f; - break; + H5G_trav_ud7_t udata; /* User data for callback routine */ + unsigned target_flags = H5G_TARGET_NORMAL; + herr_t ret_value = SUCCEED; /* Return value */ - case H5I_GENPROP_CLS: - case H5I_GENPROP_LST: - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "unable to get symbol table entry of property list"); + FUNC_ENTER_NOAPI(H5G_insert, FAIL) - case H5I_ERROR_CLASS: - case H5I_ERROR_MSG: - case H5I_ERROR_STACK: - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "unable to get symbol table entry of error class, message or stack"); + /* Check args. */ + HDassert(loc); + HDassert(name && *name); + HDassert(obj_loc); - case H5I_GROUP: - if (NULL==(group=H5I_object (loc_id))) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, NULL, "invalid group ID"); - if (NULL==(ret_value=H5G_entof(group))) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "unable to get symbol table entry of group"); - break; + /* Check for intermediate group creation flag present */ + if(oc_plist != NULL) { + unsigned crt_intmd_group; - case H5I_DATATYPE: - if (NULL==(dt=H5I_object(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid type ID"); - if (NULL==(ret_value=H5T_entof(dt))) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "unable to get symbol table entry of datatype"); - break; + if(H5P_get(oc_plist, H5G_CRT_INTERMEDIATE_GROUP_NAME, &crt_intmd_group) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for creating missing groups") - case H5I_DATASPACE: - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "unable to get symbol table entry of dataspace"); + if (crt_intmd_group > 0) + target_flags |= H5G_CRT_INTMD_GROUP; + } /* end if */ - case H5I_DATASET: - if (NULL==(dset=H5I_object(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid data ID"); - if (NULL==(ret_value=H5D_entof(dset))) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "unable to get symbol table entry of dataset"); - break; + /* Set up user data callback for path traversal */ + udata.obj_loc = obj_loc; + udata.dxpl_id = dxpl_id; - case H5I_ATTR: - if (NULL==(attr=H5I_object(loc_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid attribute ID"); - if (NULL==(ret_value=H5A_entof(attr))) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "unable to get symbol table entry of attribute"); - break; + /* + * Lookup and insert the name -- it shouldn't exist yet. + */ + if(H5G_traverse(loc, name, target_flags, H5G_insert_cb, &udata, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_EXISTS, FAIL, "can't insert object in group") - case H5I_REFERENCE: - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "unable to get symbol table entry of reference"); +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_insert() */ - default: - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid object ID"); - } + +/*------------------------------------------------------------------------- + * Function: H5G_link_cb + * + * Purpose: Callback for creating a link to an object. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Monday, September 19, 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_link_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t UNUSED *lnk, + H5G_loc_t *obj_loc, void *_udata/*in,out*/) +{ + H5G_trav_ud3_t *udata = (H5G_trav_ud3_t *)_udata; /* User data passed in */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5G_link_cb) + + /* Check if the name in this group resolved to a valid location */ + /* (which is not what we want) */ + if(obj_loc != NULL) + HGOTO_ERROR(H5E_SYM, H5E_EXISTS, FAIL, "name already exists") + + /* Check for crossing file boundaries with a new hard link */ + if(udata->lnk->type == H5G_LINK_HARD) { + /* Check that both objects are in same file */ + if(grp_loc->oloc->file->shared != udata->file->shared) + HGOTO_ERROR(H5E_SYM, H5E_LINK, FAIL, "interfile hard links are not allowed") + } /* end if */ + + /* Set the link's name correctly */ + /* Casting away const OK -QAK */ + udata->lnk->name = name; + + /* Insert link into group */ + if(H5G_obj_insert(grp_loc->oloc, name, udata->lnk, (hbool_t)(udata->lnk->type == H5G_LINK_HARD ? TRUE : FALSE), udata->dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create new name/link for object") done: - FUNC_LEAVE_NOAPI(ret_value); -} + if(ret_value < 0) { + /* Release the group location for the object */ + /* (Group traversal callbacks are responsible for either taking ownership + * of the group location for the object, or freeing it. - QAK) + */ + if(obj_loc) + H5G_loc_free(obj_loc); + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_link_cb() */ /*------------------------------------------------------------------------- @@ -2688,431 +2081,280 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5G_link (H5G_entry_t *cur_loc, const char *cur_name, H5G_entry_t *new_loc, - const char *new_name, H5G_link_t type, unsigned namei_flags, hid_t dxpl_id) +H5G_link(H5G_loc_t *cur_loc, const char *cur_name, H5G_loc_t *new_loc, + const char *new_name, H5G_link_t type, unsigned traverse_flags, hid_t dxpl_id) { - H5G_entry_t cur_obj; /*entry for the link tail */ - unsigned cur_obj_init=0; /* Flag to indicate that the current object is initialized */ - H5G_entry_t grp_ent; /*ent for grp containing link hd*/ - H5O_stab_t stab_mesg; /*symbol table message */ - const char *rest = NULL; /*last component of new name */ - char *norm_cur_name = NULL; /* Pointer to normalized current name */ - char *norm_new_name = NULL; /* Pointer to normalized current name */ - size_t nchars; /*characters in component */ - size_t offset; /*offset to sym-link value */ - herr_t ret_value=SUCCEED; /* Return value */ + char *norm_cur_name = NULL; /* Pointer to normalized current name */ + char *norm_new_name = NULL; /* Pointer to normalized current name */ + H5G_trav_ud3_t udata; /* User data for callback */ + H5O_link_t lnk; /* Link to insert */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5G_link); + FUNC_ENTER_NOAPI_NOINIT(H5G_link) /* Check args */ - assert (cur_loc); - assert (new_loc); - assert (cur_name && *cur_name); - assert (new_name && *new_name); + HDassert(cur_loc); + HDassert(new_loc); + HDassert(cur_name && *cur_name); + HDassert(new_name && *new_name); /* Get normalized copies of the current and new names */ - if((norm_cur_name=H5G_normalize(cur_name))==NULL) - HGOTO_ERROR (H5E_SYM, H5E_BADVALUE, FAIL, "can't normalize name"); - if((norm_new_name=H5G_normalize(new_name))==NULL) - HGOTO_ERROR (H5E_SYM, H5E_BADVALUE, FAIL, "can't normalize name"); + if((norm_cur_name = H5G_normalize(cur_name)) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "can't normalize name") + if((norm_new_name = H5G_normalize(new_name)) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "can't normalize name") - switch (type) { + switch(type) { case H5G_LINK_SOFT: - /* - * Lookup the the new_name so we can get the group which will contain - * the new entry. The entry shouldn't exist yet. - */ - if (H5G_namei(new_loc, norm_new_name, &rest, &grp_ent, NULL, - H5G_TARGET_NORMAL, NULL, H5G_NAMEI_TRAVERSE, NULL, dxpl_id)>=0) - HGOTO_ERROR (H5E_SYM, H5E_EXISTS, FAIL, "already exists"); - H5E_clear_stack (NULL); /*it's okay that we didn't find it*/ - rest = H5G_component (rest, &nchars); - - /* - * There should be one component left. Make sure it's null - * terminated and that `rest' points to it. - */ - assert(!rest[nchars]); - - /* - * Add the link-value to the local heap for the symbol table which - * will contain the link. - */ - if (NULL==H5O_read (&grp_ent, H5O_STAB_ID, 0, &stab_mesg, dxpl_id)) - HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, "unable to determine local heap address"); - if ((size_t)(-1)==(offset=H5HL_insert (grp_ent.file, dxpl_id, - stab_mesg.heap_addr, HDstrlen(norm_cur_name)+1, norm_cur_name))) - HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, "unable to write link value to local heap"); - H5O_reset (H5O_STAB_ID, &stab_mesg); - - /* - * Create a symbol table entry for the link. The object header is - * undefined and the cache contains the link-value offset. - */ - H5G_ent_reset(&cur_obj); - cur_obj.file = grp_ent.file; - cur_obj.type = H5G_CACHED_SLINK; - cur_obj.cache.slink.lval_offset = offset; - cur_obj_init=1; /* Indicate that the cur_obj struct is initialized */ - - /* - * Insert the link head in the symbol table. This shouldn't ever - * fail because we've already checked that the link head doesn't - * exist and the file is writable (because the local heap is - * writable). But if it does, the only side effect is that the local - * heap has some extra garbage in it. - * - * Note: We don't increment the link count of the destination object - */ - if (H5G_stab_insert (&grp_ent, rest, &cur_obj, FALSE, dxpl_id)<0) - HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, "unable to create new name/link for object"); + /* Construct link information for eventual insertion */ + lnk.type = H5G_LINK_SOFT; + lnk.u.soft.name = norm_cur_name; + + /* Set up user data for creating soft link */ + udata.file = NULL; /* no file info necessary for soft link */ break; case H5G_LINK_HARD: - if (H5G_namei(cur_loc, norm_cur_name, NULL, NULL, &cur_obj, namei_flags, NULL, H5G_NAMEI_TRAVERSE, NULL, dxpl_id)<0) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "source object not found"); - cur_obj_init=1; /* Indicate that the cur_obj struct is initialized */ - if (H5G_insert (new_loc, norm_new_name, &cur_obj, dxpl_id, NULL)<0) - HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, "unable to create new name/link for object"); + { + H5O_loc_t obj_oloc; /* Location of object to link to */ + + /* Get object location for object pointed to */ + if(H5G_obj_find(cur_loc, norm_cur_name, traverse_flags, &obj_oloc, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "source object not found") + + /* Construct link information for eventual insertion */ + lnk.type = H5G_LINK_HARD; + lnk.u.hard.addr = obj_oloc.addr; + + /* Set up user data for creating hard link */ + udata.file = obj_oloc.file; + } /* end case */ break; default: - HGOTO_ERROR (H5E_SYM, H5E_BADVALUE, FAIL, "unrecognized link type"); + HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "unrecognized link type") + } /* end switch */ + + /* Set up common link data */ +#ifdef H5_HAVE_GETTIMEOFDAY + { + struct timeval now_tv; + + HDgettimeofday(&now_tv, NULL); + lnk.ctime = now_tv.tv_sec; } +#else /* H5_HAVE_GETTIMEOFDAY */ + lnk.ctime = HDtime(NULL); +#endif /* H5_HAVE_GETTIMEOFDAY */ + lnk.cset = H5T_CSET_ASCII; /* XXX: Allow user to set this */ + /* lnk.name = name; */ /* This will be set in callback */ -done: - /* Free the group's ID to name buffer, if creating a soft link */ - if(type == H5G_LINK_SOFT) - H5G_free_ent_name(&grp_ent); + /* Set up common user data */ + udata.lnk = &lnk; + udata.dxpl_id = dxpl_id; - /* Free the ID to name buffer */ - if(cur_obj_init) - H5G_free_ent_name(&cur_obj); + /* Traverse the destination path & create new link */ + if(H5G_traverse(new_loc, norm_new_name, H5G_TARGET_NORMAL, H5G_link_cb, &udata, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "can't insert link") +done: /* Free the normalized path names */ if(norm_cur_name) H5MM_xfree(norm_cur_name); if(norm_new_name) H5MM_xfree(norm_new_name); - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_link() */ /*------------------------------------------------------------------------- - * Function: H5G_get_type - * - * Purpose: Returns the type of object pointed to by `ent'. + * Function: H5G_get_objinfo_cb * - * Return: Success: An object type defined in H5Gpublic.h + * Purpose: Callback for retrieving info about an object. This routine + * gets the info * - * Failure: H5G_UNKNOWN - * - * Programmer: Robb Matzke - * Wednesday, November 4, 1998 + * Return: Non-negative on success/Negative on failure * - * Modifications: + * Programmer: Quincey Koziol + * Tuesday, September 20, 2005 * *------------------------------------------------------------------------- */ -H5G_obj_t -H5G_get_type(H5G_entry_t *ent, hid_t dxpl_id) +static herr_t +H5G_get_objinfo_cb(H5G_loc_t *grp_loc/*in*/, const char UNUSED *name, const H5O_link_t *lnk, + H5G_loc_t *obj_loc, void *_udata/*in,out*/) { - htri_t isa; - size_t i; - H5G_obj_t ret_value=H5G_UNKNOWN; /* Return value */ - - FUNC_ENTER_NOAPI(H5G_get_type, H5G_UNKNOWN); - - for (i=H5G_ntypes_g; i>0; --i) { - if ((isa=(H5G_type_g[i-1].isa)(ent, dxpl_id))<0) { - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, H5G_UNKNOWN, "unable to determine object type"); - } else if (isa) { - HGOTO_DONE(H5G_type_g[i-1].type); - } - } - - if (0==i) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, H5G_UNKNOWN, "unable to determine object type"); - -done: - FUNC_LEAVE_NOAPI(ret_value); -} + H5G_trav_ud4_t *udata = (H5G_trav_ud4_t *)_udata; /* User data passed in */ + herr_t ret_value = SUCCEED; /* Return value */ - -/*------------------------------------------------------------------------- - * Function: H5G_get_objinfo - * - * Purpose: Returns information about an object. - * - * Return: Success: Non-negative with info about the object - * returned through STATBUF if it isn't the null - * pointer. - * - * Failure: Negative - * - * Programmer: Robb Matzke - * Monday, April 13, 1998 - * - * Modifications: - * - * Pedro Vicente, <pvn@ncsa.uiuc.edu> 18 Sep 2002 - * Added `id to name' support. - * - * John Mainzer - 6/8/05 - * Modified function to use the new dirtied parmeter of - * H5AC_unprotect(), which allows management of the is_dirty - * field of the cache info to be moved into the cache code. - * - *------------------------------------------------------------------------- - */ -herr_t -H5G_get_objinfo (H5G_entry_t *loc, const char *name, hbool_t follow_link, - H5G_stat_t *statbuf/*out*/, hid_t dxpl_id) -{ - H5G_entry_t grp_ent, obj_ent; - herr_t ret_value=SUCCEED; /* Return value */ + FUNC_ENTER_NOAPI_NOINIT(H5G_get_objinfo_cb) - FUNC_ENTER_NOAPI(H5G_get_objinfo, FAIL); + /* Check if the name in this group resolved to a valid link */ + if(lnk == NULL && obj_loc == NULL) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "name doesn't exist") - assert (loc); - assert (name && *name); - if (statbuf) HDmemset (statbuf, 0, sizeof *statbuf); + /* Only modify user's buffer if it's available */ + if(udata->statbuf) { + H5G_stat_t *statbuf = udata->statbuf; /* Convenience pointer for statbuf */ - /* Find the object's symbol table entry */ - if (H5G_namei(loc, name, NULL, &grp_ent/*out*/, &obj_ent/*out*/, - (unsigned)(follow_link?H5G_TARGET_NORMAL:H5G_TARGET_SLINK), NULL, H5G_NAMEI_TRAVERSE, NULL, dxpl_id)<0) - HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "unable to stat object"); + /* Reset buffer */ + HDmemset(statbuf, 0, sizeof(H5G_stat_t)); - /* - * Initialize the stat buf. Symbolic links aren't normal objects and - * therefore don't have much of the normal info. However, the link value - * length is specific to symbolic links. - */ - if (statbuf) { /* Common code to retrieve the file's fileno */ - if(H5F_get_fileno(obj_ent.file,&statbuf->fileno)<0) - HGOTO_ERROR (H5E_FILE, H5E_BADVALUE, FAIL, "unable to read fileno"); - - /* Retrieve information specific to each type of entry */ - if (H5G_CACHED_SLINK==obj_ent.type) { - H5O_stab_t stab_mesg; /* Symbol table message info */ - const char *s; /* Pointer to link value */ - const H5HL_t *heap; /* Pointer to local heap for group */ - - /* Named object is a symbolic link */ - if (NULL == H5O_read(&grp_ent, H5O_STAB_ID, 0, &stab_mesg, dxpl_id)) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to read symbolic link value") + /* (Use the object location's file info, if it's available) */ + if(H5F_get_fileno((obj_loc ? obj_loc : grp_loc)->oloc->file, &statbuf->fileno) < 0) + HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "unable to read fileno") + + /* Get common info from link */ + if(lnk != NULL) { + statbuf->cset = lnk->cset; + statbuf->ctime = lnk->ctime; + } /* end if */ + else { + /* lookup must be on '.' */ + HDassert(HDstrcmp(name, ".") == 0); - /* Lock the local heap */ - if (NULL == (heap = H5HL_protect(grp_ent.file, dxpl_id, stab_mesg.heap_addr))) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to read protect link value") + /* Set "fake" hard link info */ + statbuf->cset = H5T_CSET_ASCII; + statbuf->ctime = 0; + } /* end else */ - s = H5HL_offset_into(grp_ent.file, heap, obj_ent.cache.slink.lval_offset); + /* Get info for soft link */ + /* (If we don't follow the link, we can retrieve info about the soft link itself) */ + if(!udata->follow_link && lnk && lnk->type == H5G_LINK_SOFT) { + /* Set object type */ + statbuf->type = H5G_LINK; - statbuf->u.slink.linklen = HDstrlen(s) + 1; /*count the null terminator*/ + /* Get length of link value */ + statbuf->u.slink.linklen = HDstrlen(lnk->u.soft.name) + 1; /*count the null terminator*/ + } /* end if */ + /* Get info for hard link */ + else { + /* Get object type */ + statbuf->type = H5O_obj_type(obj_loc->oloc, udata->dxpl_id); + if(statbuf->type == H5G_UNKNOWN) + H5E_clear_stack(NULL); /* clear any errors resulting from checking type */ - /* Release the local heap */ - if (H5HL_unprotect(grp_ent.file, dxpl_id, heap, stab_mesg.heap_addr, H5AC__NO_FLAGS_SET) < 0) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to read unprotect link value") + /* Get basic info for object */ + statbuf->u.obj.objno = obj_loc->oloc->addr; + statbuf->u.obj.nlink = H5O_link(obj_loc->oloc, 0, udata->dxpl_id); - /* Set object type */ - statbuf->type = H5G_LINK; - } else { - /* Some other type of object */ - statbuf->u.obj.objno = obj_ent.header; - statbuf->u.obj.nlink = H5O_link (&obj_ent, 0, dxpl_id); - if (NULL==H5O_read(&obj_ent, H5O_MTIME_ID, 0, &(statbuf->u.obj.mtime), dxpl_id)) { + /* Get creation time for object */ + if(NULL == H5O_read(obj_loc->oloc, H5O_MTIME_ID, 0, &(statbuf->u.obj.mtime), udata->dxpl_id)) { H5E_clear_stack(NULL); - if (NULL==H5O_read(&obj_ent, H5O_MTIME_NEW_ID, 0, &(statbuf->u.obj.mtime), dxpl_id)) { + if(NULL == H5O_read(obj_loc->oloc, H5O_MTIME_NEW_ID, 0, &(statbuf->u.obj.mtime), udata->dxpl_id)) { H5E_clear_stack(NULL); statbuf->u.obj.mtime = 0; - } - } - /* Get object type */ - statbuf->type = H5G_get_type(&obj_ent, dxpl_id); - H5E_clear_stack(NULL); /*clear errors resulting from checking type*/ + } /* end if */ + } /* end if */ /* Get object header information */ - if(H5O_get_info(&obj_ent, &(statbuf->u.obj.ohdr), dxpl_id)<0) + if(H5O_get_info(obj_loc->oloc, &(statbuf->u.obj.ohdr), udata->dxpl_id) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get object header information") - } + } /* end else */ } /* end if */ done: - /* Free the ID to name buffers */ - H5G_free_ent_name(&grp_ent); - H5G_free_ent_name(&obj_ent); + /* Release the group location for the object */ + /* (Group traversal callbacks are responsible for either taking ownership + * of the group location for the object, or freeing it. - QAK) + */ + if(obj_loc) + H5G_loc_free(obj_loc); - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_get_objinfo_cb() */ /*------------------------------------------------------------------------- - * Function: H5G_get_num_objs + * Function: H5G_get_objinfo * - * Purpose: Private function for H5Gget_num_objs. Returns the number - * of objects in the group. It iterates all B-tree leaves - * and sum up total number of group members. + * Purpose: Returns information about an object. * - * Return: Success: Non-negative + * Return: Success: Non-negative with info about the object + * returned through STATBUF if it isn't the null + * pointer. * * Failure: Negative * - * Programmer: Raymond Lu - * Nov 20, 2002 - * - * Modifications: + * Programmer: Robb Matzke + * Monday, April 13, 1998 * *------------------------------------------------------------------------- */ -static herr_t -H5G_get_num_objs(H5G_entry_t *loc, hsize_t *num_objs, hid_t dxpl_id) +herr_t +H5G_get_objinfo(H5G_loc_t *loc, const char *name, hbool_t follow_link, + H5G_stat_t *statbuf/*out*/, hid_t dxpl_id) { - H5O_stab_t stab_mesg; /*info about B-tree */ - herr_t ret_value; - - FUNC_ENTER_NOAPI_NOINIT(H5G_get_num_objs); - - /* Sanity check */ - assert(loc); - assert(num_objs); - - /* Reset the number of objects in the group */ - *num_objs = 0; - - /* Get the B-tree info */ - if (NULL==H5O_read (loc, H5O_STAB_ID, 0, &stab_mesg, dxpl_id)) - HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "unable to determine local heap address"); - - /* Iterate over the group members */ - if ((ret_value = H5B_iterate (loc->file, dxpl_id, H5B_SNODE, - H5G_node_sumup, stab_mesg.btree_addr, num_objs))<0) - HERROR (H5E_SYM, H5E_CANTINIT, "iteration operator failed"); + H5G_trav_ud4_t udata; /* User data for callback */ + herr_t ret_value = SUCCEED; /* Return value */ -done: - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_ENTER_NOAPI(H5G_get_objinfo, FAIL) - -/*------------------------------------------------------------------------- - * Function: H5G_get_objname_by_idx - * - * Purpose: Private function for H5Gget_objname_by_idx. - * Returns the name of objects in the group by giving index. - * - * Return: Success: Non-negative - * - * Failure: Negative - * - * Programmer: Raymond Lu - * Nov 20, 2002 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static ssize_t -H5G_get_objname_by_idx(H5G_entry_t *loc, hsize_t idx, char* name, size_t size, hid_t dxpl_id) -{ - H5O_stab_t stab; /*info about local heap & B-tree */ - H5G_bt_it_ud2_t udata; /* Iteration information */ - ssize_t ret_value; /* Return value */ + HDassert(loc); + HDassert(name && *name); - FUNC_ENTER_NOAPI_NOINIT(H5G_get_objname_by_idx); + /* Set up user data for retrieving information */ + udata.statbuf = statbuf; + udata.follow_link = follow_link; + udata.dxpl_id = dxpl_id; - /* Sanity check */ - assert(loc); - - /* Get the B-tree & local heap info */ - if (NULL==H5O_read (loc, H5O_STAB_ID, 0, &stab, dxpl_id)) - HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "unable to determine local heap address"); - - /* Set iteration information */ - udata.idx = idx; - udata.num_objs = 0; - udata.heap_addr = stab.heap_addr; - udata.name = NULL; - - /* Iterate over the group members */ - if ((ret_value = H5B_iterate (loc->file, dxpl_id, H5B_SNODE, - H5G_node_name, stab.btree_addr, &udata))<0) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "iteration operator failed"); - - /* If we don't know the name now, we almost certainly went out of bounds */ - if(udata.name==NULL) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "index out of bound"); - - /* Get the length of the name */ - ret_value = (ssize_t)HDstrlen(udata.name); - - /* Copy the name into the user's buffer, if given */ - if(name) { - HDstrncpy(name, udata.name, MIN((size_t)(ret_value+1),size)); - if((size_t)ret_value >= size) - name[size-1]='\0'; - } /* end if */ + /* Traverse the group hierarchy to locate the object to get info about */ + if(H5G_traverse(loc, name, (unsigned)(follow_link ? H5G_TARGET_NORMAL : H5G_TARGET_SLINK), + H5G_get_objinfo_cb, &udata, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_EXISTS, FAIL, "name doesn't exist") done: - /* Free the duplicated name */ - if(udata.name!=NULL) - H5MM_xfree(udata.name); - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_get_objinfo() */ /*------------------------------------------------------------------------- - * Function: H5G_get_objtype_by_idx - * - * Purpose: Private function for H5Gget_objtype_by_idx. - * Returns the type of objects in the group by giving index. - * - * Return: Success: H5G_GROUP(1), H5G_DATASET(2), H5G_TYPE(3) + * Function: H5G_linkval_cb * - * Failure: UNKNOWN + * Purpose: Callback for retrieving soft link value for an object. * - * Programmer: Raymond Lu - * Nov 20, 2002 + * Return: Non-negative on success/Negative on failure * - * Modifications: + * Programmer: Quincey Koziol + * Tuesday, September 20, 2005 * *------------------------------------------------------------------------- */ -static H5G_obj_t -H5G_get_objtype_by_idx(H5G_entry_t *loc, hsize_t idx, hid_t dxpl_id) +static herr_t +H5G_linkval_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name, const H5O_link_t *lnk, + H5G_loc_t UNUSED *obj_loc, void *_udata/*in,out*/) { - H5O_stab_t stab_mesg; /*info about local heap & B-tree */ - H5G_bt_it_ud3_t udata; /* User data for B-tree callback */ - H5G_obj_t ret_value; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5G_get_objtype_by_idx); + H5G_trav_ud5_t *udata = (H5G_trav_ud5_t *)_udata; /* User data passed in */ + herr_t ret_value = SUCCEED; /* Return value */ - /* Sanity check */ - assert(loc); - - /* Get the B-tree & local heap info */ - if (NULL==H5O_read (loc, H5O_STAB_ID, 0, &stab_mesg, dxpl_id)) - HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "unable to determine local heap address"); + FUNC_ENTER_NOAPI_NOINIT(H5G_linkval_cb) - /* Set iteration information */ - udata.idx = idx; - udata.num_objs = 0; - udata.type = H5G_UNKNOWN; + /* Check if the name in this group resolved to a valid link */ + if(lnk == NULL) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "name doesn't exist") - /* Iterate over the group members */ - if (H5B_iterate (loc->file, dxpl_id, H5B_SNODE, - H5G_node_type, stab_mesg.btree_addr, &udata)<0) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "iteration operator failed"); + if(H5G_LINK_SOFT != lnk->type) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object is not a symbolic link") - /* If we don't know the type now, we almost certainly went out of bounds */ - if(udata.type==H5G_UNKNOWN) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "index out of bound"); - - ret_value = udata.type; + /* Copy to output buffer */ + if(udata->size > 0 && udata->buf) { + HDstrncpy(udata->buf, lnk->u.soft.name, udata->size); + if(HDstrlen(lnk->u.soft.name) >= udata->size) + udata->buf[udata->size - 1] = '\0'; + } /* end if */ done: - FUNC_LEAVE_NOAPI(ret_value); -} + /* Release the group location for the object */ + /* (Group traversal callbacks are responsible for either taking ownership + * of the group location for the object, or freeing it. - QAK) + */ + if(obj_loc) + H5G_loc_free(obj_loc); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_linkval_cb() */ /*------------------------------------------------------------------------- @@ -3131,65 +2373,27 @@ done: * Programmer: Robb Matzke * Monday, April 13, 1998 * - * Modifications: - * - * Pedro Vicente, <pvn@ncsa.uiuc.edu> 18 Sep 2002 - * Added `id to name' support. - * - * John Mainzer - 6/8/05 - * Modified function to use the new dirtied parmeter of - * H5AC_unprotect(), which allows management of the is_dirty - * field of the cache info to be moved into the cache code. - * *------------------------------------------------------------------------- */ static herr_t -H5G_linkval (H5G_entry_t *loc, const char *name, size_t size, char *buf/*out*/, hid_t dxpl_id) +H5G_linkval(H5G_loc_t *loc, const char *name, size_t size, char *buf/*out*/, hid_t dxpl_id) { - const char *s = NULL; - H5G_entry_t grp_ent, obj_ent; - H5O_stab_t stab_mesg; - const H5HL_t *heap; - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5G_linkval); - - /* - * Get the symbol table entry for the link head and the symbol table - * entry for the group in which the link head appears. - */ - if (H5G_namei(loc, name, NULL, &grp_ent/*out*/, &obj_ent/*out*/, - H5G_TARGET_SLINK, NULL, H5G_NAMEI_TRAVERSE, NULL, dxpl_id)<0) - HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "symbolic link was not found"); - if (H5G_CACHED_SLINK!=obj_ent.type) - HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "object is not a symbolic link"); - - /* - * Get the address of the local heap for the link value and a pointer - * into that local heap. - */ - if (NULL==H5O_read (&grp_ent, H5O_STAB_ID, 0, &stab_mesg, dxpl_id)) - HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, "unable to determine local heap address"); + H5G_trav_ud5_t udata; /* User data for callback */ + herr_t ret_value = SUCCEED; /* Return value */ - if (NULL == (heap = H5HL_protect(grp_ent.file, dxpl_id, stab_mesg.heap_addr))) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to read protect link value") + FUNC_ENTER_NOAPI_NOINIT(H5G_linkval) - s = H5HL_offset_into(grp_ent.file, heap, obj_ent.cache.slink.lval_offset); + /* Set up user data for retrieving information */ + udata.size = size; + udata.buf = buf; - /* Copy to output buffer */ - if (size>0 && buf) - HDstrncpy (buf, s, size); - - if (H5HL_unprotect(grp_ent.file, dxpl_id, heap, stab_mesg.heap_addr, H5AC__NO_FLAGS_SET) < 0) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to read unprotect link value") + /* Traverse the group hierarchy to locate the object to get info about */ + if(H5G_traverse(loc, name, H5G_TARGET_SLINK, H5G_linkval_cb, &udata, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_EXISTS, FAIL, "name doesn't exist") done: - /* Free the ID to name buffers */ - H5G_free_ent_name(&grp_ent); - H5G_free_ent_name(&obj_ent); - - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* H5G_linkval() */ /*------------------------------------------------------------------------- @@ -3202,44 +2406,36 @@ done: * Programmer: Robb Matzke * Monday, July 20, 1998 * - * Modifications: - * - * Pedro Vicente, <pvn@ncsa.uiuc.edu> 18 Sep 2002 - * Added `id to name' support. - * *------------------------------------------------------------------------- */ static herr_t -H5G_set_comment(H5G_entry_t *loc, const char *name, const char *buf, hid_t dxpl_id) +H5G_set_comment(H5G_loc_t *loc, const char *name, const char *buf, hid_t dxpl_id) { - H5G_entry_t obj_ent; + H5O_loc_t obj_oloc; /* Object's location */ H5O_name_t comment; - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5G_set_comment); + FUNC_ENTER_NOAPI_NOINIT(H5G_set_comment) /* Get the symbol table entry for the object */ - if (H5G_find(loc, name, &obj_ent/*out*/, dxpl_id)<0) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found"); + if(H5G_obj_find(loc, name, H5G_TARGET_NORMAL, &obj_oloc/*out*/, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found") /* Remove the previous comment message if any */ - if (H5O_remove(&obj_ent, H5O_NAME_ID, 0, TRUE, dxpl_id)<0) + if(H5O_remove(&obj_oloc, H5O_NAME_ID, 0, TRUE, dxpl_id) < 0) H5E_clear_stack(NULL); /* Add the new message */ - if (buf && *buf) { - comment.s = H5MM_xstrdup(buf); - if (H5O_modify(&obj_ent, H5O_NAME_ID, H5O_NEW_MESG, 0, H5O_UPDATE_TIME, &comment, dxpl_id)<0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to set comment object header message"); - H5O_reset(H5O_NAME_ID, &comment); - } + if(buf && *buf) { + /* Casting away const OK -QAK */ + comment.s = (char *)buf; + if(H5O_modify(&obj_oloc, H5O_NAME_ID, H5O_NEW_MESG, 0, H5O_UPDATE_TIME, &comment, dxpl_id) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to set comment object header message") + } /* end if */ done: - /* Free the ID to name buffer */ - H5G_free_ent_name(&obj_ent); - - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_set_comment() */ /*------------------------------------------------------------------------- @@ -3256,30 +2452,25 @@ done: * Programmer: Robb Matzke * Monday, July 20, 1998 * - * Modifications: - * - * Pedro Vicente, <pvn@ncsa.uiuc.edu> 18 Sep 2002 - * Added `id to name' support. - * *------------------------------------------------------------------------- */ static int -H5G_get_comment(H5G_entry_t *loc, const char *name, size_t bufsize, char *buf, hid_t dxpl_id) +H5G_get_comment(H5G_loc_t *loc, const char *name, size_t bufsize, char *buf, hid_t dxpl_id) { H5O_name_t comment; - H5G_entry_t obj_ent; - int ret_value; + H5O_loc_t obj_oloc; /* Object's location */ + int ret_value; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5G_get_comment); + FUNC_ENTER_NOAPI_NOINIT(H5G_get_comment) /* Get the symbol table entry for the object */ - if (H5G_find(loc, name, &obj_ent/*out*/, dxpl_id)<0) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found"); + if(H5G_obj_find(loc, name, H5G_TARGET_NORMAL, &obj_oloc/*out*/, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found") /* Get the message */ comment.s = NULL; - if (NULL==H5O_read(&obj_ent, H5O_NAME_ID, 0, &comment, dxpl_id)) { - if (buf && bufsize>0) + if(NULL == H5O_read(&obj_oloc, H5O_NAME_ID, 0, &comment, dxpl_id)) { + if(buf && bufsize > 0) buf[0] = '\0'; ret_value = 0; } else { @@ -3287,14 +2478,57 @@ H5G_get_comment(H5G_entry_t *loc, const char *name, size_t bufsize, char *buf, h HDstrncpy(buf, comment.s, bufsize); ret_value = (int)HDstrlen(comment.s); H5O_reset(H5O_NAME_ID, &comment); - } + } /* end else */ done: - /* Free the ID to name buffer */ - H5G_free_ent_name(&obj_ent); + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_get_comment() */ - FUNC_LEAVE_NOAPI(ret_value); -} + +/*------------------------------------------------------------------------- + * Function: H5G_unlink_cb + * + * Purpose: Callback for unlinking an object. This routine + * deletes the link + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Monday, September 19, 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_unlink_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t UNUSED *lnk, + H5G_loc_t *obj_loc, void *_udata/*in,out*/) +{ + H5G_trav_ud6_t *udata = (H5G_trav_ud6_t *)_udata; /* User data passed in */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5G_unlink_cb) + + /* Check if the name in this group resolved to a valid link */ + if(obj_loc == NULL) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "name doesn't exist") + + /* Check for removing '.' */ + if(lnk == NULL) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't delete self") + + /* Remove the link from the group */ + if(H5G_loc_remove(grp_loc, name, obj_loc, udata->dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to unlink name from group") + +done: + /* Release the group location for the object */ + /* (Group traversal callbacks are responsible for either taking ownership + * of the group location for the object, or freeing it. - QAK) + */ + if(obj_loc) + H5G_loc_free(obj_loc); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_unlink_cb() */ /*------------------------------------------------------------------------- @@ -3307,68 +2541,92 @@ done: * Programmer: Robb Matzke * Thursday, September 17, 1998 * - * Modifications: - * - * Pedro Vicente, <pvn@ncsa.uiuc.edu> 18 Sep 2002 - * Added `id to name' support. - * *------------------------------------------------------------------------- */ static herr_t -H5G_unlink(H5G_entry_t *loc, const char *name, hid_t dxpl_id) +H5G_unlink(H5G_loc_t *loc, const char *name, hid_t dxpl_id) { - H5G_entry_t grp_ent, obj_ent; - const char *base=NULL; + H5G_trav_ud6_t udata; /* User data for callback */ char *norm_name = NULL; /* Pointer to normalized name */ - H5G_obj_t obj_type; /* Object type */ - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5G_unlink); + FUNC_ENTER_NOAPI_NOINIT(H5G_unlink) /* Sanity check */ - assert(loc); - assert(name && *name); + HDassert(loc); + HDassert(name && *name); /* Get normalized copy of the name */ - if((norm_name=H5G_normalize(name))==NULL) - HGOTO_ERROR (H5E_SYM, H5E_BADVALUE, FAIL, "can't normalize name"); - - /* Reset the group entries to known values in a portable way */ - H5G_ent_reset(&grp_ent); - H5G_ent_reset(&obj_ent); - - /* Get the entry for the group that contains the object to be unlinked */ - if (H5G_namei(loc, norm_name, NULL, &grp_ent, &obj_ent, - H5G_TARGET_SLINK|H5G_TARGET_MOUNT, NULL, H5G_NAMEI_TRAVERSE, NULL, dxpl_id)<0) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found"); - if (!H5F_addr_defined(grp_ent.header)) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "no containing group specified"); - if (NULL==(base=H5G_basename(norm_name, NULL)) || '/'==*base) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "problems obtaining object base name"); - - /* Get object type before unlink */ - if((obj_type = H5G_get_type(&obj_ent, dxpl_id)) < 0) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't determine object type"); - - /* Remove the name from the symbol table */ - if (H5G_stab_remove(&grp_ent, base, dxpl_id)<0) - HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to unlink name from symbol table"); - - /* Search the open IDs and replace names for unlinked object */ - if (H5G_replace_name(obj_type, &obj_ent, NULL, NULL, NULL, NULL, OP_UNLINK )<0) - HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to replace name"); + if((norm_name = H5G_normalize(name)) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "can't normalize name") -done: - /* Free the ID to name buffers */ - H5G_free_ent_name(&grp_ent); - H5G_free_ent_name(&obj_ent); + /* Set up user data for creating soft link */ + udata.dxpl_id = dxpl_id; + + if(H5G_traverse(loc, norm_name, H5G_TARGET_SLINK|H5G_TARGET_MOUNT, H5G_unlink_cb, &udata, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_EXISTS, FAIL, "name doesn't exist") +done: /* Free the normalized path name */ if(norm_name) H5MM_xfree(norm_name); - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_unlink() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_move_cb + * + * Purpose: Callback for moving an object. This routine replaces the + * names of open objects with the moved object in the path + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Monday, September 19, 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_move_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name, const H5O_link_t UNUSED *lnk, + H5G_loc_t *obj_loc, void *_udata/*in,out*/) +{ + H5G_trav_ud2_t *udata = (H5G_trav_ud2_t *)_udata; /* User data passed in */ + H5RS_str_t *src_name_r = NULL; /* Ref-counted version of src name */ + H5RS_str_t *dst_name_r = NULL; /* Ref-counted version of dest name */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5G_move_cb) + + /* Check if the name in this group resolved to a valid link */ + if(obj_loc == NULL) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "name doesn't exist") + + /* Fix names up */ + src_name_r = H5RS_wrap(udata->src_name); + HDassert(src_name_r); + dst_name_r = H5RS_wrap(udata->dst_name); + HDassert(dst_name_r); + if(H5G_name_replace(udata->type, obj_loc, src_name_r, udata->src_loc, dst_name_r, udata->dst_loc, OP_MOVE) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to replace name ") + +done: + /* Cleanup */ + if(src_name_r) + H5RS_decr(src_name_r); + if(dst_name_r) + H5RS_decr(dst_name_r); + + /* Release the group location for the object */ + /* (Group traversal callbacks are responsible for either taking ownership + * of the group location for the object, or freeing it. - QAK) + */ + if(obj_loc) + H5G_loc_free(obj_loc); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_move_cb() */ /*------------------------------------------------------------------------- @@ -3381,87 +2639,102 @@ done: * Programmer: Robb Matzke * Friday, September 25, 1998 * - * Modifications: - * - * Raymond Lu - * Thursday, April 18, 2002 - * - * Pedro Vicente, <pvn@ncsa.uiuc.edu> 22 Aug 2002 - * Added `id to name' support. - * *------------------------------------------------------------------------- */ static herr_t -H5G_move(H5G_entry_t *src_loc, const char *src_name, H5G_entry_t *dst_loc, +H5G_move(H5G_loc_t *src_loc, const char *src_name, H5G_loc_t *dst_loc, const char *dst_name, hid_t dxpl_id) { - H5G_stat_t sb; - char *linkval=NULL; - size_t lv_size=32; - H5G_entry_t obj_ent; /* Object entry for object being moved */ - H5RS_str_t *src_name_r; /* Ref-counted version of src name */ - H5RS_str_t *dst_name_r; /* Ref-counted version of dest name */ - herr_t ret_value=SUCCEED; /* Return value */ + H5G_stat_t sb; /* Object info for link to move */ + H5G_trav_ud2_t udata; /* User data for traversal */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5G_move); + FUNC_ENTER_NOAPI_NOINIT(H5G_move) /* Sanity check */ - assert(src_loc); - assert(dst_loc); - assert(src_name && *src_name); - assert(dst_name && *dst_name); - - if (H5G_get_objinfo(src_loc, src_name, FALSE, &sb, dxpl_id)<0) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found"); - if (H5G_LINK==sb.type) { + HDassert(src_loc); + HDassert(dst_loc); + HDassert(src_name && *src_name); + HDassert(dst_name && *dst_name); + + if(H5G_get_objinfo(src_loc, src_name, FALSE, &sb, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found") + if(H5G_LINK == sb.type) { + char *linkval = NULL; + /* * When renaming a symbolic link we rename the link but don't change * the value of the link. */ - do { - if (NULL==(linkval=H5MM_realloc(linkval, 2*lv_size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate space for symbolic link value"); - linkval[lv_size-1] = '\0'; - if (H5G_linkval(src_loc, src_name, lv_size, linkval, dxpl_id)<0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to read symbolic link value"); - } while (linkval[lv_size-1]); - if (H5G_link(src_loc, linkval, dst_loc, dst_name, H5G_LINK_SOFT, - H5G_TARGET_NORMAL, dxpl_id)<0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to rename symbolic link"); + if(NULL == (linkval = H5MM_malloc(sb.u.slink.linklen))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate space for symbolic link value") + if(H5G_linkval(src_loc, src_name, sb.u.slink.linklen, linkval, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to read symbolic link value") + if(H5G_link(src_loc, linkval, dst_loc, dst_name, H5G_LINK_SOFT, H5G_TARGET_NORMAL, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to rename symbolic link") H5MM_xfree(linkval); - } else { /* * Rename the object. */ - if (H5G_link(src_loc, src_name, dst_loc, dst_name, H5G_LINK_HARD, - H5G_TARGET_MOUNT, dxpl_id)<0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to register new name for object"); - } + if(H5G_link(src_loc, src_name, dst_loc, dst_name, H5G_LINK_HARD, H5G_TARGET_MOUNT, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to register new name for object") + } /* end else */ + + /* Set up user data for name replacement */ + udata.type = sb.type; + udata.src_name = src_name; + udata.src_loc = src_loc; + udata.dst_name = dst_name; + udata.dst_loc = dst_loc; /* Search the open ID list and replace names for the move operation - * This has to be done here because H5G_link and H5G_unlink have - * internal object entries, and do not modify the entries list - */ - if (H5G_namei(src_loc, src_name, NULL, NULL, &obj_ent, H5G_TARGET_NORMAL|H5G_TARGET_SLINK, NULL, H5G_NAMEI_TRAVERSE, NULL, dxpl_id)) - HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "unable to follow symbolic link"); - src_name_r=H5RS_wrap(src_name); - assert(src_name_r); - dst_name_r=H5RS_wrap(dst_name); - assert(dst_name_r); - if (H5G_replace_name(sb.type, &obj_ent, src_name_r, src_loc, dst_name_r, dst_loc, OP_MOVE )<0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to replace name "); - H5RS_decr(src_name_r); - H5RS_decr(dst_name_r); - H5G_free_ent_name(&obj_ent); + */ + if(H5G_traverse(src_loc, src_name, H5G_TARGET_NORMAL|H5G_TARGET_SLINK, H5G_move_cb, &udata, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to follow symbolic link") /* Remove the old name */ - if (H5G_unlink(src_loc, src_name, dxpl_id)<0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to deregister old object name"); + if(H5G_unlink(src_loc, src_name, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to deregister old object name") done: - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_move() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_insertion_file_cb + * + * Purpose: Callback for finding insertion file. This routine sets the + * correct information for the file pointer to return. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Monday, September 19, 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_insertion_file_cb(H5G_loc_t *grp_loc/*in*/, const char UNUSED *name, const H5O_link_t UNUSED *lnk, + H5G_loc_t *obj_loc, void *_udata/*in,out*/) +{ + H5G_trav_ud1_t *udata = (H5G_trav_ud1_t *)_udata; /* User data passed in */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5G_insertion_file_cb) + + /* Check if the name in this group resolves to a valid location */ + /* (which is not what we want) */ + if(obj_loc != NULL) + HGOTO_ERROR(H5E_SYM, H5E_EXISTS, FAIL, "name already exists") + + /* Get file pointer for location */ + udata->file = grp_loc->oloc->file; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_insertion_file_cb() */ /*------------------------------------------------------------------------- @@ -3478,65 +2751,43 @@ done: * Programmer: Robb Matzke * Wednesday, October 14, 1998 * - * Modifications: - * - * Pedro Vicente, <pvn@ncsa.uiuc.edu> 18 Sep 2002 - * Added `id to name' support. - * *------------------------------------------------------------------------- */ H5F_t * -H5G_insertion_file(H5G_entry_t *loc, const char *name, hid_t dxpl_id) +H5G_insertion_file(H5G_loc_t *loc, const char *name, hid_t dxpl_id) { H5F_t *ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5G_insertion_file, NULL); + FUNC_ENTER_NOAPI(H5G_insertion_file, NULL) - assert(loc); - assert(name && *name); + HDassert(loc); + HDassert(name && *name); /* Check if the location the object will be inserted into is part of a * file mounting chain (either a parent or a child) and perform a more * rigorous determination of the location's file (which traverses into * mounted files, etc.). */ - if(H5F_has_mount(loc->file) || H5F_is_mount(loc->file)) { - const char *rest; - H5G_entry_t grp_ent; - size_t size; + if(H5F_has_mount(loc->oloc->file) || H5F_is_mount(loc->oloc->file)) { + H5G_trav_ud1_t udata; /* User data for traversal */ /* * Look up the name to get the containing group and to make sure the name * doesn't already exist. */ - if (H5G_namei(loc, name, &rest, &grp_ent, NULL, H5G_TARGET_NORMAL, NULL, H5G_NAMEI_TRAVERSE, NULL, dxpl_id)>=0) { - H5G_free_ent_name(&grp_ent); - HGOTO_ERROR(H5E_SYM, H5E_EXISTS, NULL, "name already exists"); - } /* end if */ - H5E_clear_stack(NULL); - - /* Make sure only the last component wasn't resolved */ - rest = H5G_component(rest, &size); - assert(*rest && size>0); - rest = H5G_component(rest+size, NULL); - if (*rest) { - H5G_free_ent_name(&grp_ent); - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, NULL, "insertion point not found"); - } /* end if */ + if(H5G_traverse(loc, name, H5G_TARGET_NORMAL, H5G_insertion_file_cb, &udata, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_EXISTS, NULL, "name already exists") /* Set return value */ - ret_value=grp_ent.file; - - /* Free the ID to name buffer */ - H5G_free_ent_name(&grp_ent); + ret_value = udata.file; } /* end if */ else /* Use the location's file */ - ret_value=loc->file; + ret_value = loc->oloc->file; done: - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_insertion_file() */ /*------------------------------------------------------------------------- @@ -3552,630 +2803,25 @@ done: * * Comments: Used now only on the root group close, in H5F_close() * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t H5G_free_grp_name(H5G_t *grp) { - H5G_entry_t *ent; /* Group object's entry */ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5G_free_grp_name, FAIL); - - /* Check args */ - assert(grp && grp->shared); - assert(grp->shared->fo_count > 0); - - /* Get the entry for the group */ - if (NULL==( ent = H5G_entof(grp))) - HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, "cannot get entry"); - - /* Free the entry */ - H5G_free_ent_name(ent); - -done: - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5G_free_ent_name - * - * Purpose: Free the 'ID to name' buffers. - * - * Return: Success - * - * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu - * - * Date: August 22, 2002 - * - * Comments: - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5G_free_ent_name(H5G_entry_t *ent) -{ - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5G_free_ent_name, FAIL); + FUNC_ENTER_NOAPI(H5G_free_grp_name, FAIL) /* Check args */ - assert(ent); - - if(ent->user_path_r) { - H5RS_decr(ent->user_path_r); - ent->user_path_r=NULL; - } /* end if */ - if(ent->canon_path_r) { - H5RS_decr(ent->canon_path_r); - ent->canon_path_r=NULL; - } /* end if */ - -done: - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5G_replace_name - * - * Purpose: Search the list of open IDs and replace names according to a - * particular operation. The operation occured on the LOC - * entry, which had SRC_NAME previously. The new name (if there - * is one) is DST_NAME. Additional entry location information - * (currently only needed for the 'move' operation) is passed - * in SRC_LOC and DST_LOC. - * - * Return: Success: 0, Failure: -1 - * - * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu - * - * Date: June 11, 2002 - * - * Comments: - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5G_replace_name(H5G_obj_t type, H5G_entry_t *loc, - H5RS_str_t *src_name, H5G_entry_t *src_loc, - H5RS_str_t *dst_name, H5G_entry_t *dst_loc, H5G_names_op_t op ) -{ - H5G_names_t names; /* Structure to hold operation information for callback */ - unsigned search_group=0; /* Flag to indicate that groups are to be searched */ - unsigned search_dataset=0; /* Flag to indicate that datasets are to be searched */ - unsigned search_datatype=0; /* Flag to indicate that datatypes are to be searched */ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI(H5G_replace_name, FAIL); - - /* Set up common information for callback */ - names.src_name=src_name; - names.dst_name=dst_name; - names.loc=loc; - names.src_loc=src_loc; - names.dst_loc=dst_loc; - names.op=op; - - /* Determine which types of IDs need to be operated on */ - switch(type) { - /* Object is a group */ - case H5G_GROUP: - /* Search and replace names through group IDs */ - search_group=1; - break; - - /* Object is a dataset */ - case H5G_DATASET: - /* Search and replace names through dataset IDs */ - search_dataset=1; - break; - - /* Object is a named datatype */ - case H5G_TYPE: - /* Search and replace names through datatype IDs */ - search_datatype=1; - break; - - case H5G_UNKNOWN: /* We pass H5G_UNKNOWN as object type when we need to search all IDs */ - case H5G_LINK: /* Symbolic links might resolve to any object, so we need to search all IDs */ - /* Check if we will need to search groups */ - if(H5I_nmembers(H5I_GROUP)>0) - search_group=1; - - /* Check if we will need to search datasets */ - if(H5I_nmembers(H5I_DATASET)>0) - search_dataset=1; - - /* Check if we will need to search datatypes */ - if(H5I_nmembers(H5I_DATATYPE)>0) - search_datatype=1; - break; - - default: - HGOTO_ERROR (H5E_DATATYPE, H5E_BADTYPE, FAIL, "not valid object type"); - } /* end switch */ - - /* Search through group IDs */ - if(search_group) - H5I_search(H5I_GROUP, H5G_replace_ent, &names); - - /* Search through dataset IDs */ - if(search_dataset) - H5I_search(H5I_DATASET, H5G_replace_ent, &names); - - /* Search through datatype IDs */ - if(search_datatype) - H5I_search(H5I_DATATYPE, H5G_replace_ent, &names); - -done: - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5G_common_path - * - * Purpose: Determine if one path is a valid prefix of another path - * - * Return: TRUE for valid prefix, FALSE for not a valid prefix, FAIL - * on error - * - * Programmer: Quincey Koziol, koziol@ncsa.uiuc.edu - * - * Date: September 24, 2002 - * - * Comments: - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static htri_t -H5G_common_path(const H5RS_str_t *fullpath_r, const H5RS_str_t *prefix_r) -{ - const char *fullpath; /* Pointer to actual fullpath string */ - const char *prefix; /* Pointer to actual prefix string */ - size_t nchars1,nchars2; /* Number of characters in components */ - htri_t ret_value=FALSE; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_common_path); - - /* Get component of each name */ - fullpath=H5RS_get_str(fullpath_r); - assert(fullpath); - fullpath=H5G_component(fullpath,&nchars1); - assert(fullpath); - prefix=H5RS_get_str(prefix_r); - assert(prefix); - prefix=H5G_component(prefix,&nchars2); - assert(prefix); - - /* Check if we have a real string for each component */ - while(*fullpath && *prefix) { - /* Check that the components we found are the same length */ - if(nchars1==nchars2) { - /* Check that the two components are equal */ - if(HDstrncmp(fullpath,prefix,nchars1)==0) { - /* Advance the pointers in the names */ - fullpath+=nchars1; - prefix+=nchars2; - - /* Get next component of each name */ - fullpath=H5G_component(fullpath,&nchars1); - assert(fullpath); - prefix=H5G_component(prefix,&nchars2); - assert(prefix); - } /* end if */ - else - HGOTO_DONE(FALSE); - } /* end if */ - else - HGOTO_DONE(FALSE); - } /* end while */ - - /* If we reached the end of the prefix path to check, it must be a valid prefix */ - if(*prefix=='\0') - ret_value=TRUE; - -done: - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5G_build_fullpath - * - * Purpose: Build a full path from a prefix & base pair of reference counted - * strings - * - * Return: Pointer to reference counted string on success, NULL on error - * - * Programmer: Quincey Koziol, koziol@ncsa.uiuc.edu - * - * Date: August 19, 2005 - * - * Comments: - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static H5RS_str_t * -H5G_build_fullpath(const H5RS_str_t *prefix_r, const H5RS_str_t *name_r) -{ - const char *prefix; /* Pointer to raw string of prefix */ - const char *name; /* Pointer to raw string of name */ - char *full_path; /* Full user path built */ - size_t path_len; /* Length of the path */ - unsigned need_sep; /* Flag to indicate if separator is needed */ - H5RS_str_t *ret_value; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5G_build_fullpath) - - /* Get the pointer to the prefix */ - prefix=H5RS_get_str(prefix_r); - - /* Get the length of the prefix */ - path_len=HDstrlen(prefix); - - /* Determine if there is a trailing separator in the name */ - if(prefix[path_len-1]=='/') - need_sep=0; - else - need_sep=1; - - /* Get the pointer to the raw src user path */ - name=H5RS_get_str(name_r); - - /* Add in the length needed for the '/' separator and the relative path */ - path_len+=HDstrlen(name)+need_sep; - - /* Allocate space for the path */ - if(NULL==(full_path = H5FL_BLK_MALLOC(str_buf,path_len+1))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - - /* Build full path */ - HDstrcpy(full_path,prefix); - if(need_sep) - HDstrcat(full_path,"/"); - HDstrcat(full_path,name); - - /* Create reference counted string for path */ - ret_value=H5RS_own(full_path); - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5G_build_fullpath() */ - - -/*------------------------------------------------------------------------- - * Function: H5G_replace_ent - * - * Purpose: H5I_search callback function to replace group entry names - * - * Return: Success: 0, Failure: -1 - * - * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu - * - * Date: June 5, 2002 - * - * Comments: - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static int -H5G_replace_ent(void *obj_ptr, hid_t obj_id, void *key) -{ - const H5G_names_t *names = (const H5G_names_t *)key; /* Get operation's information */ - H5G_entry_t *ent = NULL; /* Group entry for object that the ID refers to */ - H5F_t *top_ent_file; /* Top file in entry's mounted file chain */ - H5F_t *top_loc_file; /* Top file in location's mounted file chain */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5G_replace_ent); - - assert(obj_ptr); - - /* Get the symbol table entry */ - switch(H5I_get_type(obj_id)) { - case H5I_GROUP: - ent = H5G_entof((H5G_t*)obj_ptr); - break; - - case H5I_DATASET: - ent = H5D_entof((H5D_t*)obj_ptr); - break; - - case H5I_DATATYPE: - /* Avoid non-named datatypes */ - if(!H5T_is_named((H5T_t*)obj_ptr)) - HGOTO_DONE(SUCCEED); /* Do not exit search over IDs */ - - ent = H5T_entof((H5T_t*)obj_ptr); - break; - - default: - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "unknown data object"); - } /* end switch */ - assert(ent); - - switch(names->op) { - /*------------------------------------------------------------------------- - * OP_MOUNT - *------------------------------------------------------------------------- - */ - case OP_MOUNT: - if(ent->user_path_r) { - if(ent->file->mtab.parent && H5RS_cmp(ent->user_path_r,ent->canon_path_r)) { - /* Find the "top" file in the chain of mounted files */ - top_ent_file=ent->file->mtab.parent; - while(top_ent_file->mtab.parent!=NULL) - top_ent_file=top_ent_file->mtab.parent; - } /* end if */ - else - top_ent_file=ent->file; - - /* Check for entry being in correct file (or mounted file) */ - if(top_ent_file->shared == names->loc->file->shared) { - /* Check if the source is along the entry's path */ - /* (But not actually the entry itself) */ - if(H5G_common_path(ent->user_path_r,names->src_name) && - H5RS_cmp(ent->user_path_r,names->src_name)!=0) { - /* Hide the user path */ - ent->user_path_hidden++; - } /* end if */ - } /* end if */ - } /* end if */ - break; - - /*------------------------------------------------------------------------- - * OP_UNMOUNT - *------------------------------------------------------------------------- - */ - case OP_UNMOUNT: - if(ent->user_path_r) { - if(ent->file->mtab.parent) { - /* Find the "top" file in the chain of mounted files for the entry */ - top_ent_file=ent->file->mtab.parent; - while(top_ent_file->mtab.parent!=NULL) - top_ent_file=top_ent_file->mtab.parent; - } /* end if */ - else - top_ent_file=ent->file; - - if(names->loc->file->mtab.parent) { - /* Find the "top" file in the chain of mounted files for the location */ - top_loc_file=names->loc->file->mtab.parent; - while(top_loc_file->mtab.parent!=NULL) - top_loc_file=top_loc_file->mtab.parent; - } /* end if */ - else - top_loc_file=names->loc->file; - - /* If the ID's entry is not in the file we operated on, skip it */ - if(top_ent_file->shared == top_loc_file->shared) { - if(ent->user_path_hidden) { - if(H5G_common_path(ent->user_path_r,names->src_name)) { - /* Un-hide the user path */ - ent->user_path_hidden--; - } /* end if */ - } /* end if */ - else { - if(H5G_common_path(ent->user_path_r,names->src_name)) { - /* Free user path */ - H5RS_decr(ent->user_path_r); - ent->user_path_r=NULL; - } /* end if */ - } /* end else */ - } /* end if */ - } /* end if */ - break; - - /*------------------------------------------------------------------------- - * OP_UNLINK - *------------------------------------------------------------------------- - */ - case OP_UNLINK: - /* If the ID's entry is not in the file we operated on, skip it */ - if(ent->file->shared == names->loc->file->shared && - names->loc->canon_path_r && ent->canon_path_r && ent->user_path_r) { - /* Check if we are referring to the same object */ - if(H5F_addr_eq(ent->header, names->loc->header)) { - /* Check if the object was opened with the same canonical path as the one being moved */ - if(H5RS_cmp(ent->canon_path_r,names->loc->canon_path_r)==0) { - /* Free user path */ - H5RS_decr(ent->user_path_r); - ent->user_path_r=NULL; - } /* end if */ - } /* end if */ - else { - /* Check if the location being unlinked is in the canonical path for the current object */ - if(H5G_common_path(ent->canon_path_r,names->loc->canon_path_r)) { - /* Free user path */ - H5RS_decr(ent->user_path_r); - ent->user_path_r=NULL; - } /* end if */ - } /* end else */ - } /* end if */ - break; - - /*------------------------------------------------------------------------- - * OP_MOVE - *------------------------------------------------------------------------- - */ - case OP_MOVE: /* H5Gmove case, check for relative names case */ - /* If the ID's entry is not in the file we operated on, skip it */ - if(ent->file->shared == names->loc->file->shared) { - if(ent->user_path_r && names->loc->user_path_r && - names->src_loc->user_path_r && names->dst_loc->user_path_r) { - H5RS_str_t *src_path_r; /* Full user path of source name */ - H5RS_str_t *dst_path_r; /* Full user path of destination name */ - H5RS_str_t *canon_src_path_r; /* Copy of canonical part of source path */ - H5RS_str_t *canon_dst_path_r; /* Copy of canonical part of destination path */ - - /* Sanity check */ - HDassert(names->src_name); - HDassert(names->dst_name); - - /* Make certain that the source and destination names are full (not relative) paths */ - if(*(H5RS_get_str(names->src_name))!='/') { - /* Create reference counted string for full src path */ - if((src_path_r = H5G_build_fullpath(names->src_loc->user_path_r, names->src_name)) == NULL) - HGOTO_ERROR (H5E_SYM, H5E_PATH, FAIL, "can't build source path name") - } /* end if */ - else - src_path_r=H5RS_dup(names->src_name); - if(*(H5RS_get_str(names->dst_name))!='/') { - /* Create reference counted string for full dst path */ - if((dst_path_r = H5G_build_fullpath(names->dst_loc->user_path_r, names->dst_name)) == NULL) - HGOTO_ERROR (H5E_SYM, H5E_PATH, FAIL, "can't build destination path name") - } /* end if */ - else - dst_path_r=H5RS_dup(names->dst_name); - - /* Get the canonical parts of the source and destination names */ - - /* Check if the object being moved was accessed through a mounted file */ - if(H5RS_cmp(names->loc->user_path_r,names->loc->canon_path_r)!=0) { - size_t non_canon_name_len; /* Length of non-canonical part of name */ - - /* Get current string lengths */ - non_canon_name_len=H5RS_len(names->loc->user_path_r)-H5RS_len(names->loc->canon_path_r); - - canon_src_path_r=H5RS_create(H5RS_get_str(src_path_r)+non_canon_name_len); - canon_dst_path_r=H5RS_create(H5RS_get_str(dst_path_r)+non_canon_name_len); - } /* end if */ - else { - canon_src_path_r=H5RS_dup(src_path_r); - canon_dst_path_r=H5RS_dup(dst_path_r); - } /* end else */ - - /* Check if the link being changed in the file is along the canonical path for this object */ - if(H5G_common_path(ent->canon_path_r,canon_src_path_r)) { - size_t user_dst_len; /* Length of destination user path */ - size_t canon_dst_len; /* Length of destination canonical path */ - const char *old_user_path; /* Pointer to previous user path */ - char *new_user_path; /* Pointer to new user path */ - char *new_canon_path; /* Pointer to new canonical path */ - const char *tail_path; /* Pointer to "tail" of path */ - size_t tail_len; /* Pointer to "tail" of path */ - char *src_canon_prefix; /* Pointer to source canonical path prefix of component which is moving */ - size_t src_canon_prefix_len;/* Length of the source canonical path prefix */ - char *dst_canon_prefix; /* Pointer to destination canonical path prefix of component which is moving */ - size_t dst_canon_prefix_len;/* Length of the destination canonical path prefix */ - char *user_prefix; /* Pointer to user path prefix of component which is moving */ - size_t user_prefix_len; /* Length of the user path prefix */ - char *src_comp; /* The source name of the component which is actually changing */ - char *dst_comp; /* The destination name of the component which is actually changing */ - const char *canon_src_path; /* pointer to canonical part of source path */ - const char *canon_dst_path; /* pointer to canonical part of destination path */ - - /* Get the pointers to the raw strings */ - canon_src_path=H5RS_get_str(canon_src_path_r); - canon_dst_path=H5RS_get_str(canon_dst_path_r); - - /* Get the source & destination components */ - src_comp=HDstrrchr(canon_src_path,'/'); - assert(src_comp); - dst_comp=HDstrrchr(canon_dst_path,'/'); - assert(dst_comp); - - /* Find the canonical prefixes for the entry */ - src_canon_prefix_len=HDstrlen(canon_src_path)-HDstrlen(src_comp); - if(NULL==(src_canon_prefix = H5MM_malloc(src_canon_prefix_len+1))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - HDstrncpy(src_canon_prefix,canon_src_path,src_canon_prefix_len); - src_canon_prefix[src_canon_prefix_len]='\0'; - - dst_canon_prefix_len=HDstrlen(canon_dst_path)-HDstrlen(dst_comp); - if(NULL==(dst_canon_prefix = H5MM_malloc(dst_canon_prefix_len+1))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - HDstrncpy(dst_canon_prefix,canon_dst_path,dst_canon_prefix_len); - dst_canon_prefix[dst_canon_prefix_len]='\0'; - - /* Hold this for later use */ - old_user_path=H5RS_get_str(ent->user_path_r); - - /* Find the user prefix for the entry */ - user_prefix_len=HDstrlen(old_user_path)-H5RS_len(ent->canon_path_r); - if(NULL==(user_prefix = H5MM_malloc(user_prefix_len+1))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - HDstrncpy(user_prefix,old_user_path,user_prefix_len); - user_prefix[user_prefix_len]='\0'; - - /* Set the tail path info */ - tail_path=old_user_path+user_prefix_len+src_canon_prefix_len+HDstrlen(src_comp); - tail_len=HDstrlen(tail_path); - - /* Get the length of the destination paths */ - user_dst_len=user_prefix_len+dst_canon_prefix_len+HDstrlen(dst_comp)+tail_len; - canon_dst_len=dst_canon_prefix_len+HDstrlen(dst_comp)+tail_len; - - /* Allocate space for the new user path */ - if(NULL==(new_user_path = H5FL_BLK_MALLOC(str_buf,user_dst_len+1))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - - /* Allocate space for the new canonical path */ - if(NULL==(new_canon_path = H5FL_BLK_MALLOC(str_buf,canon_dst_len+1))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - - /* Create the new names */ - HDstrcpy(new_user_path,user_prefix); - HDstrcat(new_user_path,dst_canon_prefix); - HDstrcat(new_user_path,dst_comp); - HDstrcat(new_user_path,tail_path); - HDstrcpy(new_canon_path,dst_canon_prefix); - HDstrcat(new_canon_path,dst_comp); - HDstrcat(new_canon_path,tail_path); - - /* Release the old user & canonical paths */ - H5RS_decr(ent->user_path_r); - H5RS_decr(ent->canon_path_r); - - /* Take ownership of the new user & canonical paths */ - ent->user_path_r=H5RS_own(new_user_path); - ent->canon_path_r=H5RS_own(new_canon_path); - - /* Free the extra paths allocated */ - H5MM_xfree(src_canon_prefix); - H5MM_xfree(dst_canon_prefix); - H5MM_xfree(user_prefix); - } /* end if */ - - - /* Free the extra paths allocated */ - H5RS_decr(src_path_r); - H5RS_decr(dst_path_r); - H5RS_decr(canon_src_path_r); - H5RS_decr(canon_dst_path_r); - } /* end if */ - else { - /* Release the old user path */ - if(ent->user_path_r) { - H5RS_decr(ent->user_path_r); - ent->user_path_r = NULL; - } /* end if */ - } /* end else */ - } /* end if */ - break; + HDassert(grp && grp->shared); + HDassert(grp->shared->fo_count > 0); - default: - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid call"); - } /* end switch */ + /* Free the path */ + H5G_name_free(&(grp->path)); done: - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_free_grp_name() */ /*------------------------------------------------------------------------- @@ -4279,44 +2925,49 @@ H5G_unmount(H5G_t *grp) *------------------------------------------------------------------------- */ static herr_t -H5G_copy(H5G_entry_t *ent_src, H5G_entry_t *loc_dst, +H5G_copy(H5G_loc_t *src_loc, H5G_loc_t *dst_loc, const char *name_dst, hid_t plist_id) { H5P_genplist_t *oc_plist; /* Property list created */ hid_t dxpl_id = H5AC_dxpl_id; - H5G_entry_t ent_new; + H5G_name_t new_path; /* Copied object group hier. path */ + H5O_loc_t new_oloc; /* Copied object object location */ + H5G_loc_t new_loc; /* Group location of object copied */ hbool_t entry_inserted = FALSE; /* Flag to indicate that the new entry was inserted into a group */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5G_copy, FAIL); - HDassert(ent_src); - HDassert(ent_src->file); - HDassert(loc_dst); - HDassert(loc_dst->file); + HDassert(src_loc); + HDassert(src_loc->oloc->file); + HDassert(dst_loc); + HDassert(dst_loc->oloc->file); HDassert(name_dst); /* Get the property list */ if(NULL == (oc_plist = H5I_object(plist_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list") - /* Reset group entry for new object */ - H5G_ent_reset(&ent_new); - ent_new.file = loc_dst->file; + /* Set up copied object location to fill in */ + new_loc.oloc = &new_oloc; + new_loc.path = &new_path; + H5G_loc_reset(&new_loc); + new_oloc.file = dst_loc->oloc->file; /* copy the object from the source file to the destination file */ - if(H5O_copy_header(ent_src, &ent_new, dxpl_id) < 0) + if(H5O_copy_header(src_loc->oloc, &new_oloc, dxpl_id) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object") /* Insert the new object in the destination file's group */ - if(H5G_insert(loc_dst, name_dst, &ent_new, dxpl_id, oc_plist) < 0) + if(H5G_insert(dst_loc, name_dst, &new_loc, dxpl_id, oc_plist) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to insert the name") entry_inserted = TRUE; done: /* Free the ID to name buffers */ if(entry_inserted) - H5G_free_ent_name(&ent_new); + H5G_loc_free(&new_loc); FUNC_LEAVE_NOAPI(ret_value) } /* end H5G_copy() */ + diff --git a/src/H5Gent.c b/src/H5Gent.c index 52729c6..08f7e77 100644 --- a/src/H5Gent.c +++ b/src/H5Gent.c @@ -27,56 +27,24 @@ #include "H5FLprivate.h" /* Free Lists */ #include "H5Gpkg.h" /* Groups */ #include "H5HLprivate.h" /* Local Heaps */ +#include "H5Iprivate.h" /* IDs */ + +/* Private macros */ +#define H5G_NO_CHANGE (-1) /*see H5G_ent_modified() */ /* Private prototypes */ #ifdef NOT_YET static herr_t H5G_ent_modified(H5G_entry_t *ent, H5G_type_t cache_type); #endif /* NOT_YET */ +static herr_t H5G_ent_encode(H5F_t *f, uint8_t **pp, const H5G_entry_t *ent); +static herr_t H5G_ent_decode(H5F_t *f, const uint8_t **pp, + H5G_entry_t *ent/*out*/); /* Declare extern the PQ free list for the wrapped strings */ H5FL_BLK_EXTERN(str_buf); /*------------------------------------------------------------------------- - * Function: H5G_ent_cache - * - * Purpose: Returns a pointer to the cache associated with the symbol - * table entry. You should modify the cache directly, then call - * H5G_ent_modified() with the new cache type (even if the type is - * still the same). - * - * Return: Success: Ptr to the cache in the symbol table entry. - * - * Failure: NULL - * - * Programmer: Robb Matzke - * Friday, September 19, 1997 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -const H5G_cache_t * -H5G_ent_cache(const H5G_entry_t *ent, H5G_type_t *cache_type) -{ - const H5G_cache_t *ret_value; /* Return value */ - - FUNC_ENTER_NOAPI(H5G_ent_cache, NULL); - - if (!ent) - HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, NULL, "no entry"); - if (cache_type) - *cache_type = ent->type; - - /* Set return value */ - ret_value=(const H5G_cache_t *)&(ent->cache); - -done: - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- * Function: H5G_ent_modified * * Purpose: This function should be called after you make any @@ -94,8 +62,7 @@ done: * *------------------------------------------------------------------------- */ -#ifdef NOT_YET -static herr_t +herr_t H5G_ent_modified(H5G_entry_t *ent, H5G_type_t cache_type) { FUNC_ENTER_NOAPI_NOFUNC(H5G_ent_modified) @@ -109,7 +76,6 @@ H5G_ent_modified(H5G_entry_t *ent, H5G_type_t cache_type) FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5G_ent_modified */ -#endif /* NOT_YET */ /*------------------------------------------------------------------------- @@ -179,18 +145,18 @@ done: * *------------------------------------------------------------------------- */ -herr_t +static herr_t H5G_ent_decode(H5F_t *f, const uint8_t **pp, H5G_entry_t *ent) { const uint8_t *p_ret = *pp; uint32_t tmp; - FUNC_ENTER_NOAPI_NOFUNC(H5G_ent_decode); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_ent_decode) /* check arguments */ - assert(f); - assert(pp); - assert(ent); + HDassert(f); + HDassert(pp); + HDassert(ent); ent->file = f; @@ -222,8 +188,8 @@ H5G_ent_decode(H5F_t *f, const uint8_t **pp, H5G_entry_t *ent) *pp = p_ret + H5G_SIZEOF_ENTRY(f); - FUNC_LEAVE_NOAPI(SUCCEED); -} + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5G_ent_decode() */ /*------------------------------------------------------------------------- @@ -296,12 +262,12 @@ done: * *------------------------------------------------------------------------- */ -herr_t +static herr_t H5G_ent_encode(H5F_t *f, uint8_t **pp, const H5G_entry_t *ent) { uint8_t *p_ret = *pp + H5G_SIZEOF_ENTRY(f); - FUNC_ENTER_NOAPI_NOFUNC(H5G_ent_encode); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_ent_encode); /* check arguments */ assert(f); @@ -348,31 +314,19 @@ H5G_ent_encode(H5F_t *f, uint8_t **pp, const H5G_entry_t *ent) /*------------------------------------------------------------------------- - * Function: H5G_ent_copy - * - * Purpose: Do a deep copy of symbol table entries + * Function: H5G_ent_copy * - * Return: Success: 0, Failure: -1 + * Purpose: Do a deep copy of symbol table entries * - * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * Return: Success: Non-negative + * Failure: Negative * - * Date: August 2002 + * Programmer: Pedro Vicente + * pvn@ncsa.uiuc.edu + * ???day, August ??, 2002 * - * Comments: - * - * Modifications: - * Quincey Koziol, Sept. 25, 2002: - * - Changed source & destination parameters to match the rest - * of the functions in the library. - * - Added 'depth' parameter to determine how much of the group - * entry structure we want to copy. The new depths are: - * H5G_COPY_NULL - Copy all the fields from the - * source to the destination, but set the destination's - * user path and canonical path to NULL. - * H5G_COPY_LIMITED - Copy all the fields from the - * source to the destination, except for the user path - * field, keeping it the same as its - * previous value in the destination. + * Notes: 'depth' parameter determines how much of the group entry + * structure we want to copy. The values are: * H5G_COPY_SHALLOW - Copy all the fields from the source * to the destination, including the user path and * canonical path. (Destination "takes ownership" of @@ -384,68 +338,48 @@ H5G_ent_encode(H5F_t *f, uint8_t **pp, const H5G_entry_t *ent) *------------------------------------------------------------------------- */ herr_t -H5G_ent_copy(H5G_entry_t *dst, const H5G_entry_t *src, H5G_ent_copy_depth_t depth) +H5G_ent_copy(H5G_entry_t *dst, const H5G_entry_t *src, H5G_copy_depth_t depth) { - H5RS_str_t *tmp_user_path_r=NULL; /* Temporary string pointer for entry's user path */ - - FUNC_ENTER_NOAPI_NOFUNC(H5G_ent_copy); + FUNC_ENTER_NOAPI_NOFUNC(H5G_ent_copy) /* Check arguments */ - assert(src); - assert(dst); - - /* If the depth is "very shallow", keep the old entry's user path */ - if(depth==H5G_COPY_LIMITED) { - tmp_user_path_r=dst->user_path_r; - if(dst->canon_path_r) - H5RS_decr(dst->canon_path_r); - } /* end if */ + HDassert(src); + HDassert(dst); + HDassert(depth == H5G_COPY_SHALLOW || depth == H5G_COPY_DEEP); /* Copy the top level information */ - HDmemcpy(dst,src,sizeof(H5G_entry_t)); + HDmemcpy(dst, src, sizeof(H5G_entry_t)); /* Deep copy the names */ - if(depth==H5G_COPY_DEEP) { - dst->user_path_r=H5RS_dup(src->user_path_r); - dst->canon_path_r=H5RS_dup(src->canon_path_r); - } else if(depth==H5G_COPY_LIMITED) { - dst->user_path_r=tmp_user_path_r; - dst->canon_path_r=H5RS_dup(src->canon_path_r); - } else if(depth==H5G_COPY_NULL) { - dst->user_path_r=NULL; - dst->canon_path_r=NULL; - } else if(depth==H5G_COPY_SHALLOW) { -#ifndef NDEBUG + if(depth == H5G_COPY_DEEP) { + /* Nothing currently */ + ; + } else if(depth == H5G_COPY_SHALLOW) { /* Discarding 'const' qualifier OK - QAK */ H5G_ent_reset((H5G_entry_t *)src); -#endif /* NDEBUG */ } /* end if */ - FUNC_LEAVE_NOAPI(SUCCEED); -} + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5G_ent_copy() */ /*------------------------------------------------------------------------- - * Function: H5G_ent_reset - * - * Purpose: Reset a symbol table entry to an empty state - * - * Return: Success: 0, Failure: -1 + * Function: H5G_ent_reset * - * Programmer: Quincey Koziol, koziol@ncsa.uiuc.edu + * Purpose: Reset a symbol table entry to an empty state * - * Date: August 2005 + * Return: Success: Non-negative + * Failure: Negative * - * Comments: - * - * Modifications: + * Programmer: Quincey Koziol + * ?day, August ??, 2005 * *------------------------------------------------------------------------- */ herr_t H5G_ent_reset(H5G_entry_t *ent) { - FUNC_ENTER_NOAPI_NOFUNC(H5G_ent_reset); + FUNC_ENTER_NOAPI_NOFUNC(H5G_ent_reset) /* Check arguments */ HDassert(ent); @@ -454,126 +388,83 @@ H5G_ent_reset(H5G_entry_t *ent) HDmemset(ent, 0, sizeof(H5G_entry_t)); ent->header = HADDR_UNDEF; - FUNC_LEAVE_NOAPI(SUCCEED); + FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5G_ent_reset() */ /*------------------------------------------------------------------------- - * Function: H5G_ent_set_name + * Function: H5G_ent_convert * - * Purpose: Set the name of a symbol entry OBJ, located at LOC + * Purpose: Convert a link to a symbol table entry * - * Return: Success: 0, Failure: -1 + * Return: Success: Non-negative, with *pp pointing to the first byte + * after the last symbol. * - * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * Failure: Negative * - * Date: August 22, 2002 + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Sep 20 2005 * *------------------------------------------------------------------------- */ herr_t -H5G_ent_set_name(H5G_entry_t *loc, H5G_entry_t *obj, const char *name) +H5G_ent_convert(H5F_t *f, haddr_t heap_addr, const char *name, const H5O_link_t *lnk, + H5G_entry_t *ent, hid_t dxpl_id) { - size_t name_len; /* Length of name to append */ - herr_t ret_value = SUCCEED; + size_t name_offset; /* Offset of name in heap */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5G_ent_set_name, FAIL) + FUNC_ENTER_NOAPI(H5G_ent_convert, FAIL) - assert(loc); - assert(obj); - assert(name); + /* check arguments */ + HDassert(f); + HDassert(H5F_addr_defined(heap_addr)); + HDassert(name); + HDassert(lnk); + + /* Reset the new entry */ + H5G_ent_reset(ent); + + /* + * Add the new name to the heap. + */ + name_offset = H5HL_insert(f, dxpl_id, heap_addr, HDstrlen(name) + 1, name); + if(0 == name_offset || (size_t)(-1) == name_offset) + HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, H5B_INS_ERROR, "unable to insert symbol name into heap") + ent->name_off = name_offset; + + /* Build correct information for symbol table entry based on link type */ + switch(lnk->type) { + case H5G_LINK_HARD: + ent->type = H5G_NOTHING_CACHED; + ent->header = lnk->u.hard.addr; + break; - /* Reset the object's previous names, if they exist */ - if(obj->user_path_r) { - H5RS_decr(obj->user_path_r); - obj->user_path_r=NULL; - } /* end if */ - if(obj->canon_path_r) { - H5RS_decr(obj->canon_path_r); - obj->canon_path_r=NULL; - } /* end if */ - obj->user_path_hidden=0; - - /* Get the length of the new name */ - name_len = HDstrlen(name); - - /* Modify the object's user path, if a user path exists in the location */ - if(loc->user_path_r) { - const char *loc_user_path; /* Pointer to raw string for user path */ - size_t user_path_len; /* Length of location's user path name */ - char *new_user_path; /* Pointer to new user path */ - - /* Get the length of the strings involved */ - user_path_len = H5RS_len(loc->user_path_r); - - /* Modify the object's user path */ - - /* Get the raw string for the user path */ - loc_user_path=H5RS_get_str(loc->user_path_r); - assert(loc_user_path); - - /* The location's user path already ends in a '/' separator */ - if ('/'==loc_user_path[user_path_len-1]) { - if (NULL==(new_user_path = H5FL_BLK_MALLOC(str_buf,user_path_len+name_len+1))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") - HDstrcpy(new_user_path, loc_user_path); - } /* end if */ - /* The location's user path needs a separator */ - else { - if (NULL==(new_user_path = H5FL_BLK_MALLOC(str_buf,user_path_len+1+name_len+1))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") - HDstrcpy(new_user_path, loc_user_path); - HDstrcat(new_user_path, "/"); - } /* end else */ - - /* Append the component's name */ - HDstrcat(new_user_path, name); - - /* Give ownership of the user path to the entry */ - obj->user_path_r=H5RS_own(new_user_path); - assert(obj->user_path_r); - } /* end if */ + case H5G_LINK_SOFT: + { + size_t lnk_offset; /* Offset to sym-link value */ - /* Modify the object's canonical path, if a canonical path exists in the location */ - if(loc->canon_path_r) { - const char *loc_canon_path; /* Pointer to raw string for canonical path */ - size_t canon_path_len; /* Length of location's canonical path name */ - char *new_canon_path; /* Pointer to new canonical path */ - - /* Get the length of the strings involved */ - canon_path_len = H5RS_len(loc->canon_path_r); - - /* Modify the object's canonical path */ - - /* Get the raw string for the canonical path */ - loc_canon_path=H5RS_get_str(loc->canon_path_r); - assert(loc_canon_path); - - /* The location's canonical path already ends in a '/' separator */ - if ('/'==loc_canon_path[canon_path_len-1]) { - if (NULL==(new_canon_path = H5FL_BLK_MALLOC(str_buf,canon_path_len+name_len+1))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") - HDstrcpy(new_canon_path, loc_canon_path); - } /* end if */ - /* The location's canonical path needs a separator */ - else { - if (NULL==(new_canon_path = H5FL_BLK_MALLOC(str_buf,canon_path_len+1+name_len+1))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") - HDstrcpy(new_canon_path, loc_canon_path); - HDstrcat(new_canon_path, "/"); - } /* end else */ - - /* Append the component's name */ - HDstrcat(new_canon_path, name); - - /* Give ownership of the canonical path to the entry */ - obj->canon_path_r=H5RS_own(new_canon_path); - assert(obj->canon_path_r); - } /* end if */ + /* Insert link value into local heap */ + if((size_t)(-1) == (lnk_offset = H5HL_insert(f, dxpl_id, heap_addr, + HDstrlen(lnk->u.soft.name) + 1, lnk->u.soft.name))) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to write link value to local heap") + + ent->type = H5G_CACHED_SLINK; + ent->cache.slink.lval_offset = lnk_offset; + } /* end case */ + break; + + default: + HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "unrecognized link type") + } /* end switch */ + + /* Set the file for the entry */ + ent->file = f; done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5G_ent_set_name() */ +} /* end H5G_ent_convert() */ /*------------------------------------------------------------------------- @@ -581,17 +472,12 @@ done: * * Purpose: Prints debugging information about a symbol table entry. * - * Errors: - * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * matzke@llnl.gov * Aug 29 1997 * - * Modifications: - * Robb Matzke, 1999-07-28 - * The HEAP argument is passed by value. *------------------------------------------------------------------------- */ herr_t @@ -664,3 +550,4 @@ H5G_ent_debug(H5F_t UNUSED *f, hid_t dxpl_id, const H5G_entry_t *ent, FILE * str FUNC_LEAVE_NOAPI(SUCCEED); } + diff --git a/src/H5Glink.c b/src/H5Glink.c new file mode 100644 index 0000000..74361ca --- /dev/null +++ b/src/H5Glink.c @@ -0,0 +1,725 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5Glink.c + * Sep 5 2005 + * Quincey Koziol <koziol@ncsa.uiuc.edu> + * + * Purpose: Functions for handling link messages. + * + *------------------------------------------------------------------------- + */ +#define H5G_PACKAGE /*suppress error about including H5Gpkg */ + + +/* Packages needed by this file... */ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Gpkg.h" /* Groups */ +#include "H5HLprivate.h" /* Local Heaps */ +#include "H5Iprivate.h" /* IDs */ +#include "H5MMprivate.h" /* Memory management */ + +/* Private typedefs */ + +/* Data structure to hold table of links for a group */ +typedef struct { + size_t nlinks; /* # of links in table */ + H5O_link_t *lnks; /* Pointer to array of links */ +} H5G_link_table_t; + +/* User data for link message iteration when building link table */ +typedef struct { + H5G_link_table_t *ltable; /* Pointer to link table to build */ + size_t curr_lnk; /* Current link to operate on */ +} H5G_link_ud1_t; + +/* User data for deleting a link in the link messages */ +typedef struct { + /* downward */ + const char *name; /* Name to search for */ + H5F_t *file; /* File that object header is located within */ + hid_t dxpl_id; /* DXPL during insertion */ + + /* upward */ + H5G_obj_t *obj_type; /* Type of object deleted */ +} H5G_link_ud2_t; + +/* User data for link message iteration when querying object info */ +typedef struct { + /* downward */ + const char *name; /* Name to search for */ + H5F_t *file; /* File that object header is located within */ + hid_t dxpl_id; /* DXPL during insertion */ + + /* upward */ + H5G_stat_t *statbuf; /* Stat buffer for info */ +} H5G_link_ud3_t; + +/* User data for link message iteration when querying object location */ +typedef struct { + /* downward */ + const char *name; /* Name to search for */ + + /* upward */ + H5O_link_t *lnk; /* Link struct to fill in */ + hbool_t found; /* Flag to indicate that the object was found */ +} H5G_link_ud4_t; + +/* User data for link message iteration when querying soft link value */ +typedef struct { + /* downward */ + const char *name; /* Name to search for */ + size_t size; /* Buffer size for link value */ + + /* upward */ + char *buf; /* Buffer to fill with link value */ +} H5G_link_ud5_t; + +/* Private macros */ + +/* PRIVATE PROTOTYPES */ +static int H5G_link_cmp_name(const void *lnk1, const void *lnk2); +static herr_t H5G_link_build_table_cb(const void *_mesg, unsigned idx, void *_udata); +static herr_t H5G_link_build_table(H5O_loc_t *oloc, hid_t dxpl_id, + H5G_link_table_t *ltable); +static herr_t H5G_link_release_table(H5G_link_table_t *ltable); + + +/*------------------------------------------------------------------------- + * Function: H5G_link_cmp_name + * + * Purpose: Callback routine for comparing two link messages. + * + * Return: An integer less than, equal to, or greater than zero if the + * first argument is considered to be respectively less than, + * equal to, or greater than the second. If two members compare + * as equal, their order in the sorted array is undefined. + * (i.e. same as strcmp()) + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Sep 5 2005 + * + *------------------------------------------------------------------------- + */ +static int +H5G_link_cmp_name(const void *lnk1, const void *lnk2) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_link_cmp_name) + + FUNC_LEAVE_NOAPI(HDstrcmp(((const H5O_link_t *)lnk1)->name, ((const H5O_link_t *)lnk2)->name)) +} /* end H5G_link_cmp_name() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_link_build_table_cb + * + * Purpose: Callback routine for searching 'link' messages for a particular + * name. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Sep 5 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_link_build_table_cb(const void *_mesg, unsigned UNUSED idx, void *_udata) +{ + const H5O_link_t *lnk = (const H5O_link_t *)_mesg; /* Pointer to link */ + H5G_link_ud1_t *udata = (H5G_link_ud1_t *)_udata; /* 'User data' passed in */ + herr_t ret_value=H5O_ITER_CONT; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5G_link_build_table_cb) + + /* check arguments */ + HDassert(lnk); + HDassert(udata); + HDassert(udata->curr_lnk < udata->ltable->nlinks); + + /* Copy link message into table */ + if(H5O_copy(H5O_LINK_ID, lnk, &(udata->ltable->lnks[udata->curr_lnk])) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, H5O_ITER_ERROR, "can't copy link message") + + /* Increment current link entry to operate on */ + udata->curr_lnk++; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_link_build_table_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_link_build_table + * + * Purpose: Builds a table containing a sorted (alphabetically) list of + * links for a group + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Sep 6, 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_link_build_table(H5O_loc_t *oloc, hid_t dxpl_id, H5G_link_table_t *ltable) +{ + H5O_linfo_t linfo; /* Link info message */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5G_link_build_table) + + /* Sanity check */ + HDassert(oloc); + + /* Retrieve the link info */ + if(NULL == H5O_read(oloc, H5O_LINFO_ID, 0, &linfo, dxpl_id)) + HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't get link info") + + /* Set size of table */ + ltable->nlinks = linfo.nlinks; + + /* Allocate space for the table entries */ + if(ltable->nlinks > 0) { + H5G_link_ud1_t udata; /* User data for iteration callback */ + + if((ltable->lnks = H5MM_malloc(sizeof(H5O_link_t) * ltable->nlinks)) == NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Set up user data for iteration */ + udata.ltable = ltable; + udata.curr_lnk = 0; + + /* Iterate through the link messages, adding them to the table */ + if(H5O_iterate(oloc, H5O_LINK_ID, H5G_link_build_table_cb, &udata, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "error iterating over link messages") + + /* Sort link table (XXX: alphabetically, for now) */ + HDqsort(ltable->lnks, ltable->nlinks, sizeof(H5O_link_t), H5G_link_cmp_name); + } /* end if */ + else + ltable->lnks = NULL; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_link_build_table() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_link_release_table + * + * Purpose: Release table containing a list of links for a group + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Sep 6, 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_link_release_table(H5G_link_table_t *ltable) +{ + size_t u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5G_link_release_table) + + /* Sanity check */ + HDassert(ltable); + + /* Release link info, if any */ + if(ltable->nlinks > 0) { + /* Free link message information */ + for(u = 0; u < ltable->nlinks; u++) + if(H5O_reset(H5O_LINK_ID, &(ltable->lnks[u])) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to release link message") + + /* Free table of links */ + H5MM_xfree(ltable->lnks); + } /* end if */ + else + HDassert(ltable->lnks == NULL); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_link_release_table() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_link_convert + * + * Purpose: Converts a group entry into a link object. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Sep 5 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_link_convert(H5O_link_t *lnk, const H5G_entry_t *ent, const H5HL_t *heap, + const char *name) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_link_convert, FAIL) + + /* Check arguments. */ + HDassert(lnk); + HDassert(ent); + HDassert(name); + + /* Create link message from object entry */ + HDassert(ent->type == H5G_NOTHING_CACHED || ent->type == H5G_CACHED_SLINK); +/* XXX: Set character set & creation time for real? */ + lnk->cset = H5T_CSET_ASCII; + lnk->ctime = 0; + lnk->name = H5MM_xstrdup(name); /* Casting away const OK -QAK */ + HDassert(lnk->name); + switch(ent->type) { + case H5G_NOTHING_CACHED: + lnk->type = H5G_LINK_HARD; + lnk->u.hard.addr = ent->header; + break; + + case H5G_CACHED_SLINK: + { + const char *s; /* Pointer to link value in heap */ + + lnk->type = H5G_LINK_SOFT; + + s = H5HL_offset_into(ent->file, heap, ent->cache.slink.lval_offset); + HDassert(s); + + /* Copy to for link */ + lnk->u.soft.name = H5MM_xstrdup(s); + HDassert(lnk->u.soft.name); + } + break; + + default: + HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "unrecognized link type") + } /* end switch */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_link_convert() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_link_insert + * + * 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 OBJ_ENT. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Sep 6 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_link_insert(H5O_loc_t *grp_oloc, H5O_link_t *obj_lnk, + hid_t dxpl_id) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_link_insert, FAIL) + + /* check arguments */ + HDassert(grp_oloc && grp_oloc->file); + HDassert(obj_lnk); + + /* Insert link message into group */ + if(H5O_modify(grp_oloc, H5O_LINK_ID, H5O_NEW_MESG, 0, H5O_UPDATE_TIME, obj_lnk, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create message") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_link_insert() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_link_get_name_by_idx + * + * Purpose: Returns the name of objects in the group by giving index. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Sep 6, 2005 + * + *------------------------------------------------------------------------- + */ +ssize_t +H5G_link_get_name_by_idx(H5O_loc_t *oloc, hsize_t idx, char* name, + size_t size, hid_t dxpl_id) +{ + H5G_link_table_t ltable = {0, NULL}; /* Link table */ + ssize_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_link_get_name_by_idx, FAIL) + + /* Sanity check */ + HDassert(oloc); + + /* Build table of all link messages */ + if(H5G_link_build_table(oloc, dxpl_id, <able) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create link message table") + + /* Check for going out of bounds */ + if(idx >= ltable.nlinks) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "index out of bound") + + /* Get the length of the name */ + ret_value = (ssize_t)HDstrlen(ltable.lnks[idx].name); + + /* Copy the name into the user's buffer, if given */ + if(name) { + HDstrncpy(name, ltable.lnks[idx].name, MIN((size_t)(ret_value+1),size)); + if((size_t)ret_value >= size) + name[size-1]='\0'; + } /* end if */ + +done: + /* Release link table */ + if(ltable.lnks) { + /* Free link table information */ + if(H5G_link_release_table(<able) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to release link table") + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_link_get_name_by_idx() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_link_get_type_by_idx + * + * Purpose: Returns the type of objects in the group by giving index. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Sep 12, 2005 + * + *------------------------------------------------------------------------- + */ +H5G_obj_t +H5G_link_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx, hid_t dxpl_id) +{ + H5G_link_table_t ltable = {0, NULL}; /* Link table */ + H5G_obj_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_link_get_type_by_idx, H5G_UNKNOWN) + + /* Sanity check */ + HDassert(oloc); + + /* Build table of all link messages */ + if(H5G_link_build_table(oloc, dxpl_id, <able) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, H5G_UNKNOWN, "can't create link message table") + + /* Check for going out of bounds */ + if(idx >= ltable.nlinks) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "index out of bound") + + /* Determine type of object */ + if(ltable.lnks[idx].type == H5G_LINK_SOFT) + ret_value = H5G_LINK; + else { + H5O_loc_t tmp_oloc; /* Temporary object location */ + + /* Build temporary object location */ + tmp_oloc.file = oloc->file; + tmp_oloc.addr = ltable.lnks[idx].u.hard.addr; + + /* Get the type of the object */ + if((ret_value = H5O_obj_type(&tmp_oloc, dxpl_id)) == H5G_UNKNOWN) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "can't determine object type") + } /* end else */ + +done: + /* Release link table */ + if(ltable.lnks) { + /* Free link table information */ + if(H5G_link_release_table(<able) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTFREE, H5G_UNKNOWN, "unable to release link table") + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_link_get_type_by_idx() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_link_remove_cb + * + * Purpose: Callback routine for deleting 'link' message for a particular + * name. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Sep 5 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_link_remove_cb(const void *_mesg, unsigned UNUSED idx, void *_udata) +{ + const H5O_link_t *lnk = (const H5O_link_t *)_mesg; /* Pointer to link */ + H5G_link_ud2_t *udata = (H5G_link_ud2_t *)_udata; /* 'User data' passed in */ + herr_t ret_value = H5O_ITER_CONT; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_link_remove_cb) + + /* check arguments */ + HDassert(lnk); + HDassert(udata); + + /* If we've found the right link, get the object type */ + if(HDstrcmp(lnk->name, udata->name) == 0) { + if(lnk->type == H5G_LINK_SOFT) + *(udata->obj_type) = H5G_LINK; + else { + H5O_loc_t tmp_oloc; /* Temporary object location */ + + /* Build temporary object location */ + tmp_oloc.file = udata->file; + tmp_oloc.addr = lnk->u.hard.addr; + + /* Get the type of the object */ + /* Note: no way to check for error :-( */ + *(udata->obj_type) = H5O_obj_type(&tmp_oloc, udata->dxpl_id); + } /* end else */ + + /* Stop the iteration, we found the correct link */ + HGOTO_DONE(H5O_ITER_STOP) + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_link_remove_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_link_remove + * + * Purpose: Remove NAME from links. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Monday, September 19, 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_link_remove(const H5O_loc_t *oloc, const char *name, H5G_obj_t *obj_type, + hid_t dxpl_id) +{ + H5G_link_ud2_t udata; /* Data to pass through OH iteration */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_link_remove, FAIL) + + HDassert(oloc && oloc->file); + HDassert(name && *name); + + /* Initialize data to pass through object header iteration */ + udata.name = name; + udata.file = oloc->file; + udata.dxpl_id = dxpl_id; + udata.obj_type = obj_type; + + /* Iterate over the link messages to delete the right one */ + if(H5O_remove_op(oloc, H5O_LINK_ID, H5O_FIRST, H5G_link_remove_cb, &udata, TRUE, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete link message") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_link_remove() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_link_iterate + * + * Purpose: Iterate over the objects in a group + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Monday, October 3, 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_link_iterate(H5O_loc_t *oloc, hid_t gid, int skip, int *last_obj, + H5G_iterate_t op, void *op_data, hid_t dxpl_id) +{ + H5G_link_table_t ltable = {0, NULL}; /* Link table */ + size_t u; /* Local index variable */ + herr_t ret_value; + + FUNC_ENTER_NOAPI(H5G_link_iterate, FAIL) + + /* Sanity check */ + HDassert(oloc); + HDassert(H5I_GROUP == H5I_get_type(gid)); + HDassert(last_obj); + HDassert(op); + + /* Build table of all link messages */ + if(H5G_link_build_table(oloc, dxpl_id, <able) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, H5B_ITER_ERROR, "can't create link message table") + + /* Check for going out of bounds */ + if(skip > 0 && (size_t)skip >= ltable.nlinks) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5B_ITER_ERROR, "index out of bound") + + /* Iterate over link messages */ + for(u = 0, ret_value = H5B_ITER_CONT; u < ltable.nlinks && !ret_value; u++) { + if(skip > 0) + --skip; + else + ret_value = (op)(gid, ltable.lnks[u].name, op_data); + + /* Increment the number of entries passed through */ + /* (whether we skipped them or not) */ + (*last_obj)++; + } /* end for */ + + /* Check for callback failure and pass along return value */ + if(ret_value < 0) + HERROR(H5E_SYM, H5E_CANTNEXT, "iteration operator failed"); + +done: + /* Release link table */ + if(ltable.lnks) { + /* Free link table information */ + if(H5G_link_release_table(<able) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTFREE, H5B_ITER_ERROR, "unable to release link table") + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_link_iterate() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_link_lookup_cb + * + * Purpose: Callback routine for searching 'link' messages for a particular + * name & gettting object location for it + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Sep 20 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_link_lookup_cb(const void *_mesg, unsigned UNUSED idx, void *_udata) +{ + const H5O_link_t *lnk = (const H5O_link_t *)_mesg; /* Pointer to link */ + H5G_link_ud4_t *udata = (H5G_link_ud4_t *)_udata; /* 'User data' passed in */ + herr_t ret_value = H5O_ITER_CONT; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5G_link_lookup_cb) + + /* check arguments */ + HDassert(lnk); + HDassert(udata); + + /* Check for name to get information */ + if(HDstrcmp(lnk->name, udata->name) == 0) { + if(udata->lnk) { + /* Copy link information */ + if(H5O_copy(H5O_LINK_ID, lnk, udata->lnk) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, H5O_ITER_ERROR, "can't copy link message") + } /* end if */ + + /* Indicate that the correct link was found */ + udata->found = TRUE; + + /* Stop iteration now */ + HGOTO_DONE(H5O_ITER_STOP) + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_link_lookup_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_link_lookup + * + * Purpose: Look up an object relative to a group, using link messages. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Sep 20 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_link_lookup(H5O_loc_t *oloc, const char *name, H5O_link_t *lnk, + hid_t dxpl_id) +{ + H5G_link_ud4_t udata; /* User data for iteration callback */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_link_lookup, FAIL) + + /* check arguments */ + HDassert(lnk && oloc->file); + HDassert(name && *name); + + /* Set up user data for iteration */ + udata.name = name; + udata.lnk = lnk; + udata.found = FALSE; + + /* Iterate through the link messages, adding them to the table */ + if(H5O_iterate(oloc, H5O_LINK_ID, H5G_link_lookup_cb, &udata, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "error iterating over link messages") + + /* Check if we found the link we were looking for */ + if(!udata.found) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_link_lookup() */ + diff --git a/src/H5Gloc.c b/src/H5Gloc.c new file mode 100644 index 0000000..e2a293f --- /dev/null +++ b/src/H5Gloc.c @@ -0,0 +1,469 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5Gloc.c + * Sep 13 2005 + * Quincey Koziol <koziol@ncsa.uiuc.edu> + * + * Purpose: Functions for working with group "locations" + * + *------------------------------------------------------------------------- + */ +#define H5G_PACKAGE /*suppress error about including H5Gpkg */ + + +/* Packages needed by this file... */ +#include "H5private.h" /* Generic Functions */ +#include "H5Aprivate.h" /* Attributes */ +#include "H5Dprivate.h" /* Datasets */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Gpkg.h" /* Groups */ +#include "H5Iprivate.h" /* IDs */ + +/* Private typedefs */ + +/* User data for looking up an object in a group */ +typedef struct { + H5G_loc_t *loc; /* Group location to set */ +} H5G_loc_ud1_t; + +/* Private macros */ + +/* Local variables */ + +/* PRIVATE PROTOTYPES */ +static herr_t H5G_loc_find_cb(H5G_loc_t *grp_loc, const char *name, + const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata); + + +/*------------------------------------------------------------------------- + * Function: H5G_loc + * + * Purpose: Given an object ID return a location for the object. + * + * Return: Success: Group pointer. + * Failure: NULL + * + * Programmer: Quincey Koziol + * Tuesday, September 13, 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_loc(hid_t loc_id, H5G_loc_t *loc) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_loc, FAIL) + + switch(H5I_get_type(loc_id)) { + case H5I_FILE: + { + H5F_t *f; + + if(NULL == (f = H5I_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file ID") + if(NULL == (loc->oloc = H5G_oloc(H5G_rootof(f)))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get symbol table entry for root group") + if(NULL == (loc->path = H5G_nameof(H5G_rootof(f)))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get path for root group") + + /* Patch up root group's symbol table entry to reflect this file */ + /* (Since the root group info is only stored once for files which + * share an underlying low-level file) + */ + /* (but only for non-mounted files) */ + if(!H5F_is_mount(f)) + loc->oloc->file = f; + } /* end case */ + break; + + case H5I_GENPROP_CLS: + case H5I_GENPROP_LST: + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get symbol table entry of property list") + + case H5I_ERROR_CLASS: + case H5I_ERROR_MSG: + case H5I_ERROR_STACK: + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get symbol table entry of error class, message or stack") + + case H5I_GROUP: + { + H5G_t *group; + + if(NULL == (group = H5I_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid group ID") + if(NULL == (loc->oloc = H5G_oloc(group))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get symbol table entry of group") + if(NULL == (loc->path = H5G_nameof(group))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get path of group") + } /* end case */ + break; + + case H5I_DATATYPE: + { + H5T_t *dt; + + if(NULL == (dt = H5I_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid type ID") + if(NULL == (loc->oloc = H5T_oloc(dt))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get symbol table entry of datatype") + if(NULL == (loc->path = H5T_nameof(dt))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get path of datatype") + } /* end case */ + break; + + case H5I_DATASPACE: + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get symbol table entry of dataspace") + + case H5I_DATASET: + { + H5D_t *dset; + + if(NULL == (dset = H5I_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid data ID") + if(NULL == (loc->oloc = H5D_oloc(dset))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get symbol table entry of dataset") + if(NULL == (loc->path = H5D_nameof(dset))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get path of dataset") + } /* end case */ + break; + + case H5I_ATTR: + { + H5A_t *attr; + + if(NULL == (attr = H5I_object(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid attribute ID") + if(NULL == (loc->oloc = H5A_oloc(attr))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get symbol table entry of attribute") + if(NULL == (loc->path = H5A_nameof(attr))) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get path of attribute") + } /* end case */ + break; + + case H5I_REFERENCE: + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get symbol table entry of reference") + + default: + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object ID") + } /* end switch */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_loc() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_loc_copy + * + * Purpose: Copy over information for a location + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, September 13, 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_loc_copy(H5G_loc_t *dst, H5G_loc_t *src, H5G_copy_depth_t depth) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_loc_copy, FAIL) + + /* Check args. */ + HDassert(dst); + HDassert(src); + + /* Copy components of the location */ + if(H5O_loc_copy(dst->oloc, src->oloc, (depth == H5G_COPY_SHALLOW ? H5O_COPY_SHALLOW : H5O_COPY_DEEP)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to copy entry") + if(H5G_name_copy(dst->path, src->path, depth) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to copy path") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_loc_copy() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_loc_reset + * + * Purpose: Reset information for a location + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, September 13, 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_loc_reset(H5G_loc_t *loc) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_loc_reset, FAIL) + + /* Check args. */ + HDassert(loc); + + /* Reset components of the location */ + if(H5O_loc_reset(loc->oloc) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to reset entry") + if(H5G_name_reset(loc->path) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to reset path") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_loc_reset() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_loc_free + * + * Purpose: Free information for a location + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, September 13, 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_loc_free(H5G_loc_t *loc) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_loc_free, FAIL) + + /* Check args. */ + HDassert(loc); + + /* Reset components of the location */ +#ifdef NOT_YET + if(H5G_ent_free(loc->ent) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to free entry") +#endif /* NOT_YET */ + if(H5G_name_free(loc->path) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to free path") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_loc_free() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_loc_find_cb + * + * Purpose: Callback for retrieving object location for an object in a group + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Monday, October 17, 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_loc_find_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name, const H5O_link_t UNUSED *lnk, + H5G_loc_t *obj_loc, void *_udata/*in,out*/) +{ + H5G_loc_ud1_t *udata = (H5G_loc_ud1_t *)_udata; /* User data passed in */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5G_loc_find_cb) + + /* Check if the name in this group resolved to a valid link */ + if(obj_loc == NULL) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "name doesn't exist") + + /* Take ownership of the object's group location */ + /* (Group traversal callbacks are responsible for either taking ownership + * of the group location for the object, or freeing it. - QAK) + */ + H5G_loc_copy(udata->loc, obj_loc, H5O_COPY_SHALLOW); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_loc_find_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_loc_find + * + * Purpose: Find a symbol from a location + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, September 13, 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_loc_find(H5G_loc_t *loc, const char *name, H5G_loc_t *obj_loc/*out*/, + hid_t dxpl_id) +{ + H5G_loc_ud1_t udata; /* User data for traversal callback */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_loc_find, FAIL) + + /* Check args. */ + HDassert(loc); + HDassert(name && *name); + HDassert(obj_loc); + + /* Set up user data for locating object */ + udata.loc = obj_loc; + + /* Traverse group hierarchy to locate object */ + if(H5G_traverse(loc, name, H5G_TARGET_NORMAL, H5G_loc_find_cb, &udata, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't find object") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_loc_find() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_loc_insert + * + * Purpose: Insert an object at a location + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, September 13, 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_loc_insert(H5G_loc_t *grp_loc, const char *name, H5G_loc_t *obj_loc, + hbool_t inc_link, hid_t dxpl_id) +{ + H5O_link_t lnk; /* Link for object to insert */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_loc_insert, FAIL) + + /* Check args. */ + HDassert(grp_loc); + HDassert(name && *name); + HDassert(obj_loc); + + /* "Translate" object location into link object */ + lnk.type = H5G_LINK_HARD; +#ifdef H5_HAVE_GETTIMEOFDAY + { + struct timeval now_tv; + + HDgettimeofday(&now_tv, NULL); + lnk.ctime = now_tv.tv_sec; + } +#else /* H5_HAVE_GETTIMEOFDAY */ + lnk.ctime = HDtime(NULL); +#endif /* H5_HAVE_GETTIMEOFDAY */ + lnk.cset = H5T_CSET_ASCII; /* XXX: Allow user to set this */ + /* Casting away const OK -QAK */ + lnk.name = (char *)name; + lnk.u.hard.addr = obj_loc->oloc->addr; + + /* Insert new group into current group's symbol table */ + if(H5G_obj_insert(grp_loc->oloc, name, &lnk, inc_link, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert object") + + /* Set the name of the object location */ + if(H5G_name_set(grp_loc->path, obj_loc->path, name) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "cannot set name") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_loc_insert() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_loc_exists + * + * Purpose: Check if a symbol exists in a location + * + * Return: Non-negative if object exists/Negative if object doesn't exist + * + * Programmer: Quincey Koziol + * Monday, September 19, 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_loc_exists(const H5G_loc_t *loc, const char *name, hid_t dxpl_id) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_loc_exists, FAIL) + + /* Check args. */ + HDassert(loc); + HDassert(name && *name); + + /* Get information for object in current group */ + if(H5G_obj_lookup(loc->oloc, name, NULL, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "component not found") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_loc_exists() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_loc_remove + * + * Purpose: Remove a link from a group + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Monday, September 19, 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_loc_remove(H5G_loc_t *grp_loc, const char *name, H5G_loc_t *obj_loc, hid_t dxpl_id) +{ + H5G_obj_t obj_type; /* Type of object removed */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_loc_remove, FAIL) + + /* Check args. */ + HDassert(grp_loc); + HDassert(name && *name); + + /* Remove object from group */ + if(H5G_obj_remove(grp_loc->oloc, name, &obj_type, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "component not found") + + /* Search the open IDs and replace names for unlinked object */ + if(H5G_name_replace(obj_type, obj_loc, NULL, NULL, NULL, NULL, OP_UNLINK) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to replace name") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_loc_remove() */ + diff --git a/src/H5Gname.c b/src/H5Gname.c new file mode 100644 index 0000000..1d1a141 --- /dev/null +++ b/src/H5Gname.c @@ -0,0 +1,880 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5Gname.c + * Sep 12 2005 + * Quincey Koziol <koziol@ncsa.uiuc.edu> + * + * Purpose: Functions for handling group hierarchy paths. + * + *------------------------------------------------------------------------- + */ +#define H5F_PACKAGE /*suppress error about including H5Fpkg */ +#define H5G_PACKAGE /*suppress error about including H5Gpkg */ + + +/* Packages needed by this file... */ +#include "H5private.h" /* Generic Functions */ +#include "H5Dprivate.h" /* Datasets */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Fpkg.h" /* File access */ +#include "H5FLprivate.h" /* Free Lists */ +#include "H5Gpkg.h" /* Groups */ +#include "H5Iprivate.h" /* IDs */ +#include "H5MMprivate.h" /* Memory management */ + +/* Private typedefs */ + +/* Struct used by change name callback function */ +typedef struct H5G_names_t { + H5G_loc_t *loc; + H5RS_str_t *src_name; + H5G_loc_t *src_loc; + H5RS_str_t *dst_name; + H5G_loc_t *dst_loc; + H5G_names_op_t op; +} H5G_names_t; + +/* Private macros */ + +/* Local variables */ + +/* Declare extern the PQ free list for the wrapped strings */ +H5FL_BLK_EXTERN(str_buf); + +/* PRIVATE PROTOTYPES */ +static htri_t H5G_common_path(const H5RS_str_t *fullpath_r, const H5RS_str_t *prefix_r); +static H5RS_str_t *H5G_build_fullpath(const char *prefix, const char *name); +static H5RS_str_t *H5G_build_fullpath_refstr_refstr(const H5RS_str_t *prefix_r, const H5RS_str_t *name_r); +static H5RS_str_t *H5G_build_fullpath_refstr_str(H5RS_str_t *path_r, const char *name); +static int H5G_name_replace_cb(void *obj_ptr, hid_t obj_id, void *key); + + +/*------------------------------------------------------------------------- + * Function: H5G_common_path + * + * Purpose: Determine if one path is a valid prefix of another path + * + * Return: TRUE for valid prefix, FALSE for not a valid prefix, FAIL + * on error + * + * Programmer: Quincey Koziol, koziol@ncsa.uiuc.edu + * + * Date: September 24, 2002 + * + *------------------------------------------------------------------------- + */ +static htri_t +H5G_common_path(const H5RS_str_t *fullpath_r, const H5RS_str_t *prefix_r) +{ + const char *fullpath; /* Pointer to actual fullpath string */ + const char *prefix; /* Pointer to actual prefix string */ + size_t nchars1,nchars2; /* Number of characters in components */ + htri_t ret_value=FALSE; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_common_path) + + /* Get component of each name */ + fullpath=H5RS_get_str(fullpath_r); + assert(fullpath); + fullpath=H5G_component(fullpath,&nchars1); + assert(fullpath); + prefix=H5RS_get_str(prefix_r); + assert(prefix); + prefix=H5G_component(prefix,&nchars2); + assert(prefix); + + /* Check if we have a real string for each component */ + while(*fullpath && *prefix) { + /* Check that the components we found are the same length */ + if(nchars1==nchars2) { + /* Check that the two components are equal */ + if(HDstrncmp(fullpath,prefix,nchars1)==0) { + /* Advance the pointers in the names */ + fullpath+=nchars1; + prefix+=nchars2; + + /* Get next component of each name */ + fullpath=H5G_component(fullpath,&nchars1); + assert(fullpath); + prefix=H5G_component(prefix,&nchars2); + assert(prefix); + } /* end if */ + else + HGOTO_DONE(FALSE) + } /* end if */ + else + HGOTO_DONE(FALSE) + } /* end while */ + + /* If we reached the end of the prefix path to check, it must be a valid prefix */ + if(*prefix=='\0') + ret_value=TRUE; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_common_path() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_build_fullpath + * + * Purpose: Build a full path from a prefix & base pair of strings + * + * Return: Pointer to reference counted string on success, NULL on error + * + * Programmer: Quincey Koziol, koziol@ncsa.uiuc.edu + * + * Date: August 19, 2005 + * + *------------------------------------------------------------------------- + */ +static H5RS_str_t * +H5G_build_fullpath(const char *prefix, const char *name) +{ + char *full_path; /* Full user path built */ + size_t path_len; /* Length of the path */ + unsigned need_sep; /* Flag to indicate if separator is needed */ + H5RS_str_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5G_build_fullpath) + + /* Sanity check */ + HDassert(prefix); + HDassert(name); + + /* Get the length of the prefix */ + path_len = HDstrlen(prefix); + + /* Determine if there is a trailing separator in the name */ + if(prefix[path_len - 1] == '/') + need_sep = 0; + else + need_sep = 1; + + /* Add in the length needed for the '/' separator and the relative path */ + path_len += HDstrlen(name) + need_sep; + + /* Allocate space for the path */ + if(NULL == (full_path = H5FL_BLK_MALLOC(str_buf, path_len + 1))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* Build full path */ + HDstrcpy(full_path, prefix); + if(need_sep) + HDstrcat(full_path, "/"); + HDstrcat(full_path, name); + + /* Create reference counted string for path */ + if((ret_value = H5RS_own(full_path)) == NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_build_fullpath() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_build_fullpath_refstr_str + * + * Purpose: Append an object path to an existing ref-counted path + * + * Return: Success: Non-NULL, combined path + * Failure: NULL + * + * Programmer: Quincey Koziol, koziol@ncsa.uiuc.edu + * Tuesday, October 11, 2005 + * + *------------------------------------------------------------------------- + */ +static H5RS_str_t * +H5G_build_fullpath_refstr_str(H5RS_str_t *prefix_r, const char *name) +{ + const char *prefix; /* Pointer to raw string for path */ + H5RS_str_t *ret_value; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_build_fullpath_refstr_str) + + HDassert(prefix_r); + HDassert(name); + + /* Get the raw string for the user path */ + prefix = H5RS_get_str(prefix_r); + HDassert(prefix); + + /* Create reference counted string for path */ + ret_value = H5G_build_fullpath(prefix, name); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_build_fullpath_refstr_str() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_name_concat_refstr_refstr + * + * Purpose: Build a full path from a prefix & base pair of reference counted + * strings + * + * Return: Pointer to reference counted string on success, NULL on error + * + * Programmer: Quincey Koziol, koziol@ncsa.uiuc.edu + * + * Date: August 19, 2005 + * + *------------------------------------------------------------------------- + */ +static H5RS_str_t * +H5G_build_fullpath_refstr_refstr(const H5RS_str_t *prefix_r, const H5RS_str_t *name_r) +{ + const char *prefix; /* Pointer to raw string of prefix */ + const char *name; /* Pointer to raw string of name */ + H5RS_str_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_build_fullpath_refstr_refstr) + + /* Get the pointer to the prefix */ + prefix = H5RS_get_str(prefix_r); + + /* Get the pointer to the raw src user path */ + name = H5RS_get_str(name_r); + + /* Create reference counted string for path */ + ret_value = H5G_build_fullpath(prefix, name); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_build_fullpath_refstr_refstr() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_name_init + * + * Purpose: Set the initial path for a group hierarchy name + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Monday, September 12, 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_name_init(H5G_name_t *name, const char *path) +{ + FUNC_ENTER_NOAPI_NOFUNC(H5G_name_init) + + /* Check arguments */ + HDassert(name); + + /* Set the initial paths for a name object */ + name->user_path_r=H5RS_create(path); + HDassert(name->user_path_r); + name->canon_path_r=H5RS_create(path); + HDassert(name->canon_path_r); + name->user_path_hidden=0; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5G_name_init() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_name_set + * + * Purpose: Set the name of a symbol entry OBJ, located at LOC + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * Thursday, August 22, 2002 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_name_set(H5G_name_t *loc, H5G_name_t *obj, const char *name) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(H5G_name_set, FAIL) + + HDassert(loc); + HDassert(obj); + HDassert(name); + + /* Free & reset the object's previous paths info (if they exist) */ + H5G_name_free(obj); + + /* Create the object's user path, if a user path exists in the location */ + if(loc->user_path_r) { + /* Go build the new user path */ + if((obj->user_path_r = H5G_build_fullpath_refstr_str(loc->user_path_r, name)) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_PATH, FAIL, "can't build user path name") + } /* end if */ + + /* Create the object's canonical path, if a canonical path exists in the location */ + if(loc->canon_path_r) { + /* Go build the new canonical path */ + if((obj->canon_path_r = H5G_build_fullpath_refstr_str(loc->canon_path_r, name)) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_PATH, FAIL, "can't build canonical path name") + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_name_set() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_name_copy + * + * Purpose: Do a copy of group hier. names + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Monday, September 12, 2005 + * + * Notes: 'depth' parameter determines how much of the group entry + * structure we want to copy. The new depths are: + * H5G_COPY_SHALLOW - Copy all the fields from the source + * to the destination, including the user path and + * canonical path. (Destination "takes ownership" of + * user and canonical paths) + * H5G_COPY_CANON - Deep copy the canonical path and leave + * the user path alone + * H5G_COPY_DEEP - Copy all the fields from the source to + * the destination, deep copying the user and canonical + * paths. + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_name_copy(H5G_name_t *dst, const H5G_name_t *src, H5G_copy_depth_t depth) +{ + H5RS_str_t *tmp_user_path_r = NULL; /* Temporary string pointer for entry's user path */ + + FUNC_ENTER_NOAPI_NOFUNC(H5G_name_copy) + + /* Check arguments */ + HDassert(src); + HDassert(dst); + HDassert(depth == H5G_COPY_SHALLOW || depth == H5G_COPY_DEEP || depth == H5G_COPY_CANON); + + /* If only copying the canonical path, keep the old user path */ + if(depth == H5G_COPY_CANON) { + tmp_user_path_r = dst->user_path_r; + if(dst->canon_path_r) + H5RS_decr(dst->canon_path_r); + } /* end if */ + + /* Copy the top level information */ + HDmemcpy(dst, src, sizeof(H5G_name_t)); + + /* Deep copy the names */ + if(depth == H5G_COPY_DEEP) { + dst->user_path_r = H5RS_dup(src->user_path_r); + dst->canon_path_r = H5RS_dup(src->canon_path_r); + } else if(depth == H5G_COPY_CANON) { + dst->user_path_r = tmp_user_path_r; + dst->canon_path_r = H5RS_dup(src->canon_path_r); + } else { + /* Discarding 'const' qualifier OK - QAK */ + H5G_name_reset((H5G_name_t *)src); + } /* end if */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5G_name_copy() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_name_reset + * + * Purpose: Reset a group hierarchy name to an empty state + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Monday, September 12, 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_name_reset(H5G_name_t *name) +{ + FUNC_ENTER_NOAPI_NOFUNC(H5G_name_reset) + + /* Check arguments */ + HDassert(name); + + /* Clear the group hier. name to an empty state */ + HDmemset(name, 0, sizeof(H5G_name_t)); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5G_name_reset() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_name_free + * + * Purpose: Free the 'ID to name' buffers. + * + * Return: Success + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: August 22, 2002 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_name_free(H5G_name_t *name) +{ + FUNC_ENTER_NOAPI_NOFUNC(H5G_name_free) + + /* Check args */ + HDassert(name); + + if(name->user_path_r) { + H5RS_decr(name->user_path_r); + name->user_path_r=NULL; + } /* end if */ + if(name->canon_path_r) { + H5RS_decr(name->canon_path_r); + name->canon_path_r=NULL; + } /* end if */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5G_name_free() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_name_replace_cb + * + * Purpose: H5I_search callback function to replace group entry names + * + * Return: Success: 0, Failure: -1 + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: June 5, 2002 + * + *------------------------------------------------------------------------- + */ +static int +H5G_name_replace_cb(void *obj_ptr, hid_t obj_id, void *key) +{ + const H5G_names_t *names = (const H5G_names_t *)key; /* Get operation's information */ + H5O_loc_t *oloc; /* Object location for object that the ID refers to */ + H5G_name_t *obj_path; /* Pointer to group hier. path for obj */ + H5F_t *top_ent_file; /* Top file in entry's mounted file chain */ + H5F_t *top_loc_file; /* Top file in location's mounted file chain */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5G_name_replace_cb) + + HDassert(obj_ptr); + + /* Get the symbol table entry */ + switch(H5I_get_type(obj_id)) { + case H5I_GROUP: + oloc = H5G_oloc((H5G_t *)obj_ptr); + obj_path = H5G_nameof((H5G_t *)obj_ptr); + break; + + case H5I_DATASET: + oloc = H5D_oloc((H5D_t *)obj_ptr); + obj_path = H5D_nameof((H5D_t *)obj_ptr); + break; + + case H5I_DATATYPE: + /* Avoid non-named datatypes */ + if(!H5T_is_named((H5T_t *)obj_ptr)) + HGOTO_DONE(SUCCEED) /* Do not exit search over IDs */ + + oloc = H5T_oloc((H5T_t *)obj_ptr); + obj_path = H5T_nameof((H5T_t *)obj_ptr); + break; + + default: + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "unknown data object") + } /* end switch */ + HDassert(oloc); + HDassert(obj_path); + + switch(names->op) { + /*------------------------------------------------------------------------- + * OP_MOUNT + *------------------------------------------------------------------------- + */ + case OP_MOUNT: + if(obj_path->user_path_r) { + if(oloc->file->mtab.parent && H5RS_cmp(obj_path->user_path_r, obj_path->canon_path_r)) { + /* Find the "top" file in the chain of mounted files */ + top_ent_file = oloc->file->mtab.parent; + while(top_ent_file->mtab.parent != NULL) + top_ent_file = top_ent_file->mtab.parent; + } /* end if */ + else + top_ent_file = oloc->file; + + /* Check for entry being in correct file (or mounted file) */ + if(top_ent_file->shared == names->loc->oloc->file->shared) { + /* Check if the source is along the entry's path */ + /* (But not actually the entry itself) */ + if(H5G_common_path(obj_path->user_path_r, names->src_name) && + H5RS_cmp(obj_path->user_path_r, names->src_name) != 0) { + /* Hide the user path */ + (obj_path->user_path_hidden)++; + } /* end if */ + } /* end if */ + } /* end if */ + break; + + /*------------------------------------------------------------------------- + * OP_UNMOUNT + *------------------------------------------------------------------------- + */ + case OP_UNMOUNT: + if(obj_path->user_path_r) { + if(oloc->file->mtab.parent) { + /* Find the "top" file in the chain of mounted files for the entry */ + top_ent_file = oloc->file->mtab.parent; + while(top_ent_file->mtab.parent != NULL) + top_ent_file=top_ent_file->mtab.parent; + } /* end if */ + else + top_ent_file = oloc->file; + + if(names->loc->oloc->file->mtab.parent) { + /* Find the "top" file in the chain of mounted files for the location */ + top_loc_file = names->loc->oloc->file->mtab.parent; + while(top_loc_file->mtab.parent != NULL) + top_loc_file = top_loc_file->mtab.parent; + } /* end if */ + else + top_loc_file = names->loc->oloc->file; + + /* If the ID's entry is not in the file we operated on, skip it */ + if(top_ent_file->shared == top_loc_file->shared) { + if(obj_path->user_path_hidden) { + if(H5G_common_path(obj_path->user_path_r, names->src_name)) { + /* Un-hide the user path */ + (obj_path->user_path_hidden)--; + } /* end if */ + } /* end if */ + else { + if(H5G_common_path(obj_path->user_path_r, names->src_name)) { + /* Free user path */ + H5RS_decr(obj_path->user_path_r); + obj_path->user_path_r = NULL; + } /* end if */ + } /* end else */ + } /* end if */ + } /* end if */ + break; + + /*------------------------------------------------------------------------- + * OP_UNLINK + *------------------------------------------------------------------------- + */ + case OP_UNLINK: + /* If the ID's entry is not in the file we operated on, skip it */ + if(oloc->file->shared == names->loc->oloc->file->shared && + names->loc->path->canon_path_r && obj_path->canon_path_r && obj_path->user_path_r) { + /* Check if we are referring to the same object */ + if(H5F_addr_eq(oloc->addr, names->loc->oloc->addr)) { + /* Check if the object was opened with the same canonical path as the one being moved */ + if(H5RS_cmp(obj_path->canon_path_r, names->loc->path->canon_path_r) == 0) { + /* Free user path */ + H5RS_decr(obj_path->user_path_r); + obj_path->user_path_r=NULL; + } /* end if */ + } /* end if */ + else { + /* Check if the location being unlinked is in the canonical path for the current object */ + if(H5G_common_path(obj_path->canon_path_r, names->loc->path->canon_path_r)) { + /* Free user path */ + H5RS_decr(obj_path->user_path_r); + obj_path->user_path_r=NULL; + } /* end if */ + } /* end else */ + } /* end if */ + break; + + /*------------------------------------------------------------------------- + * OP_MOVE + *------------------------------------------------------------------------- + */ + case OP_MOVE: /* H5Gmove case, check for relative names case */ + /* If the ID's entry is not in the file we operated on, skip it */ + if(oloc->file->shared == names->loc->oloc->file->shared) { + if(obj_path->user_path_r && names->loc->path->user_path_r && + names->src_loc->path->user_path_r && names->dst_loc->path->user_path_r) { + H5RS_str_t *src_path_r; /* Full user path of source name */ + H5RS_str_t *dst_path_r; /* Full user path of destination name */ + H5RS_str_t *canon_src_path_r; /* Copy of canonical part of source path */ + H5RS_str_t *canon_dst_path_r; /* Copy of canonical part of destination path */ + + /* Sanity check */ + HDassert(names->src_name); + HDassert(names->dst_name); + + /* Make certain that the source and destination names are full (not relative) paths */ + if(*(H5RS_get_str(names->src_name)) != '/') { + /* Create reference counted string for full src path */ + if((src_path_r = H5G_build_fullpath_refstr_refstr(names->src_loc->path->user_path_r, names->src_name)) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_PATH, FAIL, "can't build source path name") + } /* end if */ + else + src_path_r = H5RS_dup(names->src_name); + if(*(H5RS_get_str(names->dst_name)) != '/') { + /* Create reference counted string for full dst path */ + if((dst_path_r = H5G_build_fullpath_refstr_refstr(names->dst_loc->path->user_path_r, names->dst_name)) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_PATH, FAIL, "can't build destination path name") + } /* end if */ + else + dst_path_r = H5RS_dup(names->dst_name); + + /* Get the canonical parts of the source and destination names */ + + /* Check if the object being moved was accessed through a mounted file */ + if(H5RS_cmp(names->loc->path->user_path_r, names->loc->path->canon_path_r) != 0) { + size_t non_canon_name_len; /* Length of non-canonical part of name */ + + /* Get current string lengths */ + non_canon_name_len = H5RS_len(names->loc->path->user_path_r) - H5RS_len(names->loc->path->canon_path_r); + + canon_src_path_r = H5RS_create(H5RS_get_str(src_path_r) + non_canon_name_len); + canon_dst_path_r = H5RS_create(H5RS_get_str(dst_path_r) + non_canon_name_len); + } /* end if */ + else { + canon_src_path_r = H5RS_dup(src_path_r); + canon_dst_path_r = H5RS_dup(dst_path_r); + } /* end else */ + + /* Check if the link being changed in the file is along the canonical path for this object */ + if(H5G_common_path(obj_path->canon_path_r, canon_src_path_r)) { + size_t user_dst_len; /* Length of destination user path */ + size_t canon_dst_len; /* Length of destination canonical path */ + const char *old_user_path; /* Pointer to previous user path */ + char *new_user_path; /* Pointer to new user path */ + char *new_canon_path; /* Pointer to new canonical path */ + const char *tail_path; /* Pointer to "tail" of path */ + size_t tail_len; /* Pointer to "tail" of path */ + char *src_canon_prefix; /* Pointer to source canonical path prefix of component which is moving */ + size_t src_canon_prefix_len;/* Length of the source canonical path prefix */ + char *dst_canon_prefix; /* Pointer to destination canonical path prefix of component which is moving */ + size_t dst_canon_prefix_len;/* Length of the destination canonical path prefix */ + char *user_prefix; /* Pointer to user path prefix of component which is moving */ + size_t user_prefix_len; /* Length of the user path prefix */ + char *src_comp; /* The source name of the component which is actually changing */ + char *dst_comp; /* The destination name of the component which is actually changing */ + const char *canon_src_path; /* pointer to canonical part of source path */ + const char *canon_dst_path; /* pointer to canonical part of destination path */ + + /* Get the pointers to the raw strings */ + canon_src_path = H5RS_get_str(canon_src_path_r); + canon_dst_path = H5RS_get_str(canon_dst_path_r); + + /* Get the source & destination components */ + src_comp = HDstrrchr(canon_src_path, '/'); + HDassert(src_comp); + dst_comp = HDstrrchr(canon_dst_path, '/'); + HDassert(dst_comp); + + /* Find the canonical prefixes for the entry */ + src_canon_prefix_len = HDstrlen(canon_src_path) - HDstrlen(src_comp); + if(NULL == (src_canon_prefix = H5MM_malloc(src_canon_prefix_len + 1))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + HDstrncpy(src_canon_prefix, canon_src_path, src_canon_prefix_len); + src_canon_prefix[src_canon_prefix_len] = '\0'; + + dst_canon_prefix_len = HDstrlen(canon_dst_path) - HDstrlen(dst_comp); + if(NULL == (dst_canon_prefix = H5MM_malloc(dst_canon_prefix_len + 1))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + HDstrncpy(dst_canon_prefix, canon_dst_path, dst_canon_prefix_len); + dst_canon_prefix[dst_canon_prefix_len] = '\0'; + + /* Hold this for later use */ + old_user_path = H5RS_get_str(obj_path->user_path_r); + + /* Find the user prefix for the entry */ + user_prefix_len = HDstrlen(old_user_path) - H5RS_len(obj_path->canon_path_r); + if(NULL == (user_prefix = H5MM_malloc(user_prefix_len + 1))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + HDstrncpy(user_prefix, old_user_path, user_prefix_len); + user_prefix[user_prefix_len] = '\0'; + + /* Set the tail path info */ + tail_path = old_user_path+user_prefix_len + src_canon_prefix_len + HDstrlen(src_comp); + tail_len = HDstrlen(tail_path); + + /* Get the length of the destination paths */ + user_dst_len = user_prefix_len + dst_canon_prefix_len + HDstrlen(dst_comp) + tail_len; + canon_dst_len = dst_canon_prefix_len + HDstrlen(dst_comp) + tail_len; + + /* Allocate space for the new user path */ + if(NULL == (new_user_path = H5FL_BLK_MALLOC(str_buf, user_dst_len + 1))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Allocate space for the new canonical path */ + if(NULL == (new_canon_path = H5FL_BLK_MALLOC(str_buf, canon_dst_len + 1))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Create the new names */ + HDstrcpy(new_user_path, user_prefix); + HDstrcat(new_user_path, dst_canon_prefix); + HDstrcat(new_user_path, dst_comp); + HDstrcat(new_user_path, tail_path); + HDstrcpy(new_canon_path, dst_canon_prefix); + HDstrcat(new_canon_path, dst_comp); + HDstrcat(new_canon_path, tail_path); + + /* Release the old user & canonical paths */ + H5RS_decr(obj_path->user_path_r); + H5RS_decr(obj_path->canon_path_r); + + /* Take ownership of the new user & canonical paths */ + obj_path->user_path_r = H5RS_own(new_user_path); + obj_path->canon_path_r = H5RS_own(new_canon_path); + + /* Free the extra paths allocated */ + H5MM_xfree(src_canon_prefix); + H5MM_xfree(dst_canon_prefix); + H5MM_xfree(user_prefix); + } /* end if */ + + + /* Free the extra paths allocated */ + H5RS_decr(src_path_r); + H5RS_decr(dst_path_r); + H5RS_decr(canon_src_path_r); + H5RS_decr(canon_dst_path_r); + } /* end if */ + else { + /* Release the old user path */ + if(obj_path->user_path_r) { + H5RS_decr(obj_path->user_path_r); + obj_path->user_path_r = NULL; + } /* end if */ + } /* end else */ + } /* end if */ + break; + + default: + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid call") + } /* end switch */ + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5G_name_replace_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_name_replace + * + * Purpose: Search the list of open IDs and replace names according to a + * particular operation. The operation occured on the LOC + * entry, which had SRC_NAME previously. The new name (if there + * is one) is DST_NAME. Additional entry location information + * (currently only needed for the 'move' operation) is passed + * in SRC_LOC and DST_LOC. + * + * Return: Success: 0, Failure: -1 + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: June 11, 2002 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_name_replace(H5G_obj_t type, H5G_loc_t *loc, + H5RS_str_t *src_name, H5G_loc_t *src_loc, + H5RS_str_t *dst_name, H5G_loc_t *dst_loc, H5G_names_op_t op) +{ + H5G_names_t names; /* Structure to hold operation information for callback */ + unsigned search_group = 0; /* Flag to indicate that groups are to be searched */ + unsigned search_dataset = 0; /* Flag to indicate that datasets are to be searched */ + unsigned search_datatype = 0; /* Flag to indicate that datatypes are to be searched */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(H5G_name_replace, FAIL) + + /* Set up common information for callback */ + names.src_name = src_name; + names.dst_name = dst_name; + names.loc = loc; + names.src_loc = src_loc; + names.dst_loc = dst_loc; + names.op = op; + + /* Determine which types of IDs need to be operated on */ + switch(type) { + /* Object is a group */ + case H5G_GROUP: + /* Search and replace names through group IDs */ + search_group = 1; + break; + + /* Object is a dataset */ + case H5G_DATASET: + /* Search and replace names through dataset IDs */ + search_dataset = 1; + break; + + /* Object is a named datatype */ + case H5G_TYPE: + /* Search and replace names through datatype IDs */ + search_datatype = 1; + break; + + case H5G_UNKNOWN: /* We pass H5G_UNKNOWN as object type when we need to search all IDs */ + case H5G_LINK: /* Symbolic links might resolve to any object, so we need to search all IDs */ + /* Check if we will need to search groups */ + if(H5I_nmembers(H5I_GROUP) > 0) + search_group = 1; + + /* Check if we will need to search datasets */ + if(H5I_nmembers(H5I_DATASET) > 0) + search_dataset = 1; + + /* Check if we will need to search datatypes */ + if(H5I_nmembers(H5I_DATATYPE) > 0) + search_datatype = 1; + break; + + default: + HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "not valid object type"); + } /* end switch */ + + /* Search through group IDs */ + if(search_group) + H5I_search(H5I_GROUP, H5G_name_replace_cb, &names); + + /* Search through dataset IDs */ + if(search_dataset) + H5I_search(H5I_DATASET, H5G_name_replace_cb, &names); + + /* Search through datatype IDs */ + if(search_datatype) + H5I_search(H5I_DATATYPE, H5G_name_replace_cb, &names); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_name_replace() */ + diff --git a/src/H5Gnode.c b/src/H5Gnode.c index 5e053fd..ca605b8 100644 --- a/src/H5Gnode.c +++ b/src/H5Gnode.c @@ -890,48 +890,39 @@ done: * matzke@llnl.gov * Jun 23 1997 * - * Modifications: - * Robb Matzke, 1999-07-28 - * The ADDR argument is passed by value. - * - * John Mainzer, 6/17/05 - * Modified the function to use the new dirtied parameter of - * of H5AC_unprotect() instead of modifying the is_dirty - * field of the cache info. - * *------------------------------------------------------------------------- */ static herr_t H5G_node_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *_lt_key, void *_udata) { - H5G_bt_ud1_t *udata = (H5G_bt_ud1_t *) _udata; + H5G_bt_ud3_t *udata = (H5G_bt_ud3_t *) _udata; H5G_node_t *sn = NULL; const H5HL_t *heap = NULL; unsigned lt = 0, idx = 0, rt; int cmp = 1; const char *s; const char *base; /* Base of heap */ - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5G_node_found); + FUNC_ENTER_NOAPI_NOINIT(H5G_node_found) /* * Check arguments. */ - assert(f); - assert(H5F_addr_defined(addr)); - assert(udata); + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(udata); /* * Load the symbol table node for exclusive access. */ - if (NULL == (sn = H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, NULL, NULL, H5AC_READ))) - HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, FAIL, "unable to protect symbol table node"); + if(NULL == (sn = H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, NULL, NULL, H5AC_READ))) + HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, FAIL, "unable to protect symbol table node") /* Get base address of heap */ - if (NULL == (heap = H5HL_protect(f, dxpl_id, udata->common.heap_addr))) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to protect symbol name"); + if(NULL == (heap = H5HL_protect(f, dxpl_id, udata->common.heap_addr))) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to protect symbol name") base = H5HL_offset_into(f, heap, 0); @@ -939,46 +930,34 @@ H5G_node_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *_lt_key * Binary search. */ rt = sn->nsyms; - while (lt < rt && cmp) { + while(lt < rt && cmp) { idx = (lt + rt) / 2; - s=base+sn->entry[idx].name_off; + s = base + sn->entry[idx].name_off; cmp = HDstrcmp(udata->common.name, s); if (cmp < 0) rt = idx; else lt = idx + 1; - } + } /* end while */ - if (H5HL_unprotect(f, dxpl_id, heap, udata->common.heap_addr, H5AC__NO_FLAGS_SET) < 0) - HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol name"); - heap=NULL; base=NULL; - - if (cmp) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "not found"); + if(H5HL_unprotect(f, dxpl_id, heap, udata->common.heap_addr, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol name") + heap = NULL; base = NULL; - /* - * The caller is querying the symbol entry, copy it into the UDATA - * entry field. - * - * (do a NULL copy, since the entry's name will be constructed later) - */ - if (H5G_ent_copy(udata->ent, &sn->entry[idx], H5G_COPY_NULL)<0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to copy entry"); + if(cmp) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "not found") - /* Leave object in same file as lookup occurs in */ - /* If a file is opened through different H5Fopen() calls, the symbol - * table entry from the B-tree lookup ("&sn->entry[idx]" above) will be - * in the "first" file, but the lookup might occur in the second file. - QAK - */ - udata->ent->file = f; + /* Call user's callback operator */ + if((udata->op)(&sn->entry[idx], udata->op_data) < 0) + HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "iterator callback failed") done: - if (sn && H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, H5AC__NO_FLAGS_SET) < 0) - HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to release symbol table node"); + if(sn && H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to release symbol table node") - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_node_found() */ /*------------------------------------------------------------------------- @@ -1013,59 +992,50 @@ done: * matzke@llnl.gov * Jun 24 1997 * - * Modifications: - * Robb Matzke, 1999-07-28 - * The ADDR argument is passed by value. - * - * John Mainzer, 6/8/05 - * Modified the function to use the new dirtied parameter of - * of H5AC_unprotect() instead of modifying the is_dirty - * field of the cache info. - * *------------------------------------------------------------------------- */ static H5B_ins_t -H5G_node_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, void UNUSED *_lt_key, - hbool_t UNUSED *lt_key_changed, void *_md_key, - void *_udata, void *_rt_key, hbool_t *rt_key_changed, - haddr_t *new_node_p) +H5G_node_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, + void UNUSED *_lt_key, hbool_t UNUSED *lt_key_changed, + void *_md_key, void *_udata, + void *_rt_key, hbool_t *rt_key_changed, + haddr_t *new_node_p) { H5G_node_key_t *md_key = (H5G_node_key_t *) _md_key; H5G_node_key_t *rt_key = (H5G_node_key_t *) _rt_key; H5G_bt_ud1_t *udata = (H5G_bt_ud1_t *) _udata; - H5G_node_t *sn = NULL, *snrt = NULL; unsigned sn_flags = H5AC__NO_FLAGS_SET, snrt_flags = H5AC__NO_FLAGS_SET; const H5HL_t *heap = NULL; - size_t offset; /*offset of name in heap */ const char *s; const char *base; /* Base of heap */ unsigned lt = 0, rt; /* Binary search cntrs */ int cmp = 1, idx = -1; H5G_node_t *insert_into = NULL; /*node that gets new entry*/ + H5G_entry_t ent; /* Entry to insert in node */ H5B_ins_t ret_value = H5B_INS_ERROR; - FUNC_ENTER_NOAPI_NOINIT(H5G_node_insert); + FUNC_ENTER_NOAPI_NOINIT(H5G_node_insert) /* * Check arguments. */ - assert(f); - assert(H5F_addr_defined(addr)); - assert(md_key); - assert(rt_key); - assert(udata); - assert(new_node_p); + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(md_key); + HDassert(rt_key); + HDassert(udata); + HDassert(new_node_p); /* * Load the symbol node. */ - if (NULL == (sn = H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, NULL, NULL, H5AC_WRITE))) - HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR, "unable to protect symbol table node"); + if(NULL == (sn = H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, NULL, NULL, H5AC_WRITE))) + HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR, "unable to protect symbol table node") /* Get base address of heap */ - if (NULL == (heap = H5HL_protect(f, dxpl_id, udata->common.heap_addr))) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5B_INS_ERROR, "unable to protect symbol name"); + if(NULL == (heap = H5HL_protect(f, dxpl_id, udata->common.heap_addr))) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5B_INS_ERROR, "unable to protect symbol name") base = H5HL_offset_into(f, heap, 0); @@ -1073,40 +1043,37 @@ H5G_node_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, void UNUSED *_lt_key, * Where does the new symbol get inserted? We use a binary search. */ rt = sn->nsyms; - while (lt < rt) { + while(lt < rt) { idx = (lt + rt) / 2; - s=base+sn->entry[idx].name_off; + s = base + sn->entry[idx].name_off; - if (0 == (cmp = HDstrcmp(udata->common.name, s))) /*already present */ { + if(0 == (cmp = HDstrcmp(udata->common.name, s))) /*already present */ { HCOMMON_ERROR(H5E_SYM, H5E_CANTINSERT, "symbol is already present in symbol table"); - if (H5HL_unprotect(f, dxpl_id, heap, udata->common.heap_addr, H5AC__NO_FLAGS_SET) < 0) - HGOTO_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to unprotect symbol name"); - heap=NULL; base=NULL; + if(H5HL_unprotect(f, dxpl_id, heap, udata->common.heap_addr, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to unprotect symbol name") + heap = NULL; base = NULL; - HGOTO_DONE(H5B_INS_ERROR); - } + HGOTO_DONE(H5B_INS_ERROR) + } /* end if */ if (cmp < 0) rt = idx; else lt = idx + 1; - } + } /* end while */ idx += cmp > 0 ? 1 : 0; - if (H5HL_unprotect(f, dxpl_id, heap, udata->common.heap_addr, H5AC__NO_FLAGS_SET) < 0) - HGOTO_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to unprotect symbol name"); - heap=NULL; base=NULL; + if(H5HL_unprotect(f, dxpl_id, heap, udata->common.heap_addr, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to unprotect symbol name") + heap = NULL; base = NULL; - /* - * Add the new name to the heap. - */ - offset = H5HL_insert(f, dxpl_id, udata->common.heap_addr, HDstrlen(udata->common.name)+1, - udata->common.name); - udata->ent->name_off = offset; - if (0==offset || (size_t)(-1)==offset) - HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, H5B_INS_ERROR, "unable to insert symbol name into heap"); - if (sn->nsyms >= 2*H5F_SYM_LEAF_K(f)) { + /* Convert link information & name to symbol table entry */ + if(H5G_ent_convert(f, udata->common.heap_addr, udata->common.name, udata->lnk, &ent, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCONVERT, H5B_INS_ERROR, "unable to convert link") + + /* Determine where to place entry in node */ + if(sn->nsyms >= 2 * H5F_SYM_LEAF_K(f)) { /* * The node is full. Split it into a left and right * node and return the address of the new right node (the @@ -1115,12 +1082,11 @@ H5G_node_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, void UNUSED *_lt_key, ret_value = H5B_INS_RIGHT; /* The right node */ - if (H5G_node_create(f, dxpl_id, H5B_INS_FIRST, NULL, NULL, NULL, - new_node_p/*out*/)<0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, H5B_INS_ERROR, "unable to split symbol table node"); + if(H5G_node_create(f, dxpl_id, H5B_INS_FIRST, NULL, NULL, NULL, new_node_p/*out*/) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, H5B_INS_ERROR, "unable to split symbol table node") - if (NULL == (snrt = H5AC_protect(f, dxpl_id, H5AC_SNODE, *new_node_p, NULL, NULL, H5AC_WRITE))) - HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR, "unable to split symbol table node"); + if(NULL == (snrt = H5AC_protect(f, dxpl_id, H5AC_SNODE, *new_node_p, NULL, NULL, H5AC_WRITE))) + HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR, "unable to split symbol table node") HDmemcpy(snrt->entry, sn->entry + H5F_SYM_LEAF_K(f), H5F_SYM_LEAF_K(f) * sizeof(H5G_entry_t)); @@ -1137,37 +1103,35 @@ H5G_node_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, void UNUSED *_lt_key, md_key->offset = sn->entry[sn->nsyms - 1].name_off; /* Where to insert the new entry? */ - if (idx <= (int)H5F_SYM_LEAF_K(f)) { + if(idx <= (int)H5F_SYM_LEAF_K(f)) { insert_into = sn; - if (idx == (int)H5F_SYM_LEAF_K(f)) - md_key->offset = offset; + if(idx == (int)H5F_SYM_LEAF_K(f)) + md_key->offset = ent.name_off; } else { idx -= H5F_SYM_LEAF_K(f); insert_into = snrt; - if (idx == (int)H5F_SYM_LEAF_K (f)) { - rt_key->offset = offset; + if(idx == (int)H5F_SYM_LEAF_K (f)) { + rt_key->offset = ent.name_off; *rt_key_changed = TRUE; - } - } + } /* end if */ + } /* end else */ } else { /* Where to insert the new entry? */ ret_value = H5B_INS_NOOP; sn_flags |= H5AC__DIRTIED_FLAG; insert_into = sn; - if (idx == (int)sn->nsyms) { - rt_key->offset = offset; + if(idx == (int)sn->nsyms) { + rt_key->offset = ent.name_off; *rt_key_changed = TRUE; - } - } + } /* end if */ + } /* end else */ /* Move entries down to make room for new entry */ - HDmemmove(insert_into->entry + idx + 1, - insert_into->entry + idx, + HDmemmove(insert_into->entry + idx + 1, insert_into->entry + idx, (insert_into->nsyms - idx) * sizeof(H5G_entry_t)); /* Copy new entry into table */ - /* (use H5G_COPY_NULL because we don't track the object names in the table) */ - H5G_ent_copy(&(insert_into->entry[idx]), udata->ent, H5G_COPY_NULL); + H5G_ent_copy(&(insert_into->entry[idx]), &ent, H5G_COPY_SHALLOW); /* Flag entry as dirty */ insert_into->entry[idx].dirty = TRUE; @@ -1176,13 +1140,13 @@ H5G_node_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, void UNUSED *_lt_key, insert_into->nsyms += 1; done: - if (snrt && H5AC_unprotect(f, dxpl_id, H5AC_SNODE, *new_node_p, snrt, snrt_flags) < 0) - HDONE_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to release symbol table node"); - if (sn && H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, sn_flags) < 0) - HDONE_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to release symbol table node"); + if(snrt && H5AC_unprotect(f, dxpl_id, H5AC_SNODE, *new_node_p, snrt, snrt_flags) < 0) + HDONE_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to release symbol table node") + if(sn && H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, sn_flags) < 0) + HDONE_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to release symbol table node") - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_node_insert() */ /*------------------------------------------------------------------------- @@ -1240,129 +1204,141 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/, H5G_node_t *sn = NULL; unsigned sn_flags = H5AC__NO_FLAGS_SET; const H5HL_t *heap = NULL; - unsigned lt=0, rt, idx=0; - int cmp=1; + unsigned lt = 0, rt, idx = 0; + int cmp = 1; const char *s = NULL; const char *base; /* Base of heap */ H5B_ins_t ret_value = H5B_INS_ERROR; - FUNC_ENTER_NOAPI_NOINIT(H5G_node_remove); + FUNC_ENTER_NOAPI_NOINIT(H5G_node_remove) /* Check arguments */ - assert(f); - assert(H5F_addr_defined(addr)); - assert(lt_key); - assert(rt_key); - assert(udata); + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(lt_key); + HDassert(rt_key); + HDassert(udata); /* Load the symbol table */ - if (NULL==(sn=H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, NULL, NULL, H5AC_WRITE))) - HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR, "unable to protect symbol table node"); + if(NULL == (sn = H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, NULL, NULL, H5AC_WRITE))) + HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR, "unable to protect symbol table node") /* "Normal" removal of a single entry from the symbol table node */ - if(udata->common.name!=NULL) { - size_t len=0; + if(udata->common.name != NULL) { + size_t len = 0; hbool_t found; /* Indicate that the string was found */ /* Get base address of heap */ - if (NULL == (heap = H5HL_protect(f, dxpl_id, udata->common.heap_addr))) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5B_INS_ERROR, "unable to protect symbol name"); + if(NULL == (heap = H5HL_protect(f, dxpl_id, udata->common.heap_addr))) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5B_INS_ERROR, "unable to protect symbol name") base = H5HL_offset_into(f, heap, 0); /* Find the name with a binary search */ rt = sn->nsyms; - while (lt<rt && cmp) { - idx = (lt+rt)/2; - s=base+sn->entry[idx].name_off; + while(lt < rt && cmp) { + idx = (lt + rt) / 2; + s = base + sn->entry[idx].name_off; cmp = HDstrcmp(udata->common.name, s); - if (cmp<0) { + if(cmp < 0) rt = idx; - } else { - lt = idx+1; - } - } + else + lt = idx + 1; + } /* end while */ - if (H5HL_unprotect(f, dxpl_id, heap, udata->common.heap_addr, H5AC__NO_FLAGS_SET) < 0) - HDONE_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to unprotect symbol name"); - heap=NULL; base=NULL; + if(H5HL_unprotect(f, dxpl_id, heap, udata->common.heap_addr, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to unprotect symbol name") + heap = NULL; base = NULL; - if (cmp) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5B_INS_ERROR, "not found"); + if(cmp) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5B_INS_ERROR, "not found") + + if(H5G_CACHED_SLINK == sn->entry[idx].type) { + /* Set the type of the link removed */ + *(udata->obj_type) = H5G_LINK; - if (H5G_CACHED_SLINK==sn->entry[idx].type) { /* Remove the symbolic link value */ - if (NULL == (heap = H5HL_protect(f, dxpl_id, udata->common.heap_addr))) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5B_INS_ERROR, "unable to protect symbol name"); + if(NULL == (heap = H5HL_protect(f, dxpl_id, udata->common.heap_addr))) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5B_INS_ERROR, "unable to protect symbol name") s = H5HL_offset_into(f, heap, sn->entry[idx].cache.slink.lval_offset); - if (s) { - len=HDstrlen(s)+1; - found=1; + if(s) { + len = HDstrlen(s) + 1; + found = 1; } /* end if */ else - found=0; + found = 0; - if (H5HL_unprotect(f, dxpl_id, heap, udata->common.heap_addr, H5AC__NO_FLAGS_SET) < 0) - HGOTO_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to unprotect symbol name"); - heap=NULL; s=NULL; + if(H5HL_unprotect(f, dxpl_id, heap, udata->common.heap_addr, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to unprotect symbol name") + heap = NULL; s = NULL; - if (found) + if(found) H5HL_remove(f, dxpl_id, udata->common.heap_addr, sn->entry[idx].cache.slink.lval_offset, len); H5E_clear_stack(NULL); /* no big deal */ } else { + H5O_loc_t tmp_oloc; /* Temporary object location */ + + /* Build temporary object location */ + tmp_oloc.file = f; + HDassert(H5F_addr_defined(sn->entry[idx].header)); + tmp_oloc.addr = sn->entry[idx].header; + + /* Get the type of the object */ + if((*(udata->obj_type) = H5O_obj_type(&tmp_oloc, dxpl_id)) == H5G_UNKNOWN) + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5B_INS_ERROR, "unable to determine object type") + /* Decrement the reference count, if requested */ if(udata->adj_link) { - HDassert(H5F_addr_defined(sn->entry[idx].header)); - if (H5O_link(sn->entry+idx, -1, dxpl_id)<0) + if(H5O_link(&tmp_oloc, -1, dxpl_id) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, H5B_INS_ERROR, "unable to decrement object link count") } /* end if */ - } + } /* end else */ /* Remove the name from the local heap */ - if (NULL == (heap = H5HL_protect(f, dxpl_id, udata->common.heap_addr))) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5B_INS_ERROR, "unable to protect symbol name"); + if(NULL == (heap = H5HL_protect(f, dxpl_id, udata->common.heap_addr))) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5B_INS_ERROR, "unable to protect symbol name") s = H5HL_offset_into(f, heap, sn->entry[idx].name_off); - if (s) { - len=HDstrlen(s)+1; - found=1; + if(s) { + len = HDstrlen(s) + 1; + found = 1; } /* end if */ else - found=0; + found = 0; - if (H5HL_unprotect(f, dxpl_id, heap, udata->common.heap_addr, H5AC__NO_FLAGS_SET) < 0) - HGOTO_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to unprotect symbol name"); - heap=NULL; s=NULL; + if(H5HL_unprotect(f, dxpl_id, heap, udata->common.heap_addr, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to unprotect symbol name") + heap = NULL; s = NULL; - if (found) + if(found) H5HL_remove(f, dxpl_id, udata->common.heap_addr, sn->entry[idx].name_off, len); H5E_clear_stack(NULL); /* no big deal */ /* Remove the entry from the symbol table node */ - if(1==sn->nsyms) { + if(1 == sn->nsyms) { /* * We are about to remove the only symbol in this node. Copy the left * key to the right key and mark the right key as dirty. Free this * node and indicate that the pointer to this node in the B-tree * should be removed also. */ - assert(0==idx); + HDassert(0 == idx); *rt_key = *lt_key; *rt_key_changed = TRUE; sn->nsyms = 0; - if (H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, addr, (hsize_t)H5G_node_size(f))<0 - || H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, H5AC__DIRTIED_FLAG | H5C__DELETED_FLAG)<0) { + if(H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, addr, (hsize_t)H5G_node_size(f)) < 0 + || H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, H5AC__DIRTIED_FLAG | H5C__DELETED_FLAG) < 0) { sn = NULL; - HGOTO_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to free symbol table node"); - } + HGOTO_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to free symbol table node") + } /* end if */ sn = NULL; ret_value = H5B_INS_REMOVE; - } else if (0==idx) { + } else if(0 == idx) { /* * We are about to remove the left-most entry from the symbol table * node but there are other entries to the right. No key values @@ -1370,11 +1346,11 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/, */ sn->nsyms -= 1; sn_flags |= H5AC__DIRTIED_FLAG; - HDmemmove(sn->entry+idx, sn->entry+idx+1, - (sn->nsyms-idx)*sizeof(H5G_entry_t)); + HDmemmove(sn->entry + idx, sn->entry + idx + 1, + (sn->nsyms-idx) * sizeof(H5G_entry_t)); ret_value = H5B_INS_NOOP; - } else if (idx+1==sn->nsyms) { + } else if (idx + 1 == sn->nsyms) { /* * We are about to remove the right-most entry from the symbol table * node but there are other entries to the left. The right key @@ -1382,7 +1358,7 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/, */ sn->nsyms -= 1; sn_flags |= H5AC__DIRTIED_FLAG; - rt_key->offset = sn->entry[sn->nsyms-1].name_off; + rt_key->offset = sn->entry[sn->nsyms - 1].name_off; *rt_key_changed = TRUE; ret_value = H5B_INS_NOOP; @@ -1393,20 +1369,27 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/, */ sn->nsyms -= 1; sn_flags |= H5AC__DIRTIED_FLAG; - HDmemmove(sn->entry+idx, sn->entry+idx+1, - (sn->nsyms-idx)*sizeof(H5G_entry_t)); + HDmemmove(sn->entry + idx, sn->entry + idx + 1, + (sn->nsyms - idx) * sizeof(H5G_entry_t)); ret_value = H5B_INS_NOOP; - } + } /* end else */ } /* end if */ /* Remove all entries from node, during B-tree deletion */ else { + H5O_loc_t tmp_oloc; /* Temporary object location */ + + /* Build temporary object location */ + tmp_oloc.file = f; + /* Reduce the link count for all entries in this node */ - for(idx=0; idx<sn->nsyms; idx++) { - if (H5G_CACHED_SLINK!=sn->entry[idx].type) { + for(idx = 0; idx < sn->nsyms; idx++) { + if(H5G_CACHED_SLINK != sn->entry[idx].type) { /* Decrement the reference count, if requested */ if(udata->adj_link) { HDassert(H5F_addr_defined(sn->entry[idx].header)); - if (H5O_link(sn->entry+idx, -1, dxpl_id)<0) + tmp_oloc.addr = sn->entry[idx].header; + + if(H5O_link(&tmp_oloc, -1, dxpl_id) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, H5B_INS_ERROR, "unable to decrement object link count") } /* end if */ } /* end if */ @@ -1421,21 +1404,21 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/, *rt_key = *lt_key; *rt_key_changed = TRUE; sn->nsyms = 0; - if (H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, addr, (hsize_t)H5G_node_size(f))<0 - || H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, H5AC__DIRTIED_FLAG | H5C__DELETED_FLAG)<0) { + if(H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, addr, (hsize_t)H5G_node_size(f)) < 0 + || H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, H5AC__DIRTIED_FLAG | H5C__DELETED_FLAG) < 0) { sn = NULL; - HGOTO_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to free symbol table node"); - } + HGOTO_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to free symbol table node") + } /* end if */ sn = NULL; ret_value = H5B_INS_REMOVE; } /* end else */ done: - if (sn && H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, sn_flags)<0) - HDONE_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to release symbol table node"); + if(sn && H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, sn_flags) < 0) + HDONE_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to release symbol table node") - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_node_remove() */ /*------------------------------------------------------------------------- @@ -1538,7 +1521,7 @@ H5G_node_iterate (H5F_t *f, hid_t dxpl_id, const void UNUSED *_lt_key, haddr_t a /* Increment the number of entries passed through */ /* (whether we skipped them or not) */ - udata->final_ent++; + (*udata->final_ent)++; } if (ret_value<0) HERROR (H5E_SYM, H5E_CANTNEXT, "iteration operator failed"); @@ -1695,13 +1678,6 @@ done: * Programmer: Raymond Lu * Nov 20, 2002 * - * Modifications: - * - * John Mainzer, 6/17/05 - * Modified the function to use the new dirtied parameter of - * of H5AC_unprotect() instead of modifying the is_dirty - * field of the cache info. - * *------------------------------------------------------------------------- */ int @@ -1709,35 +1685,114 @@ H5G_node_type(H5F_t *f, hid_t dxpl_id, const void UNUSED *_lt_key, haddr_t addr, const void UNUSED *_rt_key, void *_udata) { H5G_bt_it_ud3_t *udata = (H5G_bt_it_ud3_t*)_udata; - hsize_t loc_idx; H5G_node_t *sn = NULL; int ret_value = H5B_ITER_CONT; - FUNC_ENTER_NOAPI(H5G_node_type, H5B_ITER_ERROR); + FUNC_ENTER_NOAPI(H5G_node_type, H5B_ITER_ERROR) /* Check arguments. */ - assert(f); - assert(H5F_addr_defined(addr)); - assert(udata); + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(udata); /* Find the node, locate the object symbol table entry and retrieve the type */ - if (NULL == (sn = H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, NULL, NULL, H5AC_READ))) + if(NULL == (sn = H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, NULL, NULL, H5AC_READ))) HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_ITER_ERROR, "unable to load symbol table node"); if(udata->idx >= udata->num_objs && udata->idx < (udata->num_objs + sn->nsyms)) { + H5O_loc_t tmp_oloc; /* Temporary object location */ + hsize_t loc_idx; + + /* Compute index of entry */ loc_idx = udata->idx - udata->num_objs; - udata->type = H5G_get_type(&(sn->entry[loc_idx]), dxpl_id); + + /* Build temporary object location */ + tmp_oloc.file = f; + HDassert(H5F_addr_defined(sn->entry[loc_idx].header)); + tmp_oloc.addr = sn->entry[loc_idx].header; + + udata->type = H5O_obj_type(&tmp_oloc, dxpl_id); ret_value = H5B_ITER_STOP; } else { udata->num_objs += sn->nsyms; - } + } /* end else */ done: - if (sn && H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, H5AC__NO_FLAGS_SET) != SUCCEED) + if(sn && H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, H5AC__NO_FLAGS_SET) != SUCCEED) HDONE_ERROR(H5E_SYM, H5E_PROTECT, H5B_ITER_ERROR, "unable to release object header"); FUNC_LEAVE_NOAPI(ret_value); -} +} /* end H5G_node_type() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_node_stab_convert + * + * Purpose: This function gets called when the entries in a group are + * converted from a symbol table to link messages. + * + * Return: 0 if object isn't found in this node; 1 if found; + * Negative on failure + * + * Programmer: Quincey Koziol + * Sep 5, 2005 + * + *------------------------------------------------------------------------- + */ +int +H5G_node_stab_convert(H5F_t *f, hid_t dxpl_id, const void UNUSED *_lt_key, haddr_t addr, + const void UNUSED *_rt_key, void *_udata) +{ + H5G_bt_it_ud4_t *udata = (H5G_bt_it_ud4_t*)_udata; + H5G_node_t *sn = NULL; /* Pointer to symbol table node to operate on */ + const H5HL_t *heap = NULL; /* Pointer to local heap for group */ + const char *name; /* Pointer to name of link */ + const H5G_entry_t *ent; /* Pointer to current entry */ + unsigned u; /* Local index variable */ + int ret_value = H5B_ITER_CONT; + + FUNC_ENTER_NOAPI(H5G_node_stab_convert, H5B_ITER_ERROR) + + /* Check arguments. */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(udata); + + /* Lock the symbol table node */ + if(NULL == (sn = H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, NULL, NULL, H5AC_READ))) + HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_ITER_ERROR, "unable to load symbol table node") + + /* Lock the local heap */ + if(NULL == (heap = H5HL_protect(f, dxpl_id, udata->heap_addr))) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5B_ITER_ERROR, "unable to protect symbol name") + + /* Convert all the entries from this node into link messages */ + for(u = 0, ent = sn->entry; u < sn->nsyms; u++, ent++) { + /* Get a pointer to the link's name in the local heap */ + name = H5HL_offset_into(f, heap, ent->name_off); + HDassert(name); + + /* Check for too many links for link table */ + if(udata->nlinks >= udata->max_links) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "too many links for table") + + /* Convert entry into link message object */ + if(H5G_link_convert(&(udata->lnk_table[udata->nlinks]), ent, heap, name) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCONVERT, FAIL, "can't convert entry to link message") + + /* Increment number of links stored */ + udata->nlinks++; + } /* end for */ + +done: + if(heap && H5HL_unprotect(f, dxpl_id, heap, udata->heap_addr, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_SYM, H5E_PROTECT, H5B_ITER_ERROR, "unable to unprotect symbol name") + + if(sn && H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, H5AC__NO_FLAGS_SET) != SUCCEED) + HDONE_ERROR(H5E_SYM, H5E_PROTECT, H5B_ITER_ERROR, "unable to release object header") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_node_stab_convert() */ /*------------------------------------------------------------------------- @@ -1898,62 +1953,74 @@ H5G_node_copy(H5F_t *f, hid_t dxpl_id, const void UNUSED *_lt_key, haddr_t addr, HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_ITER_ERROR, "unable to load symbol table node") /* get the base address of the heap */ - if(NULL == (heap = H5HL_protect(f, dxpl_id, udata->heap_addr))) + if(NULL == (heap = H5HL_protect(f, dxpl_id, udata->src_heap_addr))) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5B_ITER_ERROR, "unable to protect symbol name") /* copy object in this node one by one */ for(i = 0; i < sn->nsyms; i++) { - H5G_entry_t ent_new; /* New entry to insert into dest. group */ - H5G_entry_t *ent_src = &(sn->entry[i]); /* Convenience variable to refer to current source group entry */ + H5G_entry_t *src_ent = &(sn->entry[i]); /* Convenience variable to refer to current source group entry */ + H5O_loc_t new_oloc; /* Copied object object location */ + H5O_link_t lnk; /* Link to insert */ const char *name; /* Name of source object */ - /* Set up symbol table entry for destination */ - H5G_ent_reset(&ent_new); - ent_new.file = udata->loc_dst->file; - - /* Determine name of source object */ - name = H5HL_offset_into(f, heap, ent_src->name_off); - HDassert(name); + /* Set up copied object location to fill in */ + H5O_loc_reset(&new_oloc); + new_oloc.file = udata->dst_file; /* Check if object in source group is a hard link */ - if(H5F_addr_defined(ent_src->header)) { + if(H5F_addr_defined(src_ent->header)) { + H5O_loc_t src_oloc; /* Temporary object location for source object */ + + /* Build temporary object location for source */ + src_oloc.file = f; + HDassert(H5F_addr_defined(src_ent->header)); + src_oloc.addr = src_ent->header; + /* Copy the shared object from source to destination */ /* (Increments link count on destination) */ - if(H5O_copy_header_map(ent_src, &ent_new, dxpl_id, udata->map_list) < 0) + if(H5O_copy_header_map(&src_oloc, &new_oloc, dxpl_id, udata->map_list) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, H5B_ITER_ERROR, "unable to copy object") - } /* ( H5F_addr_defined(ent_src->header)) */ - else if(H5G_CACHED_SLINK == ent_src->type) { + + /* Construct link information for eventual insertion */ + lnk.type = H5G_LINK_HARD; + lnk.u.hard.addr = new_oloc.addr; + } /* ( H5F_addr_defined(src_ent->header)) */ + else if(H5G_CACHED_SLINK == src_ent->type) { /* it is a soft link */ - H5O_stab_t stab_mesg; - size_t offset_link; - char *name_link = H5HL_offset_into(f, heap, ent_src->cache.slink.lval_offset); - - /* read the symbol table where the soft link to be inserted */ - if(NULL == H5O_read(udata->loc_dst, H5O_STAB_ID, 0, &stab_mesg, dxpl_id)) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, H5B_ITER_ERROR, "unable to determine local heap address") - if((size_t)(-1) == (offset_link = H5HL_insert(udata->loc_dst->file, dxpl_id, - stab_mesg.heap_addr, HDstrlen(name_link) + 1, name_link))) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, H5B_ITER_ERROR, "unable to write link value to local heap") - H5O_reset (H5O_STAB_ID, &stab_mesg); - - /* Set up soft link to insert */ - ent_new.type = H5G_CACHED_SLINK; - ent_new.cache.slink.lval_offset = offset_link; + + /* Construct link information for eventual insertion */ + lnk.type = H5G_LINK_SOFT; + lnk.u.soft.name = H5HL_offset_into(f, heap, src_ent->cache.slink.lval_offset); } /* else if */ else HDassert(0 && "Unknown entry type"); + /* Set up common link data */ +#ifdef H5_HAVE_GETTIMEOFDAY + { + struct timeval now_tv; + + HDgettimeofday(&now_tv, NULL); + lnk.ctime = now_tv.tv_sec; + } +#else /* H5_HAVE_GETTIMEOFDAY */ + lnk.ctime = HDtime(NULL); +#endif /* H5_HAVE_GETTIMEOFDAY */ + lnk.cset = H5T_CSET_ASCII; /* XXX: Allow user to set this */ + /* lnk.name = name; */ /* This will be set in callback */ + + /* Determine name of source object */ + name = H5HL_offset_into(f, heap, src_ent->name_off); + HDassert(name); + /* Insert the new object in the destination file's group */ /* (Don't increment the link count - that's already done above for hard links) */ - if(H5G_stab_insert(udata->loc_dst, name, &ent_new, FALSE, dxpl_id) < 0) + if(H5G_stab_insert_real(udata->dst_file, udata->dst_stab, name, &lnk, dxpl_id) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5B_ITER_ERROR, "unable to insert the name") - - /* Free the ID to name buffers */ - H5G_free_ent_name(&ent_new); } /* end of for (i=0; i<sn->nsyms; i++) */ done: - if (heap && H5HL_unprotect(f, dxpl_id, heap, udata->heap_addr, H5AC__NO_FLAGS_SET) < 0) + if (heap && H5HL_unprotect(f, dxpl_id, heap, udata->src_heap_addr, H5AC__NO_FLAGS_SET) < 0) HDONE_ERROR(H5E_SYM, H5E_PROTECT, H5B_ITER_ERROR, "unable to unprotect symbol name") if (sn && H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, H5AC__NO_FLAGS_SET) != SUCCEED) diff --git a/src/H5Gobj.c b/src/H5Gobj.c new file mode 100644 index 0000000..a178e93 --- /dev/null +++ b/src/H5Gobj.c @@ -0,0 +1,884 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5Gobj.c + * Sep 5 2005 + * Quincey Koziol <koziol@ncsa.uiuc.edu> + * + * Purpose: Functions for abstract handling of objects in groups. + * + *------------------------------------------------------------------------- + */ +#define H5F_PACKAGE /*suppress error about including H5Fpkg */ +#define H5G_PACKAGE /*suppress error about including H5Gpkg */ + + +/* Packages needed by this file... */ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Fpkg.h" /* File access */ +#include "H5Gpkg.h" /* Groups */ +#include "H5HLprivate.h" /* Local Heaps */ +#include "H5Iprivate.h" /* IDs */ +#include "H5MMprivate.h" /* Memory management */ + +/* Private typedefs */ + +/* User data for converting link messages to symbol table */ +typedef struct { + H5F_t *f; /* Pointer to file for insertion */ + haddr_t btree_addr; /* Address of symbol table B-tree */ + haddr_t heap_addr; /* Address of symbol table local heap */ + hid_t dxpl_id; /* DXPL during insertion */ +} H5G_obj_ud1_t; + +/* User data for looking up an object in a group */ +typedef struct { + H5O_loc_t *oloc; /* Object location to set */ +} H5G_obj_ud2_t; + +/* Private macros */ + +/* PRIVATE PROTOTYPES */ +static herr_t +H5G_obj_link_to_stab_cb(const void *_mesg, unsigned idx, void *_udata); + + +/*------------------------------------------------------------------------- + * Function: H5G_obj_create + * + * Purpose: Create an object header for a group and update object location info + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Sep 29 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_obj_create(H5F_t *f, hid_t dxpl_id, H5O_ginfo_t *ginfo, H5O_loc_t *oloc/*out*/) +{ + H5O_linfo_t linfo; /* Link information */ + H5O_link_t lnk; /* Temporary link message info for computing message size */ + char null_char = '\0'; /* Character for creating null string */ + size_t ginfo_size; /* Size of the group info message */ + size_t linfo_size; /* Size of the link info message */ + size_t link_size; /* Size of a link message */ + size_t hdr_size; /* Size of object header to request */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_obj_create, FAIL) + + /* + * Check arguments. + */ + HDassert(f); + HDassert(ginfo); + HDassert(oloc); + + /* Initialize message information */ + linfo.nlinks = 0; + + /* Calculate message size infomation, for creating group's object header */ + linfo_size = H5O_mesg_size(H5O_LINFO_ID, f, &linfo); + HDassert(linfo_size); + + ginfo_size = H5O_mesg_size(H5O_GINFO_ID, f, ginfo); + HDassert(ginfo_size); + + lnk.type = H5G_LINK_HARD; + lnk.name = &null_char; + link_size = H5O_mesg_size(H5O_LINK_ID, f, &lnk); + HDassert(link_size); + + /* Compute size of header to use for creation */ + hdr_size = linfo_size + + ginfo_size + + (ginfo->est_num_entries * (link_size + ginfo->est_name_len)); + + /* + * Create symbol table object header. It has a zero link count + * 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, dxpl_id, hdr_size, oloc/*out*/) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create header") + + /* Insert link info message */ + if(H5O_modify(oloc, H5O_LINFO_ID, H5O_NEW_MESG, 0, 0, &linfo, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create message") + + /* Insert group info message */ + if(H5O_modify(oloc, H5O_GINFO_ID, H5O_NEW_MESG, H5O_FLAG_CONSTANT, H5O_UPDATE_TIME, ginfo, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create message") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_obj_create() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_obj_ent_decode + * + * Purpose: Decodes a symbol table entry into a object location + * + * Return: Success: Non-negative with *pp pointing to the first byte + * following the symbol table entry. + * + * Failure: Negative + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Sep 26 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_obj_ent_decode(H5F_t *f, const uint8_t **pp, H5O_loc_t *oloc) +{ + const uint8_t *p_ret = *pp; + + FUNC_ENTER_NOAPI_NOFUNC(H5G_obj_ent_decode) + + /* check arguments */ + HDassert(f); + HDassert(pp); + HDassert(oloc); + + /* Set file pointer for root object location */ + oloc->file = f; + + /* decode header */ + *pp += H5F_SIZEOF_SIZE(f); /* Skip over local heap address */ + H5F_addr_decode(f, pp, &(oloc->addr)); + *pp += 4; /* Skip over "cache type" */ + *pp += 4; /* Reserved */ + + /* Set decode pointer */ + *pp = p_ret + H5G_SIZEOF_ENTRY(f); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5G_obj_ent_decode() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_obj_ent_encode + * + * Purpose: Encodes the specified object location into a symbol table + * entry in the buffer pointed to by *pp. + * + * Return: Success: Non-negative, with *pp pointing to the first byte + * after the symbol table entry. + * + * Failure: Negative + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Sep 26 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_obj_ent_encode(H5F_t *f, uint8_t **pp, const H5O_loc_t *oloc) +{ + uint8_t *p_ret = *pp + H5G_SIZEOF_ENTRY(f); + + FUNC_ENTER_NOAPI_NOFUNC(H5G_obj_ent_encode) + + /* check arguments */ + HDassert(f); + HDassert(pp); + + /* encode header */ + H5F_ENCODE_LENGTH(f, *pp, 0); /* No name for root group */ + if(oloc) + H5F_addr_encode(f, pp, oloc->addr); + else + H5F_addr_encode(f, pp, HADDR_UNDEF); + UINT32ENCODE(*pp, H5G_NOTHING_CACHED); + UINT32ENCODE(*pp, 0); /*reserved*/ + + /* fill with zero */ + while(*pp < p_ret) + *(*pp)++ = 0; + *pp = p_ret; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5G_obj_ent_encode() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_obj_link_to_stab_cb + * + * Purpose: Callback routine for converting 'link' messages to symbol table + * form. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Aug 30 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_obj_link_to_stab_cb(const void *_mesg, unsigned UNUSED idx, void *_udata) +{ + const H5O_link_t *lnk = (const H5O_link_t *)_mesg; /* Pointer to link */ + H5G_obj_ud1_t *udata = (H5G_obj_ud1_t *)_udata; /* 'User data' passed in */ + H5G_bt_ud1_t bt_udata; /* Data to pass through B-tree */ + herr_t ret_value = H5O_ITER_CONT; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5G_obj_link_to_stab_cb) + + /* check arguments */ + HDassert(lnk); + HDassert(udata); + + /* Construct user data to pass through B-tree routines */ + bt_udata.common.name = lnk->name; + bt_udata.common.heap_addr = udata->heap_addr; + bt_udata.lnk = lnk; + + /* Insert entry into symbol table */ + if(H5B_insert(udata->f, udata->dxpl_id, H5B_SNODE, udata->btree_addr, &bt_udata) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert entry") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_obj_link_to_stab_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_obj_insert + * + * Purpose: Insert a new symbol into the group described by GRP_OLOC. + * file F. The name of the new symbol is NAME and its symbol + * table entry is OBJ_LNK. Optionally, increment the reference + * count for the object the link points to with INC_LINK. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Sep 6 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_obj_insert(H5O_loc_t *grp_oloc, const char *name, H5O_link_t *obj_lnk, + hbool_t inc_link, hid_t dxpl_id) +{ + H5O_linfo_t linfo; /* Link info message */ + htri_t linfo_exists; /* Whether the link info is present */ + hbool_t use_stab; /* Whether to use symbol table for insertions or not */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_obj_insert, FAIL) + + /* check arguments */ + HDassert(grp_oloc && grp_oloc->file); + HDassert(name && *name); + HDassert(obj_lnk); + + /* Check if we have information about the number of objects in this group */ + if((linfo_exists = H5O_exists(grp_oloc, H5O_LINFO_ID, 0, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to check for link info") + if(linfo_exists) { + htri_t stab_exists; /* Whether the symbol table info is present */ + + /* Get the number of objects in this group */ + if(NULL == H5O_read(grp_oloc, H5O_LINFO_ID, 0, &linfo, dxpl_id)) + HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't get link info") + + /* Check if there is already a 'stab' message */ + if((stab_exists = H5O_exists(grp_oloc, H5O_STAB_ID, 0, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to check for symbol table") + if(stab_exists) + use_stab = TRUE; + else { + H5O_ginfo_t ginfo; /* Group info message */ + size_t link_msg_size; /* Size of link message in the file */ + + /* Get the link message size */ + if((link_msg_size = H5O_raw_size(H5O_LINK_ID, grp_oloc->file, obj_lnk)) == 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGETSIZE, FAIL, "can't get link size") + + /* Get the group info */ + if(NULL == H5O_read(grp_oloc, H5O_GINFO_ID, 0, &ginfo, dxpl_id)) + HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't get group info") + + /* If there's still a small enough number of links, use the 'link' message */ + /* (If the encoded form of the link is too large to fit into an object + * header message, convert to using symbol table instead of link messages) + */ + if(linfo.nlinks < ginfo.max_compact && link_msg_size < H5O_MAX_SIZE) + use_stab = FALSE; + else { + H5G_obj_ud1_t udata; /* User data for iteration */ + H5O_stab_t stab; /* Symbol table message */ + + /* The group doesn't currently have a 'stab' message, go create one */ + if(H5G_stab_create(grp_oloc, &stab, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create symbol table") + + /* Set up user data for object header message iteration */ + udata.f = grp_oloc->file; + udata.btree_addr = stab.btree_addr; + udata.heap_addr = stab.heap_addr; + udata.dxpl_id = dxpl_id; + + /* Iterate over the 'link' messages, inserting them into the symbol table */ + if(H5O_iterate(grp_oloc, H5O_LINK_ID, H5G_obj_link_to_stab_cb, &udata, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "error iterating over links") + + /* Remove all the 'link' messages */ + if(H5O_remove(grp_oloc, H5O_LINK_ID, H5O_ALL, FALSE, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete link messages") + + use_stab = TRUE; + } /* end else */ + } /* end else */ + } /* end if */ + else + use_stab = TRUE; + + /* Insert into symbol table or create link object */ + if(use_stab) { + /* Insert into symbol table */ + if(H5G_stab_insert(grp_oloc, name, obj_lnk, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert entry") + } /* end if */ + else { + /* Insert with link message */ + if(H5G_link_insert(grp_oloc, obj_lnk, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert entry") + } /* end else */ + + /* Increment the number of objects in this group */ + if(linfo_exists) { + linfo.nlinks++; + if(H5O_modify(grp_oloc, H5O_LINFO_ID, 0, 0, H5O_UPDATE_TIME, &linfo, dxpl_id) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't update link info message") + } /* end if */ + + /* Increment link count on object, if appropriate */ + if(inc_link) { + H5O_loc_t obj_oloc; /* Object location */ + + /* Convert to object location */ + obj_oloc.file = grp_oloc->file; + obj_oloc.addr = obj_lnk->u.hard.addr; + + /* Increment reference count for object */ + if(H5O_link(&obj_oloc, 1, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_LINK, FAIL, "unable to increment hard link count") + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_obj_insert() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_obj_iterate + * + * Purpose: Private function for H5Giterate. + * Iterates over objects in a group + * + * Return: Success: Non-negative + * + * Failure: Negative + * + * Programmer: Quincey Koziol + * Oct 3, 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_obj_iterate(hid_t loc_id, const char *name, int skip, int *last_obj, + H5G_iterate_t op, void *op_data, hid_t dxpl_id) +{ + htri_t stab_exists; /* Whether the symbol table info is present */ + hid_t gid = -1; /* ID of group to iterate over */ + H5G_t *grp; /* Pointer to group data structure to iterate over */ + herr_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_obj_iterate, FAIL) + + /* Sanity check */ + HDassert(name); + HDassert(last_obj); + HDassert(op); + + /* + * Open the group on which to operate. We also create a group ID which + * we can pass to the application-defined operator. + */ + if((gid = H5Gopen (loc_id, name)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group") + if((grp = H5I_object(gid)) == NULL) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "bad group ID") + + /* Check if we have information about the number of objects in this group */ + if((stab_exists = H5O_exists(&(grp->oloc), H5O_STAB_ID, 0, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to check for symbol table") + + /* If the symbol table doesn't exist, iterate over link messages */ + if(!stab_exists) { + /* Get the object's name from the link messages */ + if((ret_value = H5G_link_iterate(&(grp->oloc), gid, skip, last_obj, op, op_data, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over links") + } /* end if */ + else { + /* Iterate over symbol table */ + if((ret_value = H5G_stab_iterate(&(grp->oloc), gid, skip, last_obj, op, op_data, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over symbol table") + } /* end else */ + +done: + if(gid > 0) + H5I_dec_ref(gid); /*also closes 'grp'*/ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_obj_iterate() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_obj_count + * + * Purpose: Check the number of objects in a group + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Sep 6 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_obj_count(H5O_loc_t *oloc, hsize_t *num_objs, hid_t dxpl_id) +{ + htri_t linfo_exists; /* Whether the link info is present */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_obj_count, FAIL) + + /* Sanity check */ + HDassert(oloc); + HDassert(num_objs); + + /* Check if we have information about the number of objects in this group */ + if((linfo_exists = H5O_exists(oloc, H5O_LINFO_ID, 0, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to check for link info") + + /* If the link info exists, then it has the number of objects in the group */ + if(linfo_exists > 0) { + H5O_linfo_t linfo; /* Link info message */ + + /* Get the link info for this group */ + if(NULL == H5O_read(oloc, H5O_LINFO_ID, 0, &linfo, dxpl_id)) + HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't get link info") + + /* Set the number of objects */ + *num_objs = linfo.nlinks; + } /* end if */ + else { + /* Get the number of objects in this group by iterating over symbol table */ + if(H5G_stab_count(oloc, num_objs, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOUNT, FAIL, "can't count objects") + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_obj_count() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_obj_get_name_by_idx + * + * Purpose: Private function for H5Gget_objname_by_idx. + * Returns the name of objects in the group by giving index. + * + * Return: Success: Non-negative + * + * Failure: Negative + * + * Programmer: Raymond Lu + * Nov 20, 2002 + * + *------------------------------------------------------------------------- + */ +ssize_t +H5G_obj_get_name_by_idx(H5O_loc_t *oloc, hsize_t idx, char* name, size_t size, hid_t dxpl_id) +{ + htri_t stab_exists; /* Whether the symbol table info is present */ + ssize_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_obj_get_name_by_idx, FAIL) + + /* Sanity check */ + HDassert(oloc); + + /* Check if we have information about the number of objects in this group */ + if((stab_exists = H5O_exists(oloc, H5O_STAB_ID, 0, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to check for symbol table") + + /* If the symbol table doesn't exist, search link messages */ + if(!stab_exists) { + /* Get the object's name from the link messages */ + if((ret_value = H5G_link_get_name_by_idx(oloc, idx, name, size, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't locate name") + } /* end if */ + else { + /* Get the object's name from the symbol table */ + if((ret_value = H5G_stab_get_name_by_idx(oloc, idx, name, size, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't locate name") + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_obj_get_name_by_idx() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_obj_get_type_by_idx + * + * Purpose: Private function for H5Gget_objtype_by_idx. + * Returns the type of objects in the group by giving index. + * + * Return: Success: H5G_GROUP(1), H5G_DATASET(2), H5G_TYPE(3) + * + * Failure: Negative + * + * Programmer: Raymond Lu + * Nov 20, 2002 + * + *------------------------------------------------------------------------- + */ +H5G_obj_t +H5G_obj_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx, hid_t dxpl_id) +{ + htri_t stab_exists; /* Whether the symbol table info is present */ + H5G_obj_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_obj_get_type_by_idx, H5G_UNKNOWN) + + /* Sanity check */ + HDassert(oloc); + + /* Check if we have information about the number of objects in this group */ + if((stab_exists = H5O_exists(oloc, H5O_STAB_ID, 0, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5G_UNKNOWN, "unable to check for symbol table") + + /* If the symbol table doesn't exist, search link messages */ + if(!stab_exists) { + /* Get the object's type from the link messages */ + if((ret_value = H5G_link_get_type_by_idx(oloc, idx, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5G_UNKNOWN, "can't locate type") + } /* end if */ + else { + /* Get the object's type from the symbol table */ + if((ret_value = H5G_stab_get_type_by_idx(oloc, idx, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5G_UNKNOWN, "can't locate type") + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_obj_get_type_by_idx() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_obj_remove + * + * Purpose: Remove an object from a group. + * (Needs to hand up the type of the object removed) + * + * Return: Success: Non-negative + * + * Failure: Negative + * + * Programmer: Quincey Koziol + * Sep 19, 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_obj_remove(H5O_loc_t *oloc, const char *name, H5G_obj_t *obj_type, hid_t dxpl_id) +{ + htri_t linfo_exists; /* Whether the link info is present */ + H5O_linfo_t linfo; /* Link info message */ + htri_t stab_exists; /* Whether the symbol table info is present */ + hbool_t use_stab; /* Whether to use symbol table for deletions or not */ + H5G_obj_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_obj_remove, FAIL) + + /* Sanity check */ + HDassert(oloc); + HDassert(obj_type); + + /* Check if we have information about the number of objects in this group */ + if((stab_exists = H5O_exists(oloc, H5O_STAB_ID, 0, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to check for symbol table") + + /* Check if we have information about the number of objects in this group */ + if((linfo_exists = H5O_exists(oloc, H5O_LINFO_ID, 0, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to check for link info message") + if(linfo_exists) { + H5O_ginfo_t ginfo; /* Group info message */ + + /* Get the number of objects in this group */ + if(NULL == H5O_read(oloc, H5O_LINFO_ID, 0, &linfo, dxpl_id)) + HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't get link info") + + /* Check for deleting enough links from group to go back to link messages */ + if(stab_exists) { + /* Get the group info */ + if(NULL == H5O_read(oloc, H5O_GINFO_ID, 0, &ginfo, dxpl_id)) + HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't get group info") + + /* Switch from symbol table back to link messages */ + if(linfo.nlinks <= ginfo.min_dense) { + H5G_bt_it_ud4_t udata; + H5O_stab_t stab; /* Info about local heap & B-tree */ + H5O_link_t *lnk_table; /* Array of links to convert */ + hbool_t can_convert = TRUE; /* Whether converting to link messages is possible */ + size_t u; /* Local index */ + + /* Get the B-tree & local heap info */ + if(NULL == H5O_read(oloc, H5O_STAB_ID, 0, &stab, dxpl_id)) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to determine local heap address") + + /* Allocate space for the link table */ + H5_CHECK_OVERFLOW(linfo.nlinks, /* From: */ hsize_t, /* To: */size_t); + if(NULL == (lnk_table = H5MM_malloc(sizeof(H5O_link_t) * (size_t)linfo.nlinks))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for link table") + + /* Build udata to pass through H5B_iterate() */ + udata.heap_addr = stab.heap_addr; + udata.lnk_table = lnk_table; + udata.nlinks = 0; + udata.max_links = linfo.nlinks; + + /* Iterate over the group members, building a table of equivalent link messages */ + if((ret_value = H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, + H5G_node_stab_convert, stab.btree_addr, &udata)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTNEXT, FAIL, "error iterating over entries") + + /* Inspect links in table for ones that can't be converted back + * into link message form (currently only links which can't fit + * into an object header message) + */ + for(u = 0; u < linfo.nlinks; u++) + if(H5O_mesg_size(H5O_LINK_ID, oloc->file, &(lnk_table[u])) >= H5O_MAX_SIZE) { + can_convert = FALSE; + break; + } /* end if */ + + /* If ok, insert links as link messages */ + if(can_convert) { + for(u = 0; u < linfo.nlinks; u++) { + /* Insert link message into group */ + if(H5O_modify(oloc, H5O_LINK_ID, H5O_NEW_MESG, 0, H5O_UPDATE_TIME, &(lnk_table[u]), dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create message") + } /* end for */ + + /* Remove the 'stab' message */ + if(H5O_remove(oloc, H5O_STAB_ID, H5O_ALL, FALSE, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete symbol table message") + + use_stab = FALSE; + } /* end if */ + else + use_stab = TRUE; + + /* Release memory for link names (and memory for soft link values) */ + for(u = 0; u < linfo.nlinks; u++) { + H5MM_xfree(lnk_table[u].name); + if(lnk_table[u].type == H5G_LINK_SOFT) + H5MM_xfree(lnk_table[u].u.soft.name); + } /* end for */ + + /* Release memory for link table */ + H5MM_xfree(lnk_table); + } /* end if */ + else + use_stab = TRUE; + } /* end if */ + else + use_stab = FALSE; + } /* end if */ + else + use_stab = TRUE; + + /* If the symbol table doesn't exist, search link messages */ + if(!use_stab) { + /* Remove object from the link messages */ + if((ret_value = H5G_link_remove(oloc, name, obj_type, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't remove object") + } /* end if */ + else { + /* Remove object from the symbol table */ + if((ret_value = H5G_stab_remove(oloc, name, obj_type, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't remove object") + } /* end else */ + + /* Decrement the number of objects in this group */ + if(linfo_exists) { + linfo.nlinks--; + if(H5O_modify(oloc, H5O_LINFO_ID, 0, 0, H5O_UPDATE_TIME, &linfo, dxpl_id) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't update link info message") + + /* Remove the symbol table, if we are using one and the number of links drops to zero */ + if(linfo.nlinks == 0 && use_stab) { + if(H5O_remove(oloc, H5O_STAB_ID, H5O_ALL, FALSE, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete symbol table message") + } /* end if */ + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_obj_remove() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_obj_lookup + * + * Purpose: Look up a link in a group. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Sep 26 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_obj_lookup(H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk, + hid_t dxpl_id) +{ + htri_t stab_exists; /* Whether the symbol table info is present */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_obj_lookup, FAIL) + + /* check arguments */ + HDassert(grp_oloc && grp_oloc->file); + HDassert(name && *name); + + /* Check if we have information about the number of objects in this group */ + if((stab_exists = H5O_exists(grp_oloc, H5O_STAB_ID, 0, dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to check for symbol table") + + /* If the symbol table doesn't exist, search link messages */ + if(!stab_exists) { + /* Get the object's info from the link messages */ + if(H5G_link_lookup(grp_oloc, name, lnk, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't locate object") + } /* end if */ + else { + /* Get the object's info from the symbol table */ + if(H5G_stab_lookup(grp_oloc, name, lnk, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't locate object") + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_obj_lookup() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_obj_find_cb + * + * Purpose: Callback for retrieving object location for an object in a group + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, September 20, 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_obj_find_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name, const H5O_link_t UNUSED *lnk, + H5G_loc_t *obj_loc, void *_udata/*in,out*/) +{ + H5G_obj_ud2_t *udata = (H5G_obj_ud2_t *)_udata; /* User data passed in */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5G_obj_find_cb) + + /* Check if the name in this group resolved to a valid link */ + if(obj_loc == NULL) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "name doesn't exist") + + /* Copy object location for object */ + H5O_loc_copy(udata->oloc, obj_loc->oloc, H5O_COPY_DEEP); + + /* Release the group location for the object */ + /* (Group traversal callbacks are responsible for either taking ownership + * of the group location for the object, or freeing it. - QAK) + */ + H5G_loc_free(obj_loc); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_obj_find_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_obj_find + * + * Purpose: Look up an object relative to a group. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Sep 20 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_obj_find(H5G_loc_t *loc, const char *name, unsigned traverse_flags, + H5O_loc_t *obj_oloc, hid_t dxpl_id) +{ + H5G_obj_ud2_t udata; /* User data for traversal callback */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_obj_find, FAIL) + + /* check arguments */ + HDassert(loc && loc->oloc->file); + HDassert(name && *name); + HDassert(obj_oloc); + + /* Set up user data for locating object */ + udata.oloc = obj_oloc; + + /* Traverse group hierarchy to locate object */ + if(H5G_traverse(loc, name, traverse_flags, H5G_obj_find_cb, &udata, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't find object") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_obj_find() */ + diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h index 4c6ec68..ad65fc1 100644 --- a/src/H5Gpkg.h +++ b/src/H5Gpkg.h @@ -36,6 +36,55 @@ #include "H5SLprivate.h" /* Skip lists */ #define H5G_SIZE_HINT 256 /* default root grp size hint */ +#define H5G_NLINKS 16 /*max symlinks to follow per lookup */ + +/* + * Various types of object header information can be cached in a symbol + * table entry (it's normal home is the object header to which the entry + * points). This datatype determines what (if anything) is cached in the + * symbol table entry. + */ +typedef enum H5G_type_t { + H5G_CACHED_ERROR = -1, /*force enum to be signed */ + H5G_NOTHING_CACHED = 0, /*nothing is cached, must be 0 */ + H5G_CACHED_STAB = 1, /*symbol table, `stab' */ + H5G_CACHED_SLINK = 2, /*symbolic link */ + + H5G_NCACHED = 3 /*THIS MUST BE LAST */ +} H5G_type_t; + +/* + * A symbol table entry caches these parameters from object header + * messages... The values are entered into the symbol table when an object + * header is created (by hand) and are extracted from the symbol table with a + * callback function registered in H5O_init_interface(). Be sure to update + * H5G_ent_decode(), H5G_ent_encode(), and H5G_ent_debug() as well. + */ +typedef union H5G_cache_t { + struct { + haddr_t btree_addr; /*file address of symbol table B-tree*/ + haddr_t heap_addr; /*file address of stab name heap */ + } stab; + + struct { + size_t lval_offset; /*link value offset */ + } slink; +} H5G_cache_t; + +/* + * 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_entry_t { + hbool_t dirty; /*entry out-of-date? */ + H5G_type_t type; /*type of information cached */ + H5G_cache_t cache; /*cached data from object header */ + size_t name_off; /*offset of name within name heap */ + haddr_t header; /*file address of object header */ + H5F_t *file; /*file to which this obj hdr belongs */ +} H5G_entry_t; /* * A symbol table node is a collection of symbol table entries. It can @@ -63,8 +112,9 @@ struct H5G_shared_t { * above the H5G layer. */ struct H5G_t { - H5G_shared_t* shared; /*shared file object data */ - H5G_entry_t ent; /*info about the group */ + H5G_shared_t *shared; /* Shared file object data */ + H5O_loc_t oloc; /* Object location for group */ + H5G_name_t path; /* Group hierarchy path */ }; /* @@ -90,15 +140,12 @@ typedef H5G_bt_ud_common_t H5G_bt_ud0_t; /* * Data exchange structure for symbol table nodes. This structure is - * passed through the B-link tree layer to the methods for the objects - * to which the B-link tree points. + * passed through the B-link tree layer to the insert method for entries. */ typedef struct H5G_bt_ud1_t { /* downward */ H5G_bt_ud_common_t common; /* Common info for B-tree user data (must be first) */ - - /* downward for INSERT, upward for FIND */ - H5G_entry_t *ent; /*entry to insert into table */ + const H5O_link_t *lnk; /* Link to insert into table */ } H5G_bt_ud1_t; /* @@ -112,8 +159,25 @@ typedef struct H5G_bt_ud2_t { hbool_t adj_link; /* Whether to adjust the link count on objects */ /* upward */ + H5G_obj_t *obj_type; /*member type to be returned */ } H5G_bt_ud2_t; +/* Typedef for B-tree 'find' operation */ +typedef herr_t (*H5G_bt_find_op_t)(const H5G_entry_t *ent/*in*/, void *operator_data/*in,out*/); + +/* + * Data exchange structure for symbol table nodes. This structure is + * passed through the B-link tree layer to the 'find' method for entries. + */ +typedef struct H5G_bt_ud3_t { + /* downward */ + H5G_bt_ud_common_t common; /* Common info for B-tree user data (must be first) */ + H5G_bt_find_op_t op; /* Operator to call when correct entry is found */ + void *op_data; /* Data to pass to operator */ + + /* upward */ +} H5G_bt_ud3_t; + /* * Data exchange structure to pass through the B-tree layer for the * H5B_iterate function. @@ -127,7 +191,7 @@ typedef struct H5G_bt_it_ud1_t { int skip; /*initial entries to skip */ /* upward */ - int final_ent; /*final entry looked at */ + int *final_ent; /*final entry looked at */ } H5G_bt_it_ud1_t; /* @@ -164,18 +228,52 @@ typedef struct H5G_bt_it_ud3_t { typedef struct H5G_bt_it_ud4_t { /* downward */ haddr_t heap_addr; /*symbol table heap address */ - H5G_entry_t *grp_ent; /*entry of group */ + size_t max_links; /* Max. # of links array can store */ /* upward */ + H5O_link_t *lnk_table; /* Pointer to array of links to fill in */ + size_t nlinks; /* Links inserted into table */ } H5G_bt_it_ud4_t; /* Data passed to B-tree iteration for copying copy symblol table content */ typedef struct H5G_bt_it_ud5_t { + haddr_t src_heap_addr; /* heap address of the source symbol table */ + H5F_t *dst_file; /* File of destination group */ + H5O_stab_t *dst_stab; /* symbol table info for destination group */ H5SL_t *map_list; /* skip list to map copied object addresses */ - haddr_t heap_addr; /* heap address of the source symbol table */ - H5G_entry_t *loc_dst; /* group where new object is inserted to */ } H5G_bt_it_ud5_t; +/* Typedef for path traversal operations */ +typedef herr_t (*H5G_traverse_t)(H5G_loc_t *grp_loc/*in*/, const char *name, + const H5O_link_t *lnk/*in*/, H5G_loc_t *obj_loc/*out*/, void *operator_data/*in,out*/); + +/* "value" information for a link (as opposed to "name" of link) */ +typedef struct { + haddr_t addr; /* Address of object linked to */ +} H5G_linkvalue_hard_t; + +typedef struct { + char *name; /* Link value */ +} H5G_linkvalue_soft_t; + +typedef struct { + H5G_link_t type; /* Type of link */ + union { + H5G_linkvalue_hard_t hard; /* Information for hard link */ + H5G_linkvalue_soft_t soft; /* Information for soft link */ + } u; +} H5G_linkvalue_t; + +/* + * During name lookups (see H5G_traverse()) we sometimes want information about + * a symbolic link or a mount point. The normal operation is to follow the + * symbolic link or mount point and return information about its target. + */ +#define H5G_TARGET_NORMAL 0x0000 +#define H5G_TARGET_SLINK 0x0001 +#define H5G_TARGET_MOUNT 0x0002 +#define H5G_CRT_INTMD_GROUP 0x0004 + /* * This is the class identifier to give to the B-tree functions. */ @@ -185,32 +283,56 @@ H5_DLLVAR H5B_class_t H5B_SNODE[1]; H5_DLLVAR const H5AC_class_t H5AC_SNODE[1]; /* + * Utility functions + */ +H5_DLL H5G_t *H5G_rootof(H5F_t *f); +H5_DLL const char * H5G_component(const char *name, size_t *size_p); +H5_DLL herr_t H5G_traverse_term_interface(void); +H5_DLL herr_t H5G_traverse(const H5G_loc_t *loc, const char *name, + unsigned target, H5G_traverse_t op, void *op_data, hid_t dxpl_id); + +/* * Functions that understand symbol tables but not names. The * functions that understand names are exported to the rest of * the library and appear in H5Gprivate.h. */ -H5_DLL herr_t H5G_stab_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, - H5G_entry_t *ent/*out*/); -H5_DLL herr_t H5G_stab_find(H5G_entry_t *grp_ent, const char *name, - H5G_entry_t *obj_ent/*out*/, hid_t dxpl_id); -H5_DLL herr_t H5G_stab_insert(H5G_entry_t *grp_ent, const char *name, - H5G_entry_t *obj_ent, hbool_t inc_link, hid_t dxpl_id); +H5_DLL herr_t H5G_stab_create(H5O_loc_t *grp_oloc, H5O_stab_t *stab, hid_t dxpl_id); +H5_DLL herr_t H5G_stab_create_components(H5F_t *f, H5O_stab_t *stab, size_t size_hint, hid_t dxpl_id); +H5_DLL herr_t H5G_stab_insert(H5O_loc_t *grp_oloc, const char *name, + H5O_link_t *obj_lnk, hid_t dxpl_id); +H5_DLL herr_t H5G_stab_insert_real(H5F_t *f, H5O_stab_t *stab, const char *name, + H5O_link_t *obj_lnk, hid_t dxpl_id); H5_DLL herr_t H5G_stab_delete(H5F_t *f, hid_t dxpl_id, const H5O_stab_t *stab, hbool_t adj_link); -H5_DLL herr_t H5G_stab_remove(H5G_entry_t *grp_ent, const char *name, hid_t dxpl_id); -H5_DLL herr_t H5G_stab_copy_tmp(H5F_t *f_dst, H5O_stab_t *stab_dst, +H5_DLL herr_t H5G_stab_iterate(H5O_loc_t *oloc, hid_t gid, int skip, + int *last_obj, H5G_iterate_t op, void *op_data, hid_t dxpl_id); +H5_DLL herr_t H5G_stab_count(struct H5O_loc_t *oloc, hsize_t *num_objs, hid_t dxpl_id); +H5_DLL ssize_t H5G_stab_get_name_by_idx(H5O_loc_t *oloc, hsize_t idx, char* name, + size_t size, hid_t dxpl_id); +H5_DLL H5G_obj_t H5G_stab_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx, hid_t dxpl_id); - +H5_DLL herr_t H5G_stab_remove(H5O_loc_t *oloc, const char *name, + H5G_obj_t *obj_type, hid_t dxpl_id); +H5_DLL herr_t H5G_stab_lookup(H5O_loc_t *grp_oloc, const char *name, + H5O_link_t *lnk, hid_t dxpl_id); /* * Functions that understand symbol table entries. */ +H5_DLL herr_t H5G_ent_copy(H5G_entry_t *dst, const H5G_entry_t *src, + H5G_copy_depth_t depth); +H5_DLL herr_t H5G_ent_reset(H5G_entry_t *ent); H5_DLL herr_t H5G_ent_decode_vec(H5F_t *f, const uint8_t **pp, H5G_entry_t *ent, unsigned n); H5_DLL herr_t H5G_ent_encode_vec(H5F_t *f, uint8_t **pp, const H5G_entry_t *ent, unsigned n); -H5_DLL herr_t H5G_ent_set_name(H5G_entry_t *loc, H5G_entry_t *obj, const char *name); +H5_DLL herr_t H5G_ent_modified(H5G_entry_t *ent, H5G_type_t cache_type); +H5_DLL herr_t H5G_ent_convert(H5F_t *f, haddr_t heap_addr, const char *name, + const H5O_link_t *lnk, H5G_entry_t *ent, hid_t dxpl_id); +H5_DLL herr_t H5G_ent_debug(H5F_t *f, hid_t dxpl_id, const H5G_entry_t *ent, FILE * stream, + int indent, int fwidth, haddr_t heap); /* Functions that understand symbol table nodes */ +H5_DLL herr_t H5G_node_init(H5F_t *f); H5_DLL int H5G_node_iterate (H5F_t *f, hid_t dxpl_id, const void *_lt_key, haddr_t addr, const void *_rt_key, void *_udata); H5_DLL int H5G_node_sumup(H5F_t *f, hid_t dxpl_id, const void *_lt_key, haddr_t addr, @@ -221,5 +343,68 @@ H5_DLL int H5G_node_type(H5F_t *f, hid_t dxpl_id, const void *_lt_key, haddr_t a const void *_rt_key, void *_udata); H5_DLL int H5G_node_copy(H5F_t *f, hid_t dxpl_id, const void *_lt_key, haddr_t addr, const void *_rt_key, void *_udata); +H5_DLL int H5G_node_stab_convert(H5F_t *f, hid_t dxpl_id, const void *_lt_key, haddr_t addr, + const void *_rt_key, void *_udata); + +/* Functions that understand link messages */ +/* forward reference for later use */ +struct H5HL_t; /* defined in H5HLprivate.h */ +H5_DLL herr_t H5G_link_convert(H5O_link_t *lnk, const H5G_entry_t *ent, + const struct H5HL_t *_heap, const char *name); +H5_DLL herr_t H5G_link_insert(H5O_loc_t *grp_oloc, H5O_link_t *obj_lnk, + hid_t dxpl_id); +H5_DLL ssize_t H5G_link_get_name_by_idx(H5O_loc_t *oloc, hsize_t idx, char* name, + size_t size, hid_t dxpl_id); +H5_DLL H5G_obj_t H5G_link_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx, + hid_t dxpl_id); +H5_DLL herr_t H5G_link_remove(const H5O_loc_t *oloc, const char *name, + H5G_obj_t *obj_type, hid_t dxpl_id); +H5_DLL herr_t H5G_link_iterate(H5O_loc_t *oloc, hid_t gid, int skip, + int *last_obj, H5G_iterate_t op, void *op_data, hid_t dxpl_id); +H5_DLL herr_t H5G_link_lookup(H5O_loc_t *grp_oloc, const char *name, + H5O_link_t *lnk, hid_t dxpl_id); + +/* Functions that understand objects */ +H5_DLL herr_t H5G_obj_create(H5F_t *f, hid_t dxpl_id, H5O_ginfo_t *ginfo, + H5O_loc_t *oloc/*out*/); +H5_DLL herr_t H5G_obj_insert(H5O_loc_t *grp_oloc, const char *name, + H5O_link_t *obj_lnk, hbool_t inc_link, hid_t dxpl_id); +H5_DLL herr_t H5G_obj_lookup(H5O_loc_t *grp_oloc, const char *name, + H5O_link_t *lnk, hid_t dxpl_id); +H5_DLL herr_t H5G_obj_iterate(hid_t loc_id, const char *name, int skip, + int *last_obj, H5G_iterate_t op, void *op_data, hid_t dxpl_id); +H5_DLL herr_t H5G_obj_count(struct H5O_loc_t *oloc, hsize_t *num_objs, hid_t dxpl_id); +H5_DLL ssize_t H5G_obj_get_name_by_idx(H5O_loc_t *oloc, hsize_t idx, + char* name, size_t size, hid_t dxpl_id); +H5_DLL H5G_obj_t H5G_obj_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx, + hid_t dxpl_id); +H5_DLL herr_t H5G_obj_remove(H5O_loc_t *oloc, const char *name, + H5G_obj_t *obj_type, hid_t dxpl_id); +H5_DLL herr_t H5G_obj_find(H5G_loc_t *loc, const char *name, + unsigned traverse_flags, H5O_loc_t *obj_oloc, hid_t dxpl_id); + +/* + * These functions operate on group hierarchy names. + */ +H5_DLL herr_t H5G_name_init(H5G_name_t *name, const char *path); +H5_DLL herr_t H5G_name_set(H5G_name_t *loc, H5G_name_t *obj, const char *name); + +/* + * These functions operate on group "locations" + */ +H5_DLL herr_t H5G_loc_copy(H5G_loc_t *dst, H5G_loc_t *src, H5G_copy_depth_t depth); +H5_DLL herr_t H5G_loc_insert(H5G_loc_t *grp_loc, const char *name, + H5G_loc_t *obj_loc, hbool_t inc_link, hid_t dxpl_id); +H5_DLL herr_t H5G_loc_exists(const H5G_loc_t *loc, const char *name, hid_t dxpl_id); +H5_DLL herr_t H5G_loc_remove(H5G_loc_t *grp_loc, const char *name, + H5G_loc_t *obj_loc, hid_t dxpl_id); + +/* Testing functions */ +#ifdef H5G_TESTING +H5_DLL htri_t H5G_is_empty_test(hid_t gid); +H5_DLL htri_t H5G_has_links_test(hid_t gid, unsigned *nmsgs); +H5_DLL htri_t H5G_has_stab_test(hid_t gid); +#endif /* H5G_TESTING */ #endif + diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h index 815a76f..b902f98 100644 --- a/src/H5Gprivate.h +++ b/src/H5Gprivate.h @@ -20,11 +20,6 @@ * * Purpose: Library-visible declarations. * - * Modifications: Aug 22, 2002 - * Pedro Vicente <pvn@ncsa.uiuc.edu> - * Added 'names' field to H5G_entry_t - * Added H5G_replace_name - * *------------------------------------------------------------------------- */ @@ -49,8 +44,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_NLINKS 16 /*max symlinks to follow per lookup */ /* * The disk size for a symbol table entry... @@ -65,113 +58,84 @@ /* ========= Group Creation properties ============ */ -/* Definitions for local heap size hint */ +/* Defaults for group info values */ +#define H5G_CRT_GINFO_LHEAP_SIZE_HINT 0 +#define H5G_CRT_GINFO_MAX_COMPACT 8 +#define H5G_CRT_GINFO_MIN_DENSE 6 +#define H5G_CRT_GINFO_EST_NUM_ENTRIES 4 +#define H5G_CRT_GINFO_EST_NAME_LEN 8 + +/* Definitions for group info settings */ #define H5G_CRT_GROUP_INFO_NAME "group info" #define H5G_CRT_GROUP_INFO_SIZE sizeof(H5O_ginfo_t) -#define H5G_CRT_GROUP_INFO_DEF {0, 8, 6, 4, 8} +#define H5G_CRT_GROUP_INFO_DEF {H5G_CRT_GINFO_LHEAP_SIZE_HINT, \ + H5G_CRT_GINFO_MAX_COMPACT, \ + H5G_CRT_GINFO_MIN_DENSE, \ + H5G_CRT_GINFO_EST_NUM_ENTRIES, \ + H5G_CRT_GINFO_EST_NAME_LEN} /* Definitions for creating intermediate groups */ #define H5G_CRT_INTERMEDIATE_GROUP_NAME "intermediate_group" #define H5G_CRT_INTERMEDIATE_GROUP_SIZE sizeof(unsigned) #define H5G_CRT_INTERMEDIATE_GROUP_DEF 0 -/* - * Various types of object header information can be cached in a symbol - * table entry (it's normal home is the object header to which the entry - * points). This datatype determines what (if anything) is cached in the - * symbol table entry. - */ -typedef enum H5G_type_t { - H5G_CACHED_ERROR = -1, /*force enum to be signed */ - H5G_NOTHING_CACHED = 0, /*nothing is cached, must be 0 */ - H5G_CACHED_STAB = 1, /*symbol table, `stab' */ - H5G_CACHED_SLINK = 2, /*symbolic link */ - - H5G_NCACHED = 3 /*THIS MUST BE LAST */ -} H5G_type_t; +/* Type of operation being performed for call to H5G_name_replace() */ +typedef enum { + OP_MOVE = 0, /* H5*move call */ + OP_UNLINK, /* H5Gunlink call */ + OP_MOUNT, /* H5Fmount call */ + OP_UNMOUNT /* H5Funmount call */ +} H5G_names_op_t; -/* - * A symbol table entry caches these parameters from object header - * messages... The values are entered into the symbol table when an object - * header is created (by hand) and are extracted from the symbol table with a - * callback function registered in H5O_init_interface(). Be sure to update - * H5G_ent_decode(), H5G_ent_encode(), and H5G_ent_debug() as well. - */ -typedef union H5G_cache_t { - struct { - haddr_t btree_addr; /*file address of symbol table B-tree*/ - haddr_t heap_addr; /*file address of stab name heap */ - } stab; +/* Structure to store information about the name an object was opened with */ +typedef struct { + H5RS_str_t *user_path_r; /* Path to object, as opened by user */ + H5RS_str_t *canon_path_r; /* Path to object, as found in file */ + unsigned user_path_hidden; /* Whether the user's path is valid */ +} H5G_name_t; - struct { - size_t lval_offset; /*link value offset */ - } slink; -} H5G_cache_t; +/* Forward declarations */ +struct H5P_genplist_t; +struct H5O_loc_t; /* - * 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. + * The "location" of an object in a group hierarchy. This points to an object + * location and a group hierarchy path for the object. */ -typedef struct H5G_entry_t { - hbool_t dirty; /*entry out-of-date? */ - H5G_type_t type; /*type of information cached */ - H5G_cache_t cache; /*cached data from object header */ - size_t name_off; /*offset of name within name heap */ - haddr_t header; /*file address of object header */ - H5F_t *file; /*file to which this obj hdr belongs */ - H5RS_str_t *user_path_r; /* Path to object, as opened by user */ - H5RS_str_t *canon_path_r; /* Path to object, as found in file */ - unsigned user_path_hidden; /* Whether the user's path is valid */ -} H5G_entry_t; +typedef struct { + struct H5O_loc_t *oloc; /* Object header location */ + H5G_name_t *path; /* Group hierarchy path */ +} H5G_loc_t; typedef struct H5G_t H5G_t; typedef struct H5G_shared_t H5G_shared_t; -/* Type of operation being performed for call to H5G_replace_name() */ -typedef enum { - OP_MOVE = 0, /* H5*move call */ - OP_UNLINK, /* H5Gunlink call */ - OP_MOUNT, /* H5Fmount call */ - OP_UNMOUNT /* H5Funmount call */ -} H5G_names_op_t; - /* Depth of group entry copy */ +/* (Also used for group hier. name copies) */ typedef enum { - H5G_COPY_NULL, /* Null destination names */ - H5G_COPY_LIMITED, /* Limited copy from source to destination, omitting name & old name fields */ H5G_COPY_SHALLOW, /* Copy from source to destination, including name & old name fields */ + H5G_COPY_CANON, /* Keep user path the same, but deep copy canonical path */ H5G_COPY_DEEP /* Deep copy from source to destination, including duplicating name & old name fields */ -} H5G_ent_copy_depth_t; - -/* Forward declarations for prototype arguments */ -struct H5P_genplist_t; +} H5G_copy_depth_t; /* * Library prototypes... These are the ones that other packages routinely * call. */ -H5_DLL H5G_entry_t *H5G_loc(hid_t loc_id); -H5_DLL herr_t H5G_mkroot(H5F_t *f, hid_t dxpl_id, H5G_entry_t *root_entry); -H5_DLL H5G_entry_t *H5G_entof(H5G_t *grp); +H5_DLL htri_t H5G_isa(struct H5O_loc_t *loc, hid_t dxpl_id); +H5_DLL herr_t H5G_mkroot(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc); +H5_DLL struct H5O_loc_t *H5G_oloc(H5G_t *grp); +H5_DLL H5G_name_t * H5G_nameof(H5G_t *grp); H5_DLL H5F_t *H5G_fileof(H5G_t *grp); H5_DLL herr_t H5G_free(H5G_t *grp); -H5_DLL H5G_t *H5G_open(H5G_entry_t *ent, hid_t dxpl_id); +H5_DLL H5G_t *H5G_open(H5G_loc_t *loc, hid_t dxpl_id); H5_DLL herr_t H5G_close(H5G_t *grp); -H5_DLL H5G_obj_t H5G_get_type(H5G_entry_t *ent, hid_t dxpl_id); -H5_DLL herr_t H5G_get_objinfo(H5G_entry_t *loc, const char *name, - hbool_t follow_link, - H5G_stat_t *statbuf/*out*/, hid_t dxpl_id); -H5_DLL herr_t H5G_insert(H5G_entry_t *loc, const char *name, - H5G_entry_t *ent, hid_t dxpl_id, struct H5P_genplist_t *oc_plist); -H5_DLL herr_t H5G_find(H5G_entry_t *loc, const char *name, - H5G_entry_t *ent/*out*/, hid_t dxpl_id); -H5_DLL H5F_t *H5G_insertion_file(H5G_entry_t *loc, const char *name, hid_t dxpl_id); -H5_DLL herr_t H5G_replace_name(H5G_obj_t type, H5G_entry_t *loc, - H5RS_str_t *src_name, H5G_entry_t *src_loc, - H5RS_str_t *dst_name, H5G_entry_t *dst_loc, H5G_names_op_t op); -H5_DLL herr_t H5G_free_grp_name(H5G_t *grp); +H5_DLL herr_t H5G_insert(H5G_loc_t *loc, const char *name, + H5G_loc_t *obj_loc, hid_t dxpl_id, struct H5P_genplist_t *oc_plist); +H5_DLL herr_t H5G_get_objinfo(H5G_loc_t *loc, const char *name, + hbool_t follow_link, H5G_stat_t *statbuf/*out*/, hid_t dxpl_id); +H5_DLL H5F_t *H5G_insertion_file(H5G_loc_t *loc, const char *name, hid_t dxpl_id); +H5_DLL herr_t H5G_free_grp_name(H5G_t *grp); H5_DLL herr_t H5G_get_shared_count(H5G_t *grp); H5_DLL herr_t H5G_mount(H5G_t *grp); H5_DLL herr_t H5G_unmount(H5G_t *grp); @@ -179,24 +143,36 @@ H5_DLL herr_t H5G_unmount(H5G_t *grp); /* * These functions operate on symbol table nodes. */ +H5_DLL herr_t H5G_node_close(const H5F_t *f); H5_DLL herr_t H5G_node_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int fwidth, haddr_t heap); -H5_DLL herr_t H5G_node_init(H5F_t *f); -H5_DLL herr_t H5G_node_close(const H5F_t *f); /* - * 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. + * These functions operate on group object locations. + */ +/* forward reference for later use */ +H5_DLL herr_t H5G_obj_ent_decode(H5F_t *f, const uint8_t **pp, + struct H5O_loc_t *oloc); +H5_DLL herr_t H5G_obj_ent_encode(H5F_t *f, uint8_t **pp, + const struct H5O_loc_t *oloc); + +/* + * These functions operate on group hierarchy names. */ -H5_DLL herr_t H5G_ent_encode(H5F_t *f, uint8_t **pp, const H5G_entry_t *ent); -H5_DLL herr_t H5G_ent_decode(H5F_t *f, const uint8_t **pp, - H5G_entry_t *ent/*out*/); -H5_DLL const H5G_cache_t *H5G_ent_cache(const H5G_entry_t *ent, H5G_type_t *cache_type); -H5_DLL herr_t H5G_ent_copy(H5G_entry_t *dst, const H5G_entry_t *src, - H5G_ent_copy_depth_t depth); -H5_DLL herr_t H5G_ent_reset(H5G_entry_t *ent); -H5_DLL herr_t H5G_free_ent_name(H5G_entry_t *ent); -H5_DLL herr_t H5G_ent_debug(H5F_t *f, hid_t dxpl_id, const H5G_entry_t *ent, FILE * stream, - int indent, int fwidth, haddr_t heap); +H5_DLL herr_t H5G_name_replace(H5G_obj_t type, H5G_loc_t *loc, + H5RS_str_t *src_name, H5G_loc_t *src_loc, + H5RS_str_t *dst_name, H5G_loc_t *dst_loc, H5G_names_op_t op); +H5_DLL herr_t H5G_name_reset(H5G_name_t *name); +H5_DLL herr_t H5G_name_copy(H5G_name_t *dst, const H5G_name_t *src, H5G_copy_depth_t depth); +H5_DLL herr_t H5G_name_free(H5G_name_t *name); + +/* + * These functions operate on group "locations" + */ +H5_DLL herr_t H5G_loc(hid_t loc_id, H5G_loc_t *loc); +H5_DLL herr_t H5G_loc_find(H5G_loc_t *loc, const char *name, + H5G_loc_t *obj_loc/*out*/, hid_t dxpl_id); +H5_DLL herr_t H5G_loc_reset(H5G_loc_t *loc); +H5_DLL herr_t H5G_loc_free(H5G_loc_t *loc); + #endif diff --git a/src/H5Gpublic.h b/src/H5Gpublic.h index 1a7807a..f906a84 100644 --- a/src/H5Gpublic.h +++ b/src/H5Gpublic.h @@ -32,6 +32,7 @@ #include "H5public.h" #include "H5Ipublic.h" #include "H5Opublic.h" +#include "H5Tpublic.h" #ifdef __cplusplus extern "C" { @@ -82,6 +83,8 @@ typedef struct H5G_slink_stat_t { typedef struct H5G_stat_t { unsigned long fileno; /* File number */ + H5T_cset_t cset; /* Character set of link name */ + time_t ctime; /* Creation time */ H5G_obj_t type; /* Object type */ union { H5G_obj_stat_t obj; /* Information about objects */ @@ -121,10 +124,12 @@ H5_DLL int H5Gget_comment(hid_t loc_id, const char *name, size_t bufsize, char *buf); H5_DLL hid_t H5Gcreate_expand(hid_t loc_id, const char *name, hid_t gcpl_id, hid_t gapl_id); -H5_DLL herr_t H5Gcopy(hid_t id_src, hid_t loc_dst, const char *name_dst, +H5_DLL hid_t H5Gget_create_plist(hid_t group_id); +H5_DLL herr_t H5Gcopy(hid_t src_id, hid_t dst_loc_id, const char *name_dst, hid_t plist_id); #ifdef __cplusplus } #endif #endif + diff --git a/src/H5Gstab.c b/src/H5Gstab.c index b63e1cd..926ff7f 100644 --- a/src/H5Gstab.c +++ b/src/H5Gstab.c @@ -26,87 +26,170 @@ #include "H5Fpkg.h" /* File access */ #include "H5Gpkg.h" /* Groups */ #include "H5HLprivate.h" /* Local Heaps */ +#include "H5Iprivate.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ +/* Private typedefs */ +/* User data for finding a name in the link messages */ +typedef struct { + /* downward */ + H5F_t *f; /* Pointer to file for insertion */ + const char *name; /* Name to search for */ + + /* upward */ + H5G_entry_t *ent; /* Entry to update when match found */ +} H5G_stab_ud1_t; + +/* User data for finding object info from B-tree */ +typedef struct { + /* downward */ + H5O_loc_t *grp_oloc; /* Object location of group */ + hid_t dxpl_id; /* DXPL during operation */ + haddr_t heap_addr; /* Local heap address for group */ + + /* upward */ + H5G_stat_t *statbuf; /* Caller's statbuf */ +} H5G_stab_fnd_ud1_t; + +/* User data for finding link information from B-tree */ +typedef struct { + /* downward */ + H5F_t *file; /* Pointer to file for query */ + hid_t dxpl_id; /* DXPL during operation */ + const char *name; /* Name to search for */ + haddr_t heap_addr; /* Local heap address for group */ + + /* upward */ + H5O_link_t *lnk; /* Caller's link location */ +} H5G_stab_fnd_ud2_t; + +/* User data for finding object location from B-tree */ +typedef struct { + /* downward */ + H5F_t *file; /* Pointer to file for query */ + size_t size; /* Buffer size for link value */ + haddr_t heap_addr; /* Local heap address for group */ + hid_t dxpl_id; /* DXPL during operation */ + + /* upward */ + char *buf; /* Buffer to fill with link value */ +} H5G_stab_fnd_ud3_t; + /* Private prototypes */ /*------------------------------------------------------------------------- - * Function: H5G_stab_create + * Function: H5G_stab_create_components * - * Purpose: Creates a new empty symbol table (object header, name heap, + * Purpose: Creates the components for a new, empty, symbol table (name heap * and B-tree). The caller can specify an initial size for the - * name heap. The object header of the group is opened for - * write access. + * name heap. * * 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: - * * Return: Non-negative on success/Negative on failure * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Aug 1 1997 - * - * Modifications: + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Nov 7 2005 * *------------------------------------------------------------------------- */ herr_t -H5G_stab_create(H5F_t *f, hid_t dxpl_id, size_t init, H5G_entry_t *self/*out*/) +H5G_stab_create_components(H5F_t *f, H5O_stab_t *stab, size_t size_hint, hid_t dxpl_id) { - size_t name; /*offset of "" name */ - H5O_stab_t stab; /*symbol table message */ - herr_t ret_value=SUCCEED; /* Return value */ + size_t name_offset; /* Offset of "" name */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5G_stab_create, FAIL) + FUNC_ENTER_NOAPI(H5G_stab_create_components, FAIL) /* * Check arguments. */ HDassert(f); - HDassert(self); - init = MAX(init, H5HL_SIZEOF_FREE(f) + 2); + HDassert(stab); + HDassert(size_hint > 0); + + /* Create the B-tree */ + if(H5B_create(f, dxpl_id, H5B_SNODE, NULL, &(stab->btree_addr)/*out*/) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create B-tree") /* Create symbol table private heap */ - if (H5HL_create(f, dxpl_id, init, &(stab.heap_addr)/*out*/)<0) + if(H5HL_create(f, dxpl_id, size_hint, &(stab->heap_addr)/*out*/) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create heap") - name = H5HL_insert(f, dxpl_id, stab.heap_addr, 1, ""); - if ((size_t)(-1)==name) + name_offset = H5HL_insert(f, dxpl_id, stab->heap_addr, 1, ""); + if((size_t)(-1) == name_offset) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't initialize heap") /* * B-tree's won't work if the first name isn't at the beginning * of the heap. */ - assert(0 == name); + HDassert(0 == name_offset); - /* Create the B-tree */ - if (H5B_create(f, dxpl_id, H5B_SNODE, NULL, &(stab.btree_addr)/*out*/) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create B-tree") +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_stab_create_components() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_stab_create + * + * 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. 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. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 1 1997 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_stab_create(H5O_loc_t *grp_oloc, H5O_stab_t *stab, hid_t dxpl_id) +{ + H5O_ginfo_t ginfo; /* Group info message */ + size_t heap_hint; /* Local heap size hint */ + size_t size_hint; /* Local heap size hint */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_stab_create, FAIL) /* - * Create symbol table object header. It has a zero link count - * since nothing refers to it yet. The link count will be - * incremented if the object is added to the group directed graph. + * Check arguments. */ - if (H5O_create(f, dxpl_id, 4 + 2 * H5F_SIZEOF_ADDR(f), self/*out*/) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create header") + HDassert(grp_oloc); + HDassert(stab); + + /* Get the group info */ + if(NULL == H5O_read(grp_oloc, H5O_GINFO_ID, 0, &ginfo, dxpl_id)) + HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't get group info") + + /* Adjust the size hint, if necessary */ + if(ginfo.lheap_size_hint == 0) + heap_hint = ginfo.est_num_entries * (ginfo.est_name_len + 1); + else + heap_hint = ginfo.lheap_size_hint; + size_hint = MAX(heap_hint, H5HL_SIZEOF_FREE(grp_oloc->file) + 2); + + if(H5G_stab_create_components(grp_oloc->file, stab, size_hint, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create symbol table components") /* * Insert the symbol table message into the object header and the symbol * table entry. */ - if (H5O_modify(self, H5O_STAB_ID, H5O_NEW_MESG, H5O_FLAG_CONSTANT, H5O_UPDATE_TIME, &stab, dxpl_id)<0) { - H5O_close(self); + if(H5O_modify(grp_oloc, H5O_STAB_ID, H5O_NEW_MESG, 0, H5O_UPDATE_TIME, stab, dxpl_id) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create message") - } - self->cache.stab.btree_addr = stab.btree_addr; - self->cache.stab.heap_addr = stab.heap_addr; - self->type = H5G_CACHED_STAB; done: FUNC_LEAVE_NOAPI(ret_value) @@ -114,62 +197,47 @@ done: /*------------------------------------------------------------------------- - * Function: H5G_stab_find - * - * Purpose: Finds a symbol named NAME in the symbol table whose - * description is stored in GRP_ENT in file F and returns its - * symbol table entry through OBJ_ENT (which is optional). + * Function: H5G_stab_insert_real * - * Errors: + * Purpose: Insert a new symbol into a table. + * The name of the new symbol is NAME and its symbol + * table entry is OBJ_LNK. * * Return: Non-negative on success/Negative on failure * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Aug 1 1997 - * - * Modifications: - * - * Pedro Vicente, <pvn@ncsa.uiuc.edu> 22 Aug 2002 - * Added `id to name' support. - * Added a deep copy of the symbol table entry + * Programmer: Quincey Koziol + * koziol@uiuc.edu + * Nov 7 2005 * *------------------------------------------------------------------------- */ herr_t -H5G_stab_find(H5G_entry_t *grp_ent, const char *name, - H5G_entry_t *obj_ent/*out*/, hid_t dxpl_id) +H5G_stab_insert_real(H5F_t *f, H5O_stab_t *stab, const char *name, + H5O_link_t *obj_lnk, hid_t dxpl_id) { - H5G_bt_ud1_t udata; /*data to pass through B-tree */ - H5O_stab_t stab; /*symbol table message */ - herr_t ret_value=SUCCEED; /* Return value */ + H5G_bt_ud1_t udata; /* Data to pass through B-tree */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5G_stab_find, FAIL) + FUNC_ENTER_NOAPI(H5G_stab_insert_real, FAIL) - /* Check arguments */ - assert(grp_ent); - assert(grp_ent->file); - assert(obj_ent); - assert(name && *name); + /* check arguments */ + HDassert(f); + HDassert(stab); + HDassert(name && *name); + HDassert(obj_lnk); - /* set up the udata */ - if (NULL == H5O_read(grp_ent, H5O_STAB_ID, 0, &stab, dxpl_id)) - HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't read message") + /* Initialize data to pass through B-tree */ udata.common.name = name; - udata.common.heap_addr = stab.heap_addr; - udata.ent = obj_ent; - - /* search the B-tree */ - if (H5B_find(grp_ent->file, dxpl_id, H5B_SNODE, stab.btree_addr, &udata) < 0) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "not found") + udata.common.heap_addr = stab->heap_addr; + udata.lnk = obj_lnk; - /* Set the name for the symbol entry OBJ_ENT */ - if (H5G_ent_set_name( grp_ent, obj_ent, name ) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "cannot insert name") + /* Insert into symbol table */ + if(H5B_insert(f, dxpl_id, H5B_SNODE, stab->btree_addr, &udata) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert entry") done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5G_stab_find() */ +} /* end H5G_stab_insert_real() */ /*------------------------------------------------------------------------- @@ -188,46 +256,29 @@ done: *------------------------------------------------------------------------- */ herr_t -H5G_stab_insert(H5G_entry_t *grp_ent, const char *name, H5G_entry_t *obj_ent, - hbool_t inc_link, hid_t dxpl_id) +H5G_stab_insert(H5O_loc_t *grp_oloc, const char *name, H5O_link_t *obj_lnk, + hid_t dxpl_id) { - H5O_stab_t stab; /*symbol table message */ - H5G_bt_ud1_t udata; /*data to pass through B-tree */ - herr_t ret_value=SUCCEED; /* Return value */ + H5O_stab_t stab; /* Symbol table message */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5G_stab_insert, FAIL) /* check arguments */ - assert(grp_ent && grp_ent->file); - assert(name && *name); - assert(obj_ent && obj_ent->file); - if (grp_ent->file->shared != obj_ent->file->shared) - HGOTO_ERROR(H5E_SYM, H5E_LINK, FAIL, "interfile hard links are not allowed") - - /* Set the name for the symbol entry OBJ_ENT */ - if (H5G_ent_set_name( grp_ent, obj_ent, name ) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "cannot insert name") + HDassert(grp_oloc && grp_oloc->file); + HDassert(name && *name); + HDassert(obj_lnk); - /* initialize data to pass through B-tree */ - if (NULL == H5O_read(grp_ent, H5O_STAB_ID, 0, &stab, dxpl_id)) - HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "not a symbol table") + /* Retrieve symbol table message */ + if(NULL == H5O_read(grp_oloc, H5O_STAB_ID, 0, &stab, dxpl_id)) + HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "not a symbol table") - udata.common.name = name; - udata.common.heap_addr = stab.heap_addr; - udata.ent = obj_ent; - - /* insert */ - if (H5B_insert(grp_ent->file, dxpl_id, H5B_SNODE, stab.btree_addr, &udata) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert entry") - - /* Increment link count on object, if appropriate */ - if(inc_link) - if (H5O_link(obj_ent, 1, dxpl_id) < 0) - HGOTO_ERROR(H5E_SYM, H5E_LINK, FAIL, "unable to increment hard link count") + if(H5G_stab_insert_real(grp_oloc->file, &stab, name, obj_lnk, dxpl_id) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5B_ITER_ERROR, "unable to insert the name") done: - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_stab_insert() */ /*------------------------------------------------------------------------- @@ -240,36 +291,37 @@ done: * Programmer: Robb Matzke * Thursday, September 17, 1998 * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t -H5G_stab_remove(H5G_entry_t *grp_ent, const char *name, hid_t dxpl_id) +H5G_stab_remove(H5O_loc_t *loc, const char *name, H5G_obj_t *obj_type, hid_t dxpl_id) { H5O_stab_t stab; /*symbol table message */ H5G_bt_ud2_t udata; /*data to pass through B-tree */ - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5G_stab_remove, FAIL) - assert(grp_ent && grp_ent->file); - assert(name && *name); + HDassert(loc && loc->file); + HDassert(name && *name); - /* initialize data to pass through B-tree */ - if (NULL==H5O_read(grp_ent, H5O_STAB_ID, 0, &stab, dxpl_id)) - HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "not a symbol table") + /* Read in symbol table message */ + if(NULL == H5O_read(loc, H5O_STAB_ID, 0, &stab, dxpl_id)) + HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "not a symbol table") + + /* Initialize data to pass through B-tree */ udata.common.name = name; udata.common.heap_addr = stab.heap_addr; udata.adj_link = TRUE; + udata.obj_type = obj_type; - /* remove */ - if (H5B_remove(grp_ent->file, dxpl_id, H5B_SNODE, stab.btree_addr, &udata)<0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to remove entry") + /* Remove from symbol table */ + if(H5B_remove(loc->file, dxpl_id, H5B_SNODE, stab.btree_addr, &udata) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to remove entry") done: FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5G_stab_remove() */ /*------------------------------------------------------------------------- @@ -318,47 +370,324 @@ done: /*------------------------------------------------------------------------- - * Function: H5G_stab_copy_tmp + * Function: H5G_stab_iterate + * + * Purpose: Iterate over the objects in a group * - * Purpose: copy a group symbol table and memeber objects from SRC file to DST file. + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Monday, October 3, 2005 * - * Return: Non-negative on success - * Negative on failure. + *------------------------------------------------------------------------- + */ +herr_t +H5G_stab_iterate(H5O_loc_t *oloc, hid_t gid, int skip, int *last_obj, + H5G_iterate_t op, void *op_data, hid_t dxpl_id) +{ + H5G_bt_it_ud1_t udata; /* User data to pass to B-tree callback */ + H5O_stab_t stab; /* Info about symbol table */ + herr_t ret_value; + + FUNC_ENTER_NOAPI(H5G_stab_iterate, FAIL) + + /* Sanity check */ + HDassert(oloc); + HDassert(H5I_GROUP == H5I_get_type(gid)); + HDassert(last_obj); + HDassert(op); + + /* Get the B-tree info */ + if(NULL == H5O_read(oloc, H5O_STAB_ID, 0, &stab, dxpl_id)) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to determine local heap address") + + /* Build udata to pass through H5B_iterate() to H5G_node_iterate() */ + udata.group_id = gid; + udata.skip = skip; + udata.heap_addr = stab.heap_addr; + udata.op = op; + udata.op_data = op_data; + udata.final_ent = last_obj; + + /* Iterate over the group members */ + if((ret_value = H5B_iterate(oloc->file, H5AC_dxpl_id, H5B_SNODE, + H5G_node_iterate, stab.btree_addr, &udata))<0) + HERROR(H5E_SYM, H5E_CANTNEXT, "iteration operator failed"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_stab_iterate() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_stab_count * - * Programmer: Peter Cao - * September 10, 2005 + * Purpose: Count the # of objects in a group * - * Note: This routine should be replaced with proper call to "real" - * stab creation routine after the "big group revision" checkin - * occurs. -QAK + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, September 6, 2005 * *------------------------------------------------------------------------- */ herr_t -H5G_stab_copy_tmp(H5F_t *f_dst, H5O_stab_t *stab_dst, hid_t dxpl_id) +H5G_stab_count(H5O_loc_t *oloc, hsize_t *num_objs, hid_t dxpl_id) +{ + H5O_stab_t stab; /* Info about symbol table */ + herr_t ret_value; + + FUNC_ENTER_NOAPI(H5G_stab_count, FAIL) + + /* Sanity check */ + HDassert(oloc); + HDassert(num_objs); + + /* Reset the number of objects in the group */ + *num_objs = 0; + + /* Get the B-tree info */ + if(NULL == H5O_read(oloc, H5O_STAB_ID, 0, &stab, dxpl_id)) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to determine local heap address") + + /* Iterate over the group members */ + if((ret_value = H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, H5G_node_sumup, stab.btree_addr, num_objs)) < 0) + HERROR(H5E_SYM, H5E_CANTINIT, "iteration operator failed"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_stab_count() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_stab_get_name_by_idx + * + * Purpose: Returns the name of objects in the group by giving index. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Raymond Lu + * Nov 20, 2002 + * + *------------------------------------------------------------------------- + */ +ssize_t +H5G_stab_get_name_by_idx(H5O_loc_t *oloc, hsize_t idx, char* name, + size_t size, hid_t dxpl_id) +{ + H5O_stab_t stab; /* Info about local heap & B-tree */ + H5G_bt_it_ud2_t udata; /* Iteration information */ + ssize_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_stab_get_name_by_idx, FAIL) + + /* Sanity check */ + HDassert(oloc); + + /* Get the B-tree & local heap info */ + if(NULL == H5O_read(oloc, H5O_STAB_ID, 0, &stab, dxpl_id)) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to determine local heap address") + + /* Set iteration information */ + udata.idx = idx; + udata.num_objs = 0; + udata.heap_addr = stab.heap_addr; + udata.name = NULL; + + /* Iterate over the group members */ + if((ret_value = H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, H5G_node_name, stab.btree_addr, &udata))<0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "iteration operator failed") + + /* If we don't know the name now, we almost certainly went out of bounds */ + if(udata.name==NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "index out of bound") + + /* Get the length of the name */ + ret_value = (ssize_t)HDstrlen(udata.name); + + /* Copy the name into the user's buffer, if given */ + if(name) { + HDstrncpy(name, udata.name, MIN((size_t)(ret_value+1),size)); + if((size_t)ret_value >= size) + name[size-1]='\0'; + } /* end if */ + +done: + /* Free the duplicated name */ + if(udata.name!=NULL) + H5MM_xfree(udata.name); + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_stab_get_name_by_idx() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_get_objtype_by_idx + * + * Purpose: Private function for H5Gget_objtype_by_idx. + * Returns the type of objects in the group by giving index. + * + * Return: Success: H5G_GROUP(1), H5G_DATASET(2), H5G_TYPE(3) + * + * Failure: UNKNOWN + * + * Programmer: Raymond Lu + * Nov 20, 2002 + * + *------------------------------------------------------------------------- + */ +H5G_obj_t +H5G_stab_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx, hid_t dxpl_id) +{ + H5O_stab_t stab; /* Info about local heap & B-tree */ + H5G_bt_it_ud3_t udata; /* User data for B-tree callback */ + H5G_obj_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_stab_get_type_by_idx, H5G_UNKNOWN) + + /* Sanity check */ + HDassert(oloc); + + /* Get the B-tree & local heap info */ + if(NULL == H5O_read(oloc, H5O_STAB_ID, 0, &stab, dxpl_id)) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5G_UNKNOWN, "unable to determine local heap address") + + /* Set iteration information */ + udata.idx = idx; + udata.num_objs = 0; + udata.type = H5G_UNKNOWN; + + /* Iterate over the group members */ + if(H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, H5G_node_type, stab.btree_addr, &udata) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "iteration operator failed") + + /* If we don't know the type now, we almost certainly went out of bounds */ + if(udata.type == H5G_UNKNOWN) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "index out of bound") + + /* Set the return value */ + ret_value = udata.type; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_stab_get_type_by_idx() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_stab_lookup_cb + * + * Purpose: B-tree 'find' callback to retrieve location for an object + * + * Return: Success: Non-negative + * + * Failure: Negative + * + * Programmer: Quincey Koziol + * Sep 20, 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_stab_lookup_cb(const H5G_entry_t *ent, void *_udata) { - size_t size_init, name_offset; - herr_t ret_value = SUCCEED; /* Return value */ + H5G_stab_fnd_ud2_t *udata = (H5G_stab_fnd_ud2_t *)_udata; /* 'User data' passed in */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5G_stab_lookup_cb) + + /* Set link info */ + if(udata->lnk) { + /* Set (default) common info for link */ + udata->lnk->cset = H5T_CSET_ASCII; + udata->lnk->ctime = 0; + udata->lnk->name = H5MM_xstrdup(udata->name); + + /* Object is a symbolic link */ + if(H5G_CACHED_SLINK == ent->type) { + const char *s; /* Pointer to link value */ + const H5HL_t *heap; /* Pointer to local heap for group */ + + /* Lock the local heap */ + if(NULL == (heap = H5HL_protect(udata->file, udata->dxpl_id, udata->heap_addr))) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to read protect link value") - FUNC_ENTER_NOAPI(H5G_stab_copy_tmp, FAIL) + s = H5HL_offset_into(udata->file, heap, ent->cache.slink.lval_offset); - HDassert(f_dst); - HDassert(stab_dst); + /* Copy the link value */ + udata->lnk->u.soft.name = H5MM_xstrdup(s); - /* create B-tree private heap */ - size_init = MAX(H5G_SIZE_HINT, H5HL_SIZEOF_FREE(f_dst) + 2); - if (H5HL_create(f_dst, dxpl_id, size_init, &(stab_dst->heap_addr))<0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create heap") + /* Release the local heap */ + if(H5HL_unprotect(udata->file, udata->dxpl_id, heap, udata->heap_addr, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to read unprotect link value") - name_offset = H5HL_insert(f_dst, dxpl_id, stab_dst->heap_addr, 1, ""); - if ((size_t)(-1)==name_offset) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't initialize heap") - assert(0 == name_offset); - - /* create the B-tree */ - if (H5B_create(f_dst, dxpl_id, H5B_SNODE, NULL, &(stab_dst->btree_addr)) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create B-tree") + /* Set link type */ + udata->lnk->type = H5G_LINK_SOFT; + } /* end if */ + else { + /* Set address of object */ + udata->lnk->u.hard.addr = ent->header; + + /* Set link type */ + udata->lnk->type = H5G_LINK_HARD; + } /* end else */ + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_stab_lookup_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_stab_lookup + * + * Purpose: Look up an object relative to a group, using symbol table + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Sep 20 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_stab_lookup(H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk, + hid_t dxpl_id) +{ + H5G_bt_ud3_t bt_udata; /* Data to pass through B-tree */ + H5G_stab_fnd_ud2_t udata; /* 'User data' to give to callback */ + H5O_stab_t stab; /* Symbol table message */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_stab_lookup, FAIL) + + /* check arguments */ + HDassert(grp_oloc && grp_oloc->file); + HDassert(name && *name); + HDassert(lnk); + + /* Set up user data to pass to 'find' operation callback */ + udata.file = grp_oloc->file; + udata.dxpl_id = dxpl_id; + udata.name = name; + udata.lnk = lnk; + + /* Set up the user data for actual B-tree find operation */ + if(NULL == H5O_read(grp_oloc, H5O_STAB_ID, 0, &stab, dxpl_id)) + HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't read message") + bt_udata.common.name = name; + bt_udata.common.heap_addr = stab.heap_addr; + bt_udata.op = H5G_stab_lookup_cb; + bt_udata.op_data = &udata; + + /* Finish up user data to pass to 'find' operation callback */ + udata.heap_addr = stab.heap_addr; + + /* Search the B-tree */ + if(H5B_find(grp_oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, &bt_udata) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "not found") done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5G_stab_copy_tmp() */ +} /* end H5G_stab_lookup() */ + diff --git a/src/H5Gtest.c b/src/H5Gtest.c new file mode 100644 index 0000000..6c7d3ee --- /dev/null +++ b/src/H5Gtest.c @@ -0,0 +1,185 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> + * Monday, October 17, 2005 + * + * Purpose: Group testing functions. + */ + +#define H5G_PACKAGE /*suppress error about including H5Gpkg */ +#define H5G_TESTING /*suppress warning about H5G testing funcs*/ + + +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Gpkg.h" /* Groups */ +#include "H5Iprivate.h" /* IDs */ + + +/*-------------------------------------------------------------------------- + NAME + H5G_is_empty_test + PURPOSE + Determine whether a group contains no objects + USAGE + htri_t H5G_is_empty_test(gid) + hid_t gid; IN: group to check + RETURNS + Non-negative TRUE/FALSE on success, negative on failure + DESCRIPTION + Checks to see if the group has no link messages and no symbol table message + dimensionality and shape. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + DO NOT USE THIS FUNCTION FOR ANYTHING EXCEPT TESTING + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +htri_t +H5G_is_empty_test(hid_t gid) +{ + H5G_t *grp = NULL; /* Pointer to group */ + htri_t msg_exists = 0; /* Indicate that a header message is present */ + htri_t ret_value = TRUE; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_is_empty_test, FAIL) + + /* Get group structure */ + if(NULL == (grp = H5I_object_verify(gid, H5I_GROUP))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group") + + /* Check if the group has any link messages */ + if((msg_exists = H5O_exists(&(grp->oloc), H5O_LINK_ID, 0, H5AC_dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to read object header") + if(msg_exists > 0) + HGOTO_DONE(FALSE) + + /* Check if the group has a symbol table message */ + if((msg_exists = H5O_exists(&(grp->oloc), H5O_STAB_ID, 0, H5AC_dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to read object header") + if(msg_exists > 0) + HGOTO_DONE(FALSE) + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5G_is_empty_test() */ + + +/*-------------------------------------------------------------------------- + NAME + H5G_has_links_test + PURPOSE + Determine whether a group contains link messages + USAGE + htri_t H5G_has_links_test(gid) + hid_t gid; IN: group to check + unsigned *nmsgs; OUT: # of link messages in header + RETURNS + Non-negative TRUE/FALSE on success, negative on failure + DESCRIPTION + Checks to see if the group has link messages and how many. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + DO NOT USE THIS FUNCTION FOR ANYTHING EXCEPT TESTING + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +htri_t +H5G_has_links_test(hid_t gid, unsigned *nmsgs) +{ + H5G_t *grp = NULL; /* Pointer to group */ + htri_t msg_exists = 0; /* Indicate that a header message is present */ + htri_t ret_value = TRUE; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_has_links_test, FAIL) + + /* Get group structure */ + if(NULL == (grp = H5I_object_verify(gid, H5I_GROUP))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group") + + /* Check if the group has any link messages */ + if((msg_exists = H5O_exists(&(grp->oloc), H5O_LINK_ID, 0, H5AC_dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to read object header") + if(msg_exists == 0) + HGOTO_DONE(FALSE) + + /* Check if the group has a symbol table message */ + if((msg_exists = H5O_exists(&(grp->oloc), H5O_STAB_ID, 0, H5AC_dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to read object header") + if(msg_exists > 0) + HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "both symbol table and link messages found") + + /* Check if we should retrieve the number of link messages */ + if(nmsgs) { + int msg_count; /* Number of messages of a type */ + + /* Check how many link messages there are */ + if((msg_count = H5O_count(&(grp->oloc), H5O_LINK_ID, H5AC_dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOUNT, FAIL, "unable to count link messages") + *nmsgs = (unsigned)msg_count; + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5G_has_links_test() */ + + +/*-------------------------------------------------------------------------- + NAME + H5G_has_stab_test + PURPOSE + Determine whether a group contains a symbol table message + USAGE + htri_t H5G_has_stab_test(gid) + hid_t gid; IN: group to check + RETURNS + Non-negative TRUE/FALSE on success, negative on failure + DESCRIPTION + Checks to see if the group has a symbol table message. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + DO NOT USE THIS FUNCTION FOR ANYTHING EXCEPT TESTING + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +htri_t +H5G_has_stab_test(hid_t gid) +{ + H5G_t *grp = NULL; /* Pointer to group */ + htri_t msg_exists = 0; /* Indicate that a header message is present */ + htri_t ret_value = TRUE; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_has_stab_test, FAIL) + + /* Get group structure */ + if(NULL == (grp = H5I_object_verify(gid, H5I_GROUP))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group") + + /* Check if the group has a symbol table message */ + if((msg_exists = H5O_exists(&(grp->oloc), H5O_STAB_ID, 0, H5AC_dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to read object header") + if(msg_exists == 0) + HGOTO_DONE(FALSE) + + /* Check if the group has any link messages */ + if((msg_exists = H5O_exists(&(grp->oloc), H5O_LINK_ID, 0, H5AC_dxpl_id)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to read object header") + if(msg_exists > 0) + HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "both symbol table and link messages found") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5G_has_stab_test() */ + diff --git a/src/H5Gtraverse.c b/src/H5Gtraverse.c new file mode 100644 index 0000000..c43ffbb --- /dev/null +++ b/src/H5Gtraverse.c @@ -0,0 +1,589 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5Gtraverse.c + * Sep 13 2005 + * Quincey Koziol <koziol@ncsa.uiuc.edu> + * + * Purpose: Functions for traversing group hierarchy + * + *------------------------------------------------------------------------- + */ +#define H5F_PACKAGE /*suppress error about including H5Fpkg */ +#define H5G_PACKAGE /*suppress error about including H5Gpkg */ + + +/* Packages needed by this file... */ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Fpkg.h" /* File access */ +#include "H5Gpkg.h" /* Groups */ +#include "H5HLprivate.h" /* Local Heaps */ +#include "H5MMprivate.h" /* Memory management */ + +/* Private typedefs */ + +/* User data for path traversal routine */ +typedef struct { + H5G_loc_t *obj_loc; /* Object location */ +} H5G_trav_ud1_t; + +/* Private macros */ + +/* Local variables */ +static char *H5G_comp_g = NULL; /*component buffer */ +static size_t H5G_comp_alloc_g = 0; /*sizeof component buffer */ + +/* PRIVATE PROTOTYPES */ +static herr_t H5G_traverse_slink_cb(H5G_loc_t *grp_loc/*in*/, const char *name, + const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/); +static herr_t H5G_traverse_slink(H5G_loc_t *grp_loc/*in,out*/, H5O_link_t *lnk, + H5G_loc_t *obj_loc/*in,out*/, int *nlinks/*in,out*/, hid_t dxpl_id); +static herr_t H5G_traverse_mount(H5G_loc_t *loc/*in,out*/); +static herr_t H5G_traverse_real(const H5G_loc_t *loc, const char *name, + unsigned target, int *nlinks, H5G_traverse_t op, void *op_data, + hid_t dxpl_id); + + +/*------------------------------------------------------------------------- + * Function: H5G_traverse_term_interface + * + * Purpose: Terminates part of the H5G interface - free the global + * component buffer. + * + * Return: Success: Non-negative. + * + * Failure: Negative. + * + * Programmer: Quincey Koziol + * Monday, September 26, 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_traverse_term_interface(void) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_traverse_term_interface) + + /* Free the global component buffer */ + H5G_comp_g = H5MM_xfree(H5G_comp_g); + H5G_comp_alloc_g = 0; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5G_traverse_term_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_traverse_slink_cb + * + * Purpose: Callback for symbolic link traversal. This routine sets the + * correct information for the object location. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, September 13, 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_traverse_slink_cb(H5G_loc_t UNUSED *grp_loc, const char UNUSED *name, const H5O_link_t UNUSED *lnk, + H5G_loc_t *obj_loc, void *_udata/*in,out*/) +{ + H5G_trav_ud1_t *udata = (H5G_trav_ud1_t *)_udata; /* User data passed in */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5G_traverse_slink_cb) + + /* Check for dangling soft link */ + if(obj_loc == NULL) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "component not found") + + /* Copy new location information for resolved object */ + H5O_loc_copy(udata->obj_loc->oloc, obj_loc->oloc, H5O_COPY_DEEP); + +done: + /* Release the group location for the object */ + /* (Group traversal callbacks are responsible for either taking ownership + * of the group location for the object, or freeing it. - QAK) + */ + if(obj_loc) + H5G_loc_free(obj_loc); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_traverse_slink_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_traverse_slink + * + * Purpose: Traverses symbolic link. The link head appears in the group + * whose entry is GRP_LOC and the link tail entry is OBJ_LOC. + * + * Return: Success: Non-negative, OBJ_LOC will contain information + * about the object to which the link points and + * GRP_LOC will contain the information about + * the group in which the link tail appears. + * + * Failure: Negative + * + * Programmer: Robb Matzke + * Friday, April 10, 1998 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_traverse_slink(H5G_loc_t *grp_loc/*in,out*/, H5O_link_t *lnk, + H5G_loc_t *obj_loc/*in,out*/, int *nlinks/*in,out*/, hid_t dxpl_id) +{ + H5G_trav_ud1_t udata; /* User data to pass to link traversal callback */ + H5G_name_t tmp_obj_path; /* Temporary copy of object's path */ + hbool_t tmp_obj_path_set = FALSE; /* Flag to indicate that tmp object path is initialized */ + H5O_loc_t tmp_grp_oloc; /* Temporary copy of group entry */ + H5G_name_t tmp_grp_path; /* Temporary copy of group's path */ + H5G_loc_t tmp_grp_loc; /* Temporary copy of group's location */ + hbool_t tmp_grp_path_set = FALSE; /* Flag to indicate that tmp group path is initialized */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5G_traverse_slink) + + /* Sanity check */ + HDassert(grp_loc); + HDassert(lnk); + HDassert(lnk->type == H5G_LINK_SOFT); + HDassert(nlinks); + + /* Set up temporary location */ + tmp_grp_loc.oloc = &tmp_grp_oloc; + tmp_grp_loc.path = &tmp_grp_path; + + /* Portably initialize the temporary objects */ + H5G_loc_reset(&tmp_grp_loc); + + /* Clone the group location, so we can track the names properly */ + /* ("tracking the names properly" means to ignore the effects of the + * soft link traversal on the object's & group's paths - QAK) + */ + H5G_loc_copy(&tmp_grp_loc, grp_loc, H5G_COPY_DEEP); + tmp_grp_path_set = TRUE; + + /* Hold the object's group hier. path to restore later */ + /* (Part of "tracking the names properly") */ + H5G_name_reset(&tmp_obj_path); + H5G_name_copy(&tmp_obj_path, obj_loc->path, H5G_COPY_SHALLOW); + tmp_obj_path_set = TRUE; + + /* Set up user data for traversal callback */ + udata.obj_loc = obj_loc; + + /* Traverse to the link's last component */ + if(H5G_traverse_real(&tmp_grp_loc, lnk->u.soft.name, H5G_TARGET_NORMAL, nlinks, H5G_traverse_slink_cb, &udata, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to follow symbolic link") + +done: + /* Restore object's group hier. path */ + if(tmp_obj_path_set) { + H5G_name_free(obj_loc->path); + H5G_name_copy(obj_loc->path, &tmp_obj_path, H5G_COPY_SHALLOW); + } /* end if */ + + /* Release cloned copy of group path */ + if(tmp_grp_path_set) + H5G_name_free(&tmp_grp_path); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_traverse_slink() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_traverse_mount + * + * Purpose: If LNK is a mount point then copy the entry for the root + * group of the mounted file into LNK. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Tuesday, October 6, 1998 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_traverse_mount(H5G_loc_t *obj_loc/*in,out*/) +{ + H5F_t *parent = obj_loc->oloc->file; /* File of object */ + unsigned lt, rt, md = 0; /* Binary search indices */ + int cmp; + H5O_loc_t *oloc = NULL; /* Object location for mount points */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_traverse_mount, FAIL) + + /* Sanity check */ + HDassert(obj_loc); + + /* + * The loop is necessary because we might have file1 mounted at the root + * of file2, which is mounted somewhere in file3. + */ + do { + /* + * Use a binary search to find the potential mount point in the mount + * table for the parent + */ + lt = 0; + rt = parent->mtab.nmounts; + cmp = -1; + while(lt < rt && cmp) { + md = (lt + rt) / 2; + oloc = H5G_oloc(parent->mtab.child[md].group); + cmp = H5F_addr_cmp(obj_loc->oloc->addr, oloc->addr); + if(cmp < 0) + rt = md; + else + lt = md + 1; + } /* end while */ + + /* Copy root info over to ENT */ + if(0 == cmp) { + H5G_name_t *root_path; /* Path of root group */ + + /* Get the location for the root group in the child's file */ + oloc = H5G_oloc(parent->mtab.child[md].file->shared->root_grp); + root_path = H5G_nameof(parent->mtab.child[md].file->shared->root_grp); + + /* Copy the entry for the root group */ + if(H5O_loc_copy(obj_loc->oloc, oloc, H5O_COPY_DEEP) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, FAIL, "unable to copy object location") + + /* Don't lose the user path of the group when we copy the root group's path */ + if(H5G_name_copy(obj_loc->path, root_path, H5G_COPY_CANON) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, FAIL, "unable to copy object path") + + /* Switch to child's file */ + parent = oloc->file; + } /* end if */ + } while(!cmp); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_traverse_mount() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_traverse_real + * + * Purpose: Internal version of path traversal routine + * + * Return: Success: Non-negative if name can be fully resolved. + * + * Failure: Negative if the name could not be fully + * resolved. + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 11 1997 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_traverse_real(const H5G_loc_t *_loc, const char *name, unsigned target, + int *nlinks, H5G_traverse_t op, void *op_data, hid_t dxpl_id) +{ + H5G_loc_t loc; /* Location of start object */ + H5O_loc_t grp_oloc; /* Object loc. for current group */ + H5G_name_t grp_path; /* Path for current group */ + H5G_loc_t grp_loc; /* Location of group */ + H5O_loc_t obj_oloc; /* Object found */ + H5G_name_t obj_path; /* Path for object found */ + H5G_loc_t obj_loc; /* Location of object */ + size_t nchars; /* component name length */ + H5O_link_t lnk; /* Link information for object */ + hbool_t link_valid = FALSE; /* Flag to indicate that the link information is valid */ + hbool_t obj_loc_valid = FALSE; /* Flag to indicate that the object location is valid */ + hbool_t group_copy = FALSE; /* Flag to indicate that the group entry is copied */ + hbool_t last_comp = FALSE; /* Flag to indicate that a component is the last component in the name */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5G_traverse_real) + + /* Check parameters */ + HDassert(_loc); + HDassert(name); + HDassert(nlinks); + HDassert(op); + + /* + * Where does the searching start? For absolute names it starts at the + * root of the file; for relative names it starts at CWG. + */ + /* Check if we need to get the root group's entry */ + if('/' == *name) { + H5G_t *root_grp; /* Temporary pointer to root group of file */ + + /* Look up root group for starting location */ + root_grp = H5G_rootof(_loc->oloc->file); + HDassert(root_grp); + + /* Set the location entry to the root group's info */ + loc.oloc=&(root_grp->oloc); + loc.path=&(root_grp->path); + } /* end if */ + else { + loc.oloc = _loc->oloc; + loc.path = _loc->path; + } /* end else */ + + /* Set up group & object locations */ + grp_loc.oloc = &grp_oloc; + grp_loc.path = &grp_path; + obj_loc.oloc = &obj_oloc; + obj_loc.path = &obj_path; + + /* Deep copy of the starting location to group location */ + if(H5G_loc_copy(&grp_loc, &loc, H5G_COPY_DEEP) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to copy location") + group_copy = TRUE; + + /* Clear object location */ + if(H5G_loc_reset(&obj_loc) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to reset location") + + /* Check for needing a larger buffer for the individual path name components */ + if(HDstrlen(name) + 1 > H5G_comp_alloc_g) { + H5G_comp_alloc_g = MAX3(1024, 2 * H5G_comp_alloc_g, HDstrlen(name) + 1); + H5G_comp_g = H5MM_realloc(H5G_comp_g, H5G_comp_alloc_g); + if(!H5G_comp_g) { + H5G_comp_alloc_g = 0; + HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "unable to allocate component buffer") + } /* end if */ + } /* end if */ + + /* Traverse the path */ + while((name = H5G_component(name, &nchars)) && *name) { + const char *s; /* Temporary string pointer */ + herr_t lookup_status; /* Status from object lookup */ + + /* + * Copy the component name into a null-terminated buffer so + * we can pass it down to the other symbol table functions. + */ + HDmemcpy(H5G_comp_g, name, nchars); + H5G_comp_g[nchars] = '\0'; + + /* + * The special name `.' is a no-op. + */ + if('.' == H5G_comp_g[0] && !H5G_comp_g[1]) { + name += nchars; + continue; + } /* end if */ + + /* Check if this is the last component of the name */ + if(!((s = H5G_component(name + nchars, NULL)) && *s)) + last_comp = TRUE; + + /* If there's valid information in the link, reset it */ + if(link_valid) { + H5O_reset(H5O_LINK_ID, &lnk); + link_valid = FALSE; + } /* end if */ + + /* Get information for object in current group */ + /* (Defer issuing error for back lookup until later) */ + lookup_status = H5G_obj_lookup(grp_loc.oloc, H5G_comp_g, &lnk/*out*/, dxpl_id); + + /* If the lookup was OK, try traversing soft links and mount points, if allowed */ + if(lookup_status >= 0) { + /* Indicate that the link info is valid */ + link_valid = TRUE; + + /* Build object's group hier. location */ + if(H5G_name_set(grp_loc.path, obj_loc.path, H5G_comp_g) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "cannot set name") + + /* Set the object location, if it's a hard link set the address also */ + obj_loc.oloc->file = grp_loc.oloc->file; + if(lnk.type == H5G_LINK_HARD) { + obj_loc.oloc->addr = lnk.u.hard.addr; + } /* end if */ + obj_loc_valid = TRUE; + + /* + * If we found a symbolic link then we should follow it. But if this + * is the last component of the name and the H5G_TARGET_SLINK bit of + * TARGET is set then we don't follow it. + */ + if(H5G_LINK_SOFT == lnk.type && + (0 == (target & H5G_TARGET_SLINK) || !last_comp)) { + if((*nlinks)-- <= 0) + HGOTO_ERROR(H5E_SYM, H5E_SLINK, FAIL, "too many links") + if(H5G_traverse_slink(&grp_loc/*in,out*/, &lnk/*in*/, &obj_loc, nlinks, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "symbolic link traversal failed") + } /* end if */ + + /* + * Resolve mount points to the mounted group. Do not do this step if + * the H5G_TARGET_MOUNT bit of TARGET is set and this is the last + * component of the name. + * + * (If this link is a hard link, try to perform mount point traversal) + * + * (Note that the soft link traversal above can change the status of + * the object (into a hard link), so don't use an 'else' statement + * here. -QAK) + */ + if(H5F_addr_defined(obj_loc.oloc->addr) && + (0 == (target & H5G_TARGET_MOUNT) || !last_comp)) { + if(H5G_traverse_mount(&obj_loc/*in,out*/) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "mount point traversal failed") + } /* end if */ + } /* end if */ + + /* Check for last component in name provided */ + if(last_comp) { + H5O_link_t *tmp_lnk; /* Pointer to link info for callback */ + H5G_loc_t *tmp_loc; /* Pointer to object location for callback */ + + /* Set callback parameters appropriately, based on link being found */ + if(lookup_status < 0) { + tmp_lnk = NULL; + tmp_loc = NULL; + } /* end if */ + else { + tmp_lnk = &lnk; + tmp_loc = &obj_loc; + } /* end else */ + + /* Operator routine will take care of object location, succeed or fail */ + obj_loc_valid = FALSE; + + /* Call 'operator' routine */ + if((op)(&grp_loc, H5G_comp_g, tmp_lnk, tmp_loc, op_data) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CALLBACK, FAIL, "traversal operator failed") + HGOTO_DONE(SUCCEED) + } /* end if */ + + /* Handle lookup failures now */ + if(lookup_status < 0) { + /* If an intermediate group doesn't exist & flag is set, create the group */ + if(target & H5G_CRT_INTMD_GROUP) { + H5O_ginfo_t ginfo; /* Group info message for parent group */ + + /* Get the group info for parent group */ + if(NULL == H5O_read(grp_loc.oloc, H5O_GINFO_ID, 0, &ginfo, dxpl_id)) + HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't get group info") + + /* Create the intermediate group */ +/* XXX: Should we allow user to control the group creation params here? -QAK */ + if(H5G_obj_create(grp_oloc.file, dxpl_id, &ginfo, obj_loc.oloc/*out*/) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create group entry") + + /* Insert new group into current group's symbol table */ + if(H5G_loc_insert(&grp_loc, H5G_comp_g, &obj_loc, TRUE, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert intermediate group") + + /* Close new group */ + if(H5O_close(obj_loc.oloc) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to close") + } /* end if */ + else + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "component not found") + } /* end if */ + + /* + * Advance to the next component of the path. + */ + + /* Transfer "ownership" of the object's information to the group object */ + H5G_loc_free(&grp_loc); + H5G_loc_copy(&grp_loc, &obj_loc, H5G_COPY_SHALLOW); + H5G_loc_reset(&obj_loc); + obj_loc_valid = FALSE; + + /* Advance to next component in string */ + name += nchars; + } /* end while */ + + /* If we've fallen through to here, the name must be something like just '.' + * and we should issue the callback on that. -QAK + */ + /* Reset "group copied" flag */ + /* (callback will take ownership of group location, succeed or fail) */ + HDassert(group_copy); + group_copy = FALSE; + + /* Call 'operator' routine */ + if((op)(&grp_loc, ".", NULL, &grp_loc, op_data) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTNEXT, FAIL, "traversal operator failed") + HGOTO_DONE(SUCCEED) + +done: + /* If the object location is still valid (usually in an error situation), reset it */ + if(obj_loc_valid) + H5G_loc_free(&obj_loc); + /* If there's valid information in the link, reset it */ + if(link_valid) + H5O_reset(H5O_LINK_ID, &lnk); + /* If we copied something into the group location, free it */ + if(group_copy) + H5G_loc_free(&grp_loc); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_traverse_real() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_traverse + * + * Purpose: Traverse a path from a location & perform an operation when + * the last component of the name is reached. + * + * Return: Success: Non-negative if path can be fully traversed. + * Failure: Negative if the path could not be fully + * traversed. + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Sep 13 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_traverse(const H5G_loc_t *loc, const char *name, unsigned target, H5G_traverse_t op, + void *op_data, hid_t dxpl_id) +{ + int nlinks = H5G_NLINKS; /* Link countdown value */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_traverse, FAIL) + + /* Check args */ + if(!name || !*name) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "no name given") + if(!loc) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "no starting location") + if(!op) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "no operation provided") + + /* Go perform "real" traversal */ + if(H5G_traverse_real(loc, name, target, &nlinks, op, op_data, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "path traversal failed") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_traverse() */ + @@ -153,8 +153,7 @@ H5HL_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, haddr_t *addr_p/*out*/) if (NULL==(heap = H5FL_CALLOC(H5HL_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); heap->addr = *addr_p + (hsize_t)sizeof_hdr; - heap->disk_alloc = size_hint; - heap->mem_alloc = size_hint; + heap->heap_alloc = size_hint; if (NULL==(heap->chunk = H5FL_BLK_CALLOC(heap_chunk,(sizeof_hdr + size_hint)))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); @@ -254,25 +253,24 @@ H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * udata1, HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); /* heap data size */ - H5F_DECODE_LENGTH(f, p, heap->disk_alloc); - heap->mem_alloc = heap->disk_alloc; + H5F_DECODE_LENGTH(f, p, heap->heap_alloc); /* free list head */ H5F_DECODE_LENGTH(f, p, free_block); - if (free_block != H5HL_FREE_NULL && free_block >= heap->disk_alloc) + if (free_block != H5HL_FREE_NULL && free_block >= heap->heap_alloc) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list"); /* data */ H5F_addr_decode(f, &p, &(heap->addr)); - if (NULL==(heap->chunk = H5FL_BLK_CALLOC(heap_chunk,(sizeof_hdr + heap->mem_alloc)))) + if (NULL==(heap->chunk = H5FL_BLK_CALLOC(heap_chunk,(sizeof_hdr + heap->heap_alloc)))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - if (heap->disk_alloc && - H5F_block_read(f, H5FD_MEM_LHEAP, heap->addr, heap->disk_alloc, dxpl_id, heap->chunk + sizeof_hdr) < 0) + if (heap->heap_alloc && + H5F_block_read(f, H5FD_MEM_LHEAP, heap->addr, heap->heap_alloc, dxpl_id, heap->chunk + sizeof_hdr) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unable to read heap data"); /* Build free list */ while (H5HL_FREE_NULL != free_block) { - if (free_block >= heap->disk_alloc) + if (free_block >= heap->heap_alloc) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list"); if (NULL==(fl = H5FL_MALLOC(H5HL_free_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); @@ -287,7 +285,7 @@ H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * udata1, H5F_DECODE_LENGTH(f, p, free_block); H5F_DECODE_LENGTH(f, p, fl->size); - if (fl->offset + fl->size > heap->disk_alloc) + if (fl->offset + fl->size > heap->heap_alloc) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list"); } @@ -324,7 +322,7 @@ done: * * It used to be called during cache eviction, where it * attempted to size the disk space allocation for the - * actuall size of the heap. However, this causes problems + * actual size of the heap. However, this causes problems * in the parallel case, as the reuslting disk allocations * may not be synchronized. * @@ -338,15 +336,15 @@ done: static herr_t H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap) { - herr_t ret_value = SUCCEED; - size_t sizeof_hdr; + size_t new_heap_size = heap->heap_alloc; /* New size of heap */ + size_t sizeof_hdr; + herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(H5HL_minimize_heap_space, FAIL) /* check args */ HDassert( f ); HDassert( heap ); - HDassert( heap->disk_alloc == heap->mem_alloc ); sizeof_hdr = H5HL_SIZEOF_HDR(f); /* cache H5HL header size for file */ @@ -355,14 +353,14 @@ H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap) * eliminating free blocks at the tail of the buffer before flushing the * buffer out. */ - if (heap->freelist) { + if(heap->freelist) { H5HL_free_t *tmp_fl; H5HL_free_t *last_fl = NULL; /* Search for a free block at the end of the buffer */ for (tmp_fl = heap->freelist; tmp_fl; tmp_fl = tmp_fl->next) /* Check if the end of this free block is at the end of the buffer */ - if (tmp_fl->offset + tmp_fl->size == heap->mem_alloc) { + if (tmp_fl->offset + tmp_fl->size == heap->heap_alloc) { last_fl = tmp_fl; break; } @@ -371,98 +369,90 @@ H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap) * Found free block at the end of the buffer, decide what to do * about it */ - if (last_fl) { - size_t new_mem_size = heap->mem_alloc; /* New size of memory buffer */ - + if(last_fl) { /* * If the last free block's size is more than half the memory * buffer size (and the memory buffer is larger than the * minimum size), reduce or eliminate it. */ - if (last_fl->size >= (heap->mem_alloc / 2) && heap->mem_alloc > H5HL_MIN_HEAP) { + if(last_fl->size >= (heap->heap_alloc / 2) && heap->heap_alloc > H5HL_MIN_HEAP) { /* * Reduce size of buffer until it's too small or would * eliminate the free block */ - while (new_mem_size > H5HL_MIN_HEAP && - new_mem_size >= (last_fl->offset + H5HL_SIZEOF_FREE(f))) - new_mem_size /= 2; + while(new_heap_size > H5HL_MIN_HEAP && + new_heap_size >= (last_fl->offset + H5HL_SIZEOF_FREE(f))) + new_heap_size /= 2; /* * Check if reducing the memory buffer size would - * eliminate the free list + * eliminate the free block */ - if (new_mem_size < (last_fl->offset + H5HL_SIZEOF_FREE(f))) { + if(new_heap_size < (last_fl->offset + H5HL_SIZEOF_FREE(f))) { /* Check if this is the only block on the free list */ - if (last_fl->prev == NULL && last_fl->next == NULL) { + if(last_fl->prev == NULL && last_fl->next == NULL) { /* Double the new memory size */ - new_mem_size *= 2; + new_heap_size *= 2; /* Truncate the free block */ - last_fl->size = H5HL_ALIGN(new_mem_size - last_fl->offset); - new_mem_size = last_fl->offset + last_fl->size; + last_fl->size = H5HL_ALIGN(new_heap_size - last_fl->offset); + new_heap_size = last_fl->offset + last_fl->size; assert(last_fl->size >= H5HL_SIZEOF_FREE(f)); } else { /* * Set the size of the memory buffer to the start * of the free list */ - new_mem_size = last_fl->offset; + new_heap_size = last_fl->offset; /* Eliminate the free block from the list */ last_fl = H5HL_remove_free(heap, last_fl); - } + } /* end else */ } else { /* Truncate the free block */ - last_fl->size = H5HL_ALIGN(new_mem_size - last_fl->offset); - new_mem_size = last_fl->offset + last_fl->size; + last_fl->size = H5HL_ALIGN(new_heap_size - last_fl->offset); + new_heap_size = last_fl->offset + last_fl->size; assert(last_fl->size >= H5HL_SIZEOF_FREE(f)); assert(last_fl->size == H5HL_ALIGN(last_fl->size)); - } - - /* Resize the memory buffer and reserved space in file */ - if (new_mem_size != heap->mem_alloc) { - - heap->mem_alloc = new_mem_size; - heap->chunk = H5FL_BLK_REALLOC(heap_chunk, heap->chunk, (sizeof_hdr + new_mem_size)); - - if (!heap->chunk) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") - } - } - } - } + } /* end else */ + } /* end if */ + } /* end if */ + } /* end if */ /* * If the heap grew smaller than disk storage then move the * data segment of the heap to another contiguous block of disk * storage. */ - if (heap->mem_alloc != heap->disk_alloc) { - haddr_t old_addr = heap->addr, new_addr; + if(new_heap_size != heap->heap_alloc) { + haddr_t old_addr = heap->addr, + new_addr; + + HDassert(new_heap_size < heap->heap_alloc); - HDassert( heap->mem_alloc < heap->disk_alloc ); + /* Resize the memory buffer */ + heap->chunk = H5FL_BLK_REALLOC(heap_chunk, heap->chunk, (sizeof_hdr + new_heap_size)); + if(!heap->chunk) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") /* Release old space on disk */ - H5_CHECK_OVERFLOW(heap->disk_alloc, size_t, hsize_t); - H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, old_addr, (hsize_t)heap->disk_alloc); + /* (Should be safe to free old heap space first, since it's shrinking -QAK) */ + H5_CHECK_OVERFLOW(heap->heap_alloc, size_t, hsize_t); + H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, old_addr, (hsize_t)heap->heap_alloc); H5E_clear_stack(NULL); /* don't really care if the free failed */ /* Allocate new space on disk */ - H5_CHECK_OVERFLOW(heap->mem_alloc, size_t, hsize_t); - - if (HADDR_UNDEF == (new_addr = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, (hsize_t)heap->mem_alloc))) + H5_CHECK_OVERFLOW(new_heap_size, size_t, hsize_t); + if(HADDR_UNDEF == (new_addr = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, (hsize_t)new_heap_size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate file space for heap") + /* Update heap info*/ heap->addr = new_addr; - - /* Set new size of block on disk */ - heap->disk_alloc = heap->mem_alloc; - } + heap->heap_alloc = new_heap_size; + } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) - } /* H5HL_minimize_heap_space() */ @@ -506,7 +496,7 @@ H5HL_serialize(H5F_t *f, H5HL_t *heap, uint8_t *buf) *p++ = 0; /*reserved*/ *p++ = 0; /*reserved*/ *p++ = 0; /*reserved*/ - H5F_ENCODE_LENGTH(f, p, heap->mem_alloc); + H5F_ENCODE_LENGTH(f, p, heap->heap_alloc); H5F_ENCODE_LENGTH(f, p, fl ? fl->offset : H5HL_FREE_NULL); H5F_addr_encode(f, &p, heap->addr); @@ -573,7 +563,6 @@ H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HL_t *heap) HDassert( f ); HDassert( H5F_addr_defined(addr) ); HDassert( heap ); - HDassert( heap->disk_alloc == heap->mem_alloc ); if (heap->cache_info.is_dirty) { haddr_t hdr_end_addr; @@ -588,14 +577,14 @@ H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HL_t *heap) if (H5F_addr_eq(heap->addr, hdr_end_addr)) { /* The header and data are contiguous */ - if (H5F_block_write(f, H5FD_MEM_LHEAP, addr, (sizeof_hdr + heap->disk_alloc), + if (H5F_block_write(f, H5FD_MEM_LHEAP, addr, (sizeof_hdr + heap->heap_alloc), dxpl_id, heap->chunk) < 0) HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header and data to file") } else { if (H5F_block_write(f, H5FD_MEM_LHEAP, addr, sizeof_hdr, dxpl_id, heap->chunk) < 0) HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header to file") - if (H5F_block_write(f, H5FD_MEM_LHEAP, heap->addr, heap->disk_alloc, + if (H5F_block_write(f, H5FD_MEM_LHEAP, heap->addr, heap->heap_alloc, dxpl_id, heap->chunk + sizeof_hdr) < 0) HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap data to file") } @@ -717,7 +706,7 @@ H5HL_compute_size(const H5F_t *f, const H5HL_t *heap, size_t *size_ptr) HDassert(heap); HDassert(size_ptr); - *size_ptr = H5HL_SIZEOF_HDR(f) + heap->disk_alloc; + *size_ptr = H5HL_SIZEOF_HDR(f) + heap->heap_alloc; FUNC_LEAVE_NOAPI(SUCCEED) } /* H5HL_compute_size() */ @@ -766,8 +755,8 @@ H5HL_read(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t offset, size_t size, voi if (NULL == (heap = H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_READ))) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unable to load heap"); - assert(offset < heap->mem_alloc); - assert(offset + size <= heap->mem_alloc); + assert(offset < heap->heap_alloc); + assert(offset + size <= heap->heap_alloc); if (!buf && NULL==(buf = H5MM_malloc(size))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); @@ -864,7 +853,7 @@ H5HL_offset_into(H5F_t *f, const H5HL_t *heap, size_t offset) FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_offset_into) assert(f); assert(heap); - assert(offset < heap->mem_alloc); + assert(offset < heap->heap_alloc); FUNC_LEAVE_NOAPI(heap->chunk + H5HL_SIZEOF_HDR(f) + offset) } @@ -976,12 +965,9 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t buf_size, const void * { H5HL_t *heap = NULL; unsigned heap_flags = H5AC__NO_FLAGS_SET; - H5HL_free_t *fl = NULL, *max_fl = NULL; - htri_t tri_result; - herr_t result; + H5HL_free_t *fl = NULL, *last_fl = NULL; size_t offset = 0; - size_t need_size, old_size, need_more; - size_t new_disk_alloc; + size_t need_size; hbool_t found; size_t sizeof_hdr; /* Cache H5HL header size for file */ size_t ret_value; /* Return value */ @@ -989,10 +975,10 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t buf_size, const void * FUNC_ENTER_NOAPI(H5HL_insert, (size_t)(-1)); /* check arguments */ - assert(f); - assert(H5F_addr_defined(addr)); - assert(buf_size > 0); - assert(buf); + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(buf_size > 0); + HDassert(buf); if (0==(f->intent & H5F_ACC_RDWR)) HGOTO_ERROR (H5E_HEAP, H5E_WRITEERROR, (size_t)(-1), "no write intent on file"); @@ -1016,28 +1002,28 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t buf_size, const void * * Look for a free slot large enough for this object and which would * leave zero or at least H5G_SIZEOF_FREE bytes left over. */ - for (fl=heap->freelist, found=FALSE; fl; fl=fl->next) { - if (fl->size > need_size && - fl->size - need_size >= H5HL_SIZEOF_FREE(f)) { - /* a bigger free block was found */ + for(fl = heap->freelist, found = FALSE; fl; fl = fl->next) { + if(fl->size > need_size && + fl->size - need_size >= H5HL_SIZEOF_FREE(f)) { + /* a big enough free block was found */ offset = fl->offset; fl->offset += need_size; fl->size -= need_size; - assert (fl->offset==H5HL_ALIGN (fl->offset)); - assert (fl->size==H5HL_ALIGN (fl->size)); + HDassert(fl->offset == H5HL_ALIGN(fl->offset)); + HDassert(fl->size == H5HL_ALIGN(fl->size)); found = TRUE; break; - } else if (fl->size == need_size) { + } else if(fl->size == need_size) { /* free block of exact size found */ offset = fl->offset; fl = H5HL_remove_free(heap, fl); found = TRUE; break; - } else if (!max_fl || max_fl->offset < fl->offset) { - /* use worst fit */ - max_fl = fl; + } else if(!last_fl || last_fl->offset < fl->offset) { + /* track free space that's closest to end of heap */ + last_fl = fl; } - } + } /* end for */ /* * If no free chunk was large enough, then allocate more space and @@ -1045,34 +1031,41 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t buf_size, const void * * can extend that free chunk. Otherwise we'll have to make another * free chunk. If the heap must expand, we double its size. */ - if (found==FALSE) { - need_more = MAX3(need_size, heap->mem_alloc, H5HL_SIZEOF_FREE(f)); - - new_disk_alloc = heap->disk_alloc + need_more; - HDassert( heap->disk_alloc < new_disk_alloc ); - H5_CHECK_OVERFLOW(heap->disk_alloc, size_t, hsize_t); - H5_CHECK_OVERFLOW(new_disk_alloc, size_t, hsize_t); - - /* extend the current heap if we can... */ - tri_result = H5MF_can_extend(f, H5FD_MEM_LHEAP, heap->addr, - (hsize_t)(heap->disk_alloc), - (hsize_t)need_more); - if ( tri_result == TRUE ) { - - result = H5MF_extend(f, H5FD_MEM_LHEAP, heap->addr, - (hsize_t)(heap->disk_alloc), - (hsize_t)need_more); - if ( result < 0 ) { - - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), \ - "can't extend heap on disk"); - } + if(found == FALSE) { + size_t need_more; /* How much more space we need */ + size_t new_heap_alloc; /* Final size of space allocated for heap */ + htri_t can_extend; /* Whether the local heap's data segment on disk can be extended */ + + /* At least double the heap's size, making certain there's enough room + * for the new object */ + need_more = MAX(need_size, heap->heap_alloc); + + /* If there is no last free block or it's not at the end of the heap, + * and the amount of space to allocate is not big enough to include at + * least the new object and a free-list info, trim down the amount of + * space requested to just the amount of space needed. (Generally + * speaking, this only occurs when the heap is small -QAK) + */ + if(!(last_fl && last_fl->offset + last_fl->size == heap->heap_alloc) + && (need_more < (need_size + H5HL_SIZEOF_FREE(f)))) + need_more = need_size; - heap->disk_alloc = new_disk_alloc; + new_heap_alloc = heap->heap_alloc + need_more; + HDassert(heap->heap_alloc < new_heap_alloc); + H5_CHECK_OVERFLOW(heap->heap_alloc, size_t, hsize_t); + H5_CHECK_OVERFLOW(new_heap_alloc, size_t, hsize_t); - } else { /* ...if we can't, allocate a new chunk & release the old */ + /* Check if current heap is extendible */ + can_extend = H5MF_can_extend(f, H5FD_MEM_LHEAP, heap->addr, (hsize_t)(heap->heap_alloc), (hsize_t)need_more); + if(can_extend < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "unable to check whether heap can be extended") - haddr_t old_addr = heap->addr; + /* extend the current heap if we can... */ + if(can_extend == TRUE) { + if(H5MF_extend(f, H5FD_MEM_LHEAP, heap->addr, (hsize_t)(heap->heap_alloc), (hsize_t)need_more) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "can't extend heap on disk") + } /* end if */ + else { /* ...if we can't, allocate a new chunk & release the old */ haddr_t new_addr; /* The new allocation may fail -- to avoid the possiblity of @@ -1081,54 +1074,50 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t buf_size, const void * */ /* allocate new disk space for the heap */ - if ( (new_addr = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, - (hsize_t)new_disk_alloc)) == HADDR_UNDEF ) { - - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), \ - "unable to allocate file space for heap") - } + if((new_addr = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, (hsize_t)new_heap_alloc)) == HADDR_UNDEF) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "unable to allocate file space for heap") /* Release old space on disk */ - H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, old_addr, - (hsize_t)heap->disk_alloc); + H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, heap->addr, (hsize_t)heap->heap_alloc); H5E_clear_stack(NULL); /* don't really care if the free failed */ heap->addr = new_addr; - heap->disk_alloc = new_disk_alloc; - } + } /* end else */ - if (max_fl && max_fl->offset + max_fl->size == heap->mem_alloc) { + /* If the last free list in the heap is at the end of the heap, extend it */ + if(last_fl && last_fl->offset + last_fl->size == heap->heap_alloc) { /* - * Increase the size of the maximum free block. + * Increase the size of the last free block. */ - offset = max_fl->offset; - max_fl->offset += need_size; - max_fl->size += need_more - need_size; - assert (max_fl->offset==H5HL_ALIGN (max_fl->offset)); - assert (max_fl->size==H5HL_ALIGN (max_fl->size)); + offset = last_fl->offset; + last_fl->offset += need_size; + last_fl->size += need_more - need_size; + HDassert(last_fl->offset == H5HL_ALIGN(last_fl->offset)); + HDassert(last_fl->size == H5HL_ALIGN(last_fl->size)); - if (max_fl->size < H5HL_SIZEOF_FREE(f)) { + if (last_fl->size < H5HL_SIZEOF_FREE(f)) { #ifdef H5HL_DEBUG - if (H5DEBUG(HL) && max_fl->size) { + if (H5DEBUG(HL) && last_fl->size) { fprintf(H5DEBUG(HL), "H5HL: lost %lu bytes at line %d\n", - (unsigned long)(max_fl->size), __LINE__); + (unsigned long)(last_fl->size), __LINE__); } #endif - max_fl = H5HL_remove_free(heap, max_fl); + last_fl = H5HL_remove_free(heap, last_fl); } - } else { + } /* end if */ + else { /* * Create a new free list element large enough that we can * take some space out of it right away. */ - offset = heap->mem_alloc; - if (need_more - need_size >= H5HL_SIZEOF_FREE(f)) { - if (NULL==(fl = H5FL_MALLOC(H5HL_free_t))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "memory allocation failed"); - fl->offset = heap->mem_alloc + need_size; + offset = heap->heap_alloc; + if(need_more - need_size >= H5HL_SIZEOF_FREE(f)) { + if(NULL == (fl = H5FL_MALLOC(H5HL_free_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "memory allocation failed") + fl->offset = heap->heap_alloc + need_size; fl->size = need_more - need_size; - assert (fl->offset==H5HL_ALIGN (fl->offset)); - assert (fl->size==H5HL_ALIGN (fl->size)); + HDassert(fl->offset == H5HL_ALIGN(fl->offset)); + HDassert(fl->size == H5HL_ALIGN(fl->size)); fl->prev = NULL; fl->next = heap->freelist; if (heap->freelist) heap->freelist->prev = fl; @@ -1140,40 +1129,39 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t buf_size, const void * (unsigned long)(need_more - need_size), __LINE__); #endif } - } + } /* end else */ #ifdef H5HL_DEBUG if (H5DEBUG(HL)) { fprintf(H5DEBUG(HL), "H5HL: resize mem buf from %lu to %lu bytes\n", - (unsigned long)(heap->mem_alloc), - (unsigned long)(heap->mem_alloc + need_more)); + (unsigned long)(heap->heap_alloc), + (unsigned long)(heap->heap_alloc + need_more)); } #endif - old_size = heap->mem_alloc; - heap->mem_alloc += need_more; - heap->chunk = H5FL_BLK_REALLOC(heap_chunk,heap->chunk, - (sizeof_hdr + heap->mem_alloc)); - if (NULL==heap->chunk) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "memory allocation failed"); - - /* clear new section so junk doesn't appear in the file */ - HDmemset(heap->chunk + sizeof_hdr + old_size, 0, need_more); - } + heap->heap_alloc = new_heap_alloc; + heap->chunk = H5FL_BLK_REALLOC(heap_chunk, heap->chunk, (sizeof_hdr + heap->heap_alloc)); + if(NULL == heap->chunk) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "memory allocation failed") + + /* Clear new section so junk doesn't appear in the file */ + /* (Avoid clearing section which will be overwritten with newly inserted data) */ + HDmemset(heap->chunk + sizeof_hdr + offset + buf_size, 0, (new_heap_alloc - (offset + buf_size))); + } /* end if */ + /* * Copy the data into the heap */ HDmemcpy(heap->chunk + sizeof_hdr + offset, buf, buf_size); /* Set return value */ - ret_value=offset; + ret_value = offset; done: - if (heap && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, heap, heap_flags) != SUCCEED) - HDONE_ERROR(H5E_HEAP, H5E_PROTECT, (size_t)(-1), "unable to release object header"); - - FUNC_LEAVE_NOAPI(ret_value); + if(heap && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, heap, heap_flags) != SUCCEED) + HDONE_ERROR(H5E_HEAP, H5E_PROTECT, (size_t)(-1), "unable to release object header") + FUNC_LEAVE_NOAPI(ret_value) } /* H5HL_insert() */ #ifdef NOT_YET @@ -1227,8 +1215,8 @@ H5HL_write(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t offset, size_t size, co if (NULL == (heap = H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_WRITE))) HGOTO_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to load heap"); - assert(offset < heap->mem_alloc); - assert(offset + size <= heap->mem_alloc); + assert(offset < heap->heap_alloc); + assert(offset + size <= heap->heap_alloc); heap_flags |= H5AC__DIRTIED_FLAG; HDmemcpy(heap->chunk + H5HL_SIZEOF_HDR(f) + offset, buf, size); @@ -1305,9 +1293,8 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t offset, size_t size) if (NULL == (heap = H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_WRITE))) HGOTO_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to load heap"); - HDassert( offset < heap->mem_alloc ); - HDassert( offset + size <= heap->mem_alloc ); - HDassert( heap->disk_alloc == heap->mem_alloc ); + HDassert( offset < heap->heap_alloc ); + HDassert( offset + size <= heap->heap_alloc ); fl = heap->freelist; heap_flags |= H5AC__DIRTIED_FLAG; @@ -1331,28 +1318,19 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t offset, size_t size) assert (fl->offset==H5HL_ALIGN (fl->offset)); assert (fl->size==H5HL_ALIGN (fl->size)); fl2 = H5HL_remove_free(heap, fl2); - if ( ( (fl->offset + fl->size) == heap->mem_alloc ) && - ( (2 * fl->size) > heap->mem_alloc ) ) { - - if ( H5HL_minimize_heap_space(f, dxpl_id, heap) != - SUCCEED ) { - - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \ - "heap size minimization failed"); - } + if ( ( (fl->offset + fl->size) == heap->heap_alloc ) && + ( (2 * fl->size) > heap->heap_alloc ) ) { + if ( H5HL_minimize_heap_space(f, dxpl_id, heap) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "heap size minimization failed") } HGOTO_DONE(SUCCEED); } fl2 = fl2->next; } - if ( ( (fl->offset + fl->size) == heap->mem_alloc ) && - ( (2 * fl->size) > heap->mem_alloc ) ) { - - if ( H5HL_minimize_heap_space(f, dxpl_id, heap) != SUCCEED ) { - - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \ - "heap size minimization failed"); - } + if ( ( (fl->offset + fl->size) == heap->heap_alloc ) && + ( (2 * fl->size) > heap->heap_alloc ) ) { + if ( H5HL_minimize_heap_space(f, dxpl_id, heap) < 0 ) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "heap size minimization failed") } HGOTO_DONE(SUCCEED); @@ -1365,28 +1343,19 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t offset, size_t size) fl->size += fl2->size; assert (fl->size==H5HL_ALIGN (fl->size)); fl2 = H5HL_remove_free(heap, fl2); - if ( ( (fl->offset + fl->size) == heap->mem_alloc ) && - ( (2 * fl->size) > heap->mem_alloc ) ) { - - if ( H5HL_minimize_heap_space(f, dxpl_id, heap) != - SUCCEED ) { - - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \ - "heap size minimization failed"); - } + if ( ( (fl->offset + fl->size) == heap->heap_alloc ) && + ( (2 * fl->size) > heap->heap_alloc ) ) { + if ( H5HL_minimize_heap_space(f, dxpl_id, heap) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "heap size minimization failed") } HGOTO_DONE(SUCCEED); } fl2 = fl2->next; } - if ( ( (fl->offset + fl->size) == heap->mem_alloc ) && - ( (2 * fl->size) > heap->mem_alloc ) ) { - - if ( H5HL_minimize_heap_space(f, dxpl_id, heap) != SUCCEED ) { - - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \ - "heap size minimization failed"); - } + if ( ( (fl->offset + fl->size) == heap->heap_alloc ) && + ( (2 * fl->size) > heap->heap_alloc ) ) { + if ( H5HL_minimize_heap_space(f, dxpl_id, heap) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "heap size minimization failed") } HGOTO_DONE(SUCCEED); } @@ -1407,6 +1376,7 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t offset, size_t size) #endif HGOTO_DONE(SUCCEED); } + /* * Add an entry to the free list. */ @@ -1422,14 +1392,10 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t offset, size_t size) heap->freelist->prev = fl; heap->freelist = fl; - if ( ( (fl->offset + fl->size) == heap->mem_alloc ) && - ( (2 * fl->size) > heap->mem_alloc ) ) { - - if ( H5HL_minimize_heap_space(f, dxpl_id, heap) != SUCCEED ) { - - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, \ - "heap size minimization failed"); - } + if ( ( (fl->offset + fl->size) == heap->heap_alloc ) && + ( (2 * fl->size) > heap->heap_alloc ) ) { + if ( H5HL_minimize_heap_space(f, dxpl_id, heap) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "heap size minimization failed") } done: @@ -1488,8 +1454,8 @@ H5HL_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr) assert(!H5F_addr_overflow(addr,sizeof_hdr)); if(H5F_addr_eq(heap->addr,addr+sizeof_hdr)) { /* Free the contiguous local heap in one call */ - H5_CHECK_OVERFLOW(sizeof_hdr+heap->disk_alloc,size_t,hsize_t); - if (H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, addr, (hsize_t)(sizeof_hdr+heap->disk_alloc))<0) + H5_CHECK_OVERFLOW(sizeof_hdr+heap->heap_alloc,size_t,hsize_t); + if (H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, addr, (hsize_t)(sizeof_hdr+heap->heap_alloc))<0) HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free contiguous local heap"); } /* end if */ else { @@ -1499,8 +1465,8 @@ H5HL_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr) HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap header"); /* Free the local heap's data */ - H5_CHECK_OVERFLOW(heap->disk_alloc,size_t,hsize_t); - if (H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, heap->addr, (hsize_t)heap->disk_alloc)<0) + H5_CHECK_OVERFLOW(heap->heap_alloc,size_t,hsize_t); + if (H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, heap->addr, (hsize_t)heap->heap_alloc)<0) HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap data"); } /* end else */ @@ -1518,3 +1484,44 @@ done: FUNC_LEAVE_NOAPI(ret_value); } /* end H5HL_delete() */ + +/*------------------------------------------------------------------------- + * Function: H5HL_get_size + * + * Purpose: Retrieves the current size of a heap + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Nov 7 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HL_get_size(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t *size) +{ + H5HL_t *heap = NULL; /* Heap to query */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5HL_get_size, FAIL) + + /* check arguments */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(size); + + /* Get heap pointer */ + if(NULL == (heap = H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_READ))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap") + + /* Set the size to return */ + *size = heap->heap_alloc; + +done: + if(heap && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, heap, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release local heap") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HL_get_size() */ + diff --git a/src/H5HLdbg.c b/src/H5HLdbg.c index bf1251c..0401f92 100644 --- a/src/H5HLdbg.c +++ b/src/H5HLdbg.c @@ -84,17 +84,14 @@ H5HL_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent, int "Address of heap data:", h->addr); HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth, - "Data bytes allocated on disk:", - h->disk_alloc); - HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth, - "Data bytes allocated in core:", - h->mem_alloc); + "Data bytes allocated for heap:", + h->heap_alloc); /* * Traverse the free list and check that all free blocks fall within * the heap and that no two free blocks point to the same region of * the heap. */ - if (NULL==(marker = H5MM_calloc(h->mem_alloc))) + if (NULL==(marker = H5MM_calloc(h->heap_alloc))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); fprintf(stream, "%*sFree Blocks (offset, size):\n", indent, ""); @@ -106,7 +103,7 @@ H5HL_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent, int HDfprintf(stream, "%*s%-*s %8Zu, %8Zu\n", indent+3, "", MAX(0,fwidth-9), temp_str, freelist->offset, freelist->size); - if (freelist->offset + freelist->size > h->mem_alloc) { + if (freelist->offset + freelist->size > h->heap_alloc) { fprintf(stream, "***THAT FREE BLOCK IS OUT OF BOUNDS!\n"); } else { for (i=overlap=0; i<(int)(freelist->size); i++) { @@ -123,20 +120,20 @@ H5HL_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent, int } } - if (h->mem_alloc) { + if (h->heap_alloc) { fprintf(stream, "%*s%-*s %.2f%%\n", indent, "", fwidth, "Percent of heap used:", - (100.0 * (double)(h->mem_alloc - amount_free) / (double)h->mem_alloc)); + (100.0 * (double)(h->heap_alloc - amount_free) / (double)h->heap_alloc)); } /* * Print the data in a VMS-style octal dump. */ fprintf(stream, "%*sData follows (`__' indicates free region)...\n", indent, ""); - for (i=0; i<(int)(h->disk_alloc); i+=16) { + for (i=0; i<(int)(h->heap_alloc); i+=16) { fprintf(stream, "%*s %8d: ", indent, "", i); for (j = 0; j < 16; j++) { - if (i+j<(int)(h->disk_alloc)) { + if (i+j<(int)(h->heap_alloc)) { if (marker[i + j]) { fprintf(stream, "__ "); } else { @@ -151,7 +148,7 @@ H5HL_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent, int } for (j = 0; j < 16; j++) { - if (i+j < (int)(h->disk_alloc)) { + if (i+j < (int)(h->heap_alloc)) { if (marker[i + j]) { HDfputc(' ', stream); } else { diff --git a/src/H5HLpkg.h b/src/H5HLpkg.h index 8b099cc..3598403 100644 --- a/src/H5HLpkg.h +++ b/src/H5HLpkg.h @@ -65,8 +65,7 @@ struct H5HL_t { H5AC_info_t cache_info; /* Information for H5AC cache functions, _must_ be */ /* first field in structure */ haddr_t addr; /*address of data */ - size_t disk_alloc; /*data bytes allocated on disk */ - size_t mem_alloc; /*data bytes allocated in mem */ + size_t heap_alloc; /*size of heap on disk and in mem */ uint8_t *chunk; /*the chunk, including header */ H5HL_free_t *freelist; /*the free list */ }; diff --git a/src/H5HLprivate.h b/src/H5HLprivate.h index 001c3a1..445c1a7 100644 --- a/src/H5HLprivate.h +++ b/src/H5HLprivate.h @@ -70,6 +70,7 @@ H5_DLL size_t H5HL_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t size, const void *buf); H5_DLL herr_t H5HL_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t offset, size_t size); H5_DLL herr_t H5HL_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr); +H5_DLL herr_t H5HL_get_size(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t *size); /* Debugging functions */ H5_DLL herr_t H5HL_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent, @@ -45,6 +45,7 @@ #include "H5FLprivate.h" /* Free Lists */ #include "H5Ipkg.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ +#include "H5Oprivate.h" /* Object headers */ /* Define this to compile in support for dumping ID information */ /* #define H5I_DEBUG_OUTPUT */ @@ -2003,28 +2004,61 @@ H5I_find_id(hid_t id) ssize_t H5Iget_name(hid_t id, char *name/*out*/, size_t size) { - H5G_entry_t *ent; /*symbol table entry */ - size_t len=0; + H5G_loc_t loc; /* Object location */ + size_t len = 0; ssize_t ret_value; - FUNC_ENTER_API (H5Iget_name, FAIL); + FUNC_ENTER_API(H5Iget_name, FAIL) H5TRACE3("Zs","ixz",id,name,size); - /* get symbol table entry */ - if(NULL!=(ent = H5G_loc(id))) { - if (ent->user_path_r != NULL && ent->user_path_hidden==0) { - len = H5RS_len(ent->user_path_r); + /* get object location */ + if(H5G_loc(id, &loc) >= 0) { + if(loc.path->user_path_r != NULL && loc.path->user_path_hidden == 0) { + len = H5RS_len(loc.path->user_path_r); if(name) { - HDstrncpy(name, H5RS_get_str(ent->user_path_r), MIN(len+1,size)); + HDstrncpy(name, H5RS_get_str(loc.path->user_path_r), MIN(len + 1, size)); if(len >= size) - name[size-1]='\0'; + name[size-1] = '\0'; } /* end if */ } /* end if */ } /* end if */ /* Set return value */ - ret_value=(ssize_t)len; + ret_value = (ssize_t)len; + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Iget_name() */ + + +/*------------------------------------------------------------------------- + * Function: H5Iget_file_id + * + * Purpose: The public version of H5I_get_file_id(), obtains the file + * ID given an object ID. User has to close this ID. + * + * Return: Success: file ID + * + * Failure: a negative value + * + * Programmer: Raymond Lu + * Oct 27, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +hid_t +H5Iget_file_id(hid_t obj_id) +{ + hid_t ret_value; + + FUNC_ENTER_API(H5Iget_file_id, FAIL); + H5TRACE1("i","i",obj_id); + + if((ret_value = H5I_get_file_id(obj_id))<0) + HGOTO_ERROR (H5E_ATOM, H5E_CANTGET, FAIL, "can't retrieve file ID"); done: FUNC_LEAVE_API(ret_value); @@ -2032,6 +2066,57 @@ done: /*------------------------------------------------------------------------- + * Function: H5I_get_file_id + * + * Purpose: The private version of H5Iget_file_id(), obtains the file + * ID given an object ID. + * + * Return: Success: file ID + * + * Failure: a negative value + * + * Programmer: Raymond Lu + * Oct 27, 2003 + * + *------------------------------------------------------------------------- + */ +static hid_t +H5I_get_file_id(hid_t obj_id) +{ + H5G_loc_t loc; /* Location of object */ + H5I_type_t type; /* ID type */ + hid_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5I_get_file_id) + + /* Get object type */ + type = H5I_TYPE(obj_id); + if(type == H5I_FILE) { + ret_value = obj_id; + + /* Increment reference count on atom. */ + if(H5I_inc_ref(ret_value) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTSET, FAIL, "incrementing file ID failed") + } + else if(type == H5I_DATATYPE) { + if(H5G_loc(obj_id, &loc) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "not a named datatype") + ret_value = H5F_get_id(loc.oloc->file); + } + else if(type == H5I_GROUP || type == H5I_DATASET || type == H5I_ATTR) { + if(H5G_loc(obj_id, &loc) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't get symbol table info") + ret_value = H5F_get_id(loc.oloc->file); + } + else + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid object ID") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5I_get_file_id() */ + + +/*------------------------------------------------------------------------- * Function: H5I_debug * * Purpose: Dump the contents of a type to stderr for debugging. @@ -2056,7 +2141,7 @@ H5I_debug(H5I_type_t type) { H5I_id_type_t *type_ptr; H5I_id_info_t *cur; - H5G_entry_t *ent = NULL; + H5G_name_t *path; int is, js; unsigned int iu; herr_t ret_value; /* Return value */ @@ -2092,26 +2177,26 @@ H5I_debug(H5I_type_t type) fprintf(stderr, " count = %u\n", cur->count); fprintf(stderr, " obj = 0x%08lx\n", (unsigned long)(cur->obj_ptr)); - /* Get the symbol table entry, so we get get the name */ + /* Get the group location, so we get get the name */ switch(type) { case H5I_GROUP: - ent = H5G_entof((H5G_t*)cur->obj_ptr); + path = H5G_nameof((H5G_t*)cur->obj_ptr); break; case H5I_DATASET: - ent = H5D_entof((H5D_t*)cur->obj_ptr); + path = H5D_nameof((H5D_t*)cur->obj_ptr); break; case H5I_DATATYPE: - ent = H5T_entof((H5T_t*)cur->obj_ptr); + path = H5T_nameof((H5T_t*)cur->obj_ptr); break; default: continue; /* Other types of IDs are not stored in files */ } /* end switch*/ - if(ent) { - if(ent->name) - fprintf(stderr, " name = %s\n",ent->name); - if(ent->old_name) - fprintf(stderr, " old_name = %s\n",ent->old_name); + if(path) { + if(path->user_path_r) + fprintf(stderr, " user_path = %s\n", H5RS_get_str(path->user_path_r)); + if(ent->canon_path_r) + fprintf(stderr, " canon_path = %s\n", H5RS_get_str(path->canon_path_r)); } /* end if */ } /* end for */ } /* end for */ @@ -2121,89 +2206,3 @@ done: } #endif /* H5I_DEBUG_OUTPUT */ - -/*------------------------------------------------------------------------- - * Function: H5Iget_file_id - * - * Purpose: The public version of H5I_get_file_id(), obtains the file - * ID given an object ID. User has to close this ID. - * - * Return: Success: file ID - * - * Failure: a negative value - * - * Programmer: Raymond Lu - * Oct 27, 2003 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -hid_t -H5Iget_file_id(hid_t obj_id) -{ - hid_t ret_value; - - FUNC_ENTER_API(H5Iget_file_id, FAIL); - H5TRACE1("i","i",obj_id); - - if((ret_value = H5I_get_file_id(obj_id))<0) - HGOTO_ERROR (H5E_ATOM, H5E_CANTGET, FAIL, "can't retrieve file ID"); - -done: - FUNC_LEAVE_API(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5I_get_file_id - * - * Purpose: The private version of H5Iget_file_id(), obtains the file - * ID given an object ID. - * - * Return: Success: file ID - * - * Failure: a negative value - * - * Programmer: Raymond Lu - * Oct 27, 2003 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static hid_t -H5I_get_file_id(hid_t obj_id) -{ - H5G_entry_t *ent; - H5I_type_t type; - hid_t ret_value; - - FUNC_ENTER_NOAPI_NOINIT(H5I_get_file_id); - - /* Get object type */ - type = H5I_TYPE(obj_id); - if(type == H5I_FILE) { - ret_value = obj_id; - - /* Increment reference count on atom. */ - if (H5I_inc_ref(ret_value)<0) - HGOTO_ERROR (H5E_ATOM, H5E_CANTSET, FAIL, "incrementing file ID failed"); - } - else if(type == H5I_DATATYPE) { - if((ent = H5G_loc(obj_id))==NULL) - HGOTO_ERROR (H5E_ATOM, H5E_CANTGET, FAIL, "not a named datatype"); - ret_value = H5F_get_id(ent->file); - } - else if(type == H5I_GROUP || type == H5I_DATASET || type == H5I_ATTR) { - if((ent = H5G_loc(obj_id))==NULL) - HGOTO_ERROR (H5E_ATOM, H5E_CANTGET, FAIL, "can't get symbol table info"); - ret_value = H5F_get_id(ent->file); - } - else - HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid object ID"); - -done: - FUNC_LEAVE_NOAPI(ret_value); -} - @@ -20,8 +20,6 @@ * * Purpose: Object header virtual functions. * - * Modifications: - * *------------------------------------------------------------------------- */ @@ -33,20 +31,38 @@ #include "H5private.h" /* Generic Functions */ -#include "H5ACprivate.h" /* Metadata cache */ +#include "H5Dprivate.h" /* Datasets */ #include "H5Eprivate.h" /* Error handling */ #include "H5Fpkg.h" /* File access */ #include "H5FLprivate.h" /* Free lists */ -#include "H5Iprivate.h" /* IDs */ #include "H5MFprivate.h" /* File memory management */ #include "H5MMprivate.h" /* Memory management */ #include "H5Opkg.h" /* Object headers */ -#include "H5Pprivate.h" /* Property lists */ #ifdef H5_HAVE_GETTIMEOFDAY #include <sys/time.h> #endif /* H5_HAVE_GETTIMEOFDAY */ +/* Local macros */ + +/* Load native information for a message, if it's not already present */ +/* (Only works for messages with decode callback) */ +#define LOAD_NATIVE(F, DXPL, MSG) \ + if(NULL == (MSG)->native) { \ + const H5O_class_t *decode_type; \ + \ + /* Check for shared message */ \ + if ((MSG)->flags & H5O_FLAG_SHARED) \ + decode_type = H5O_SHARED; \ + else \ + decode_type = (MSG)->type; \ + \ + /* Decode the message */ \ + HDassert(decode_type->decode); \ + if(NULL == ((MSG)->native = (decode_type->decode)((F), (DXPL), (MSG)->raw))) \ + HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "unable to decode message") \ + } /* end if */ + /* Private typedefs */ /* User data for iteration while removing a message */ @@ -64,39 +80,114 @@ typedef struct { typedef herr_t (*H5O_operator_int_t)(H5O_mesg_t *mesg/*in,out*/, unsigned idx, unsigned * oh_flags_ptr, void *operator_data/*in,out*/); +/* + * This table contains a list of object types, descriptions, and the + * functions that determine if some object is a particular type. The table + * is allocated dynamically. + */ +typedef struct H5O_typeinfo_t { + H5G_obj_t type; /*one of the public H5G_* types */ + htri_t (*isa)(H5O_loc_t*, hid_t); /*function to determine type */ + char *desc; /*description of object type */ +} H5O_typeinfo_t; + /* Node in skip list to map addresses from one file to another during object header copy */ typedef struct H5O_addr_map_t { haddr_t src_addr; /* Address of object in source file */ haddr_t dst_addr; /* Address of object in destination file */ + hbool_t is_locked; /* Indicate that the destination object is locked currently */ + hsize_t inc_ref_count; /* Number of deferred increments to reference count */ } H5O_addr_map_t; +/* Package variables */ + +/* ID to type mapping */ +const H5O_class_t *const message_type_g[] = { + H5O_NULL, /*0x0000 Null */ + H5O_SDSPACE, /*0x0001 Simple Dimensionality */ + H5O_LINFO, /*0x0002 Link information */ + H5O_DTYPE, /*0x0003 Data Type */ + H5O_FILL, /*0x0004 Old data storage -- fill value */ + H5O_FILL_NEW, /*0x0005 New Data storage -- fill value */ + H5O_LINK, /*0x0006 Link */ + H5O_EFL, /*0x0007 Data storage -- external data files */ + H5O_LAYOUT, /*0x0008 Data Layout */ +#ifdef H5O_ENABLE_BOGUS + H5O_BOGUS, /*0x0009 "Bogus" */ +#else /* H5O_ENABLE_BOGUS */ + NULL, /*0x0009 "Bogus" */ +#endif /* H5O_ENABLE_BOGUS */ + H5O_GINFO, /*0x000A Group Information */ + H5O_PLINE, /*0x000B Data storage -- filter pipeline */ + H5O_ATTR, /*0x000C Attribute list */ + H5O_NAME, /*0x000D Object name */ + H5O_MTIME, /*0x000E Object modification date and time */ + H5O_SHARED, /*0x000F Shared header message */ + H5O_CONT, /*0x0010 Object header continuation */ + H5O_STAB, /*0x0011 Symbol table */ + H5O_MTIME_NEW, /*0x0012 New Object modification date and time */ +}; + +/* Declare a free list to manage the H5O_t struct */ +H5FL_DEFINE(H5O_t); + +/* Declare a free list to manage the H5O_mesg_t sequence information */ +H5FL_SEQ_DEFINE(H5O_mesg_t); + +/* Declare a free list to manage the H5O_chunk_t sequence information */ +H5FL_SEQ_DEFINE(H5O_chunk_t); + +/* Declare a free list to manage the chunk image information */ +H5FL_BLK_DEFINE(chunk_image); + +/* Library private variables */ + +/* Local variables */ +static H5O_typeinfo_t *H5O_type_g = NULL; /*object typing info */ +static size_t H5O_ntypes_g = 0; /*entries in type table */ +static size_t H5O_atypes_g = 0; /*entries allocated */ + +/* Declare external the free list for time_t's */ +H5FL_EXTERN(time_t); + +/* Declare extern the free list for H5O_cont_t's */ +H5FL_EXTERN(H5O_cont_t); + +/* Declare a free list to manage the H5O_addr_map_t struct */ +H5FL_DEFINE_STATIC(H5O_addr_map_t); + /* PRIVATE PROTOTYPES */ -static herr_t H5O_init(H5F_t *f, hid_t dxpl_id, size_t size_hint, - H5G_entry_t *ent/*out*/, haddr_t header); +static herr_t H5O_register_type(H5G_obj_t type, htri_t(*isa)(H5O_loc_t *, hid_t), + const char *_desc); +static herr_t H5O_new(H5F_t *f, hid_t dxpl_id, size_t size_hint, + H5O_loc_t *loc/*out*/, haddr_t header); static herr_t H5O_reset_real(const H5O_class_t *type, void *native); -static herr_t H5O_free_mesg(H5O_mesg_t *mesg); static void * H5O_copy_real(const H5O_class_t *type, const void *mesg, void *dst); -static int H5O_count_real (H5G_entry_t *ent, const H5O_class_t *type, +static int H5O_count_real(H5O_loc_t *loc, const H5O_class_t *type, hid_t dxpl_id); -static htri_t H5O_exists_real(H5G_entry_t *ent, const H5O_class_t *type, - int sequence, hid_t dxpl_id); +static htri_t H5O_exists_real(H5O_loc_t *loc, const H5O_class_t *type, + int sequence, hid_t dxpl_id); #ifdef NOT_YET static herr_t H5O_share(H5F_t *f, hid_t dxpl_id, const H5O_class_t *type, const void *mesg, H5HG_t *hobj/*out*/); #endif /* NOT_YET */ static unsigned H5O_find_in_ohdr(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_class_t **type_p, int sequence); -static int H5O_modify_real(H5G_entry_t *ent, const H5O_class_t *type, +static int H5O_modify_real(H5O_loc_t *loc, const H5O_class_t *type, int overwrite, unsigned flags, unsigned update_flags, const void *mesg, hid_t dxpl_id); static int H5O_append_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_class_t *type, unsigned flags, const void *mesg, unsigned * oh_flags_ptr); -static herr_t H5O_remove_real(H5G_entry_t *ent, const H5O_class_t *type, +static herr_t H5O_remove_real(const H5O_loc_t *loc, const H5O_class_t *type, int sequence, H5O_operator_t op, void *op_data, hbool_t adj_link, hid_t dxpl_id); static unsigned H5O_alloc(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_class_t *type, size_t size, hbool_t * oh_dirtied_ptr); +static htri_t H5O_move_msgs_forward(H5F_t *f, H5O_t *oh, hid_t dxpl_id); +static htri_t H5O_merge_null(H5F_t *f, H5O_t *oh); +static htri_t H5O_remove_empty_chunks(H5F_t *f, H5O_t *oh, hid_t dxpl_id); +static herr_t H5O_condense_header(H5F_t *f, H5O_t *oh, hid_t dxpl_id); static htri_t H5O_alloc_extend_chunk(H5F_t *f, H5O_t *oh, unsigned chunkno, size_t size, unsigned * msg_idx); static unsigned H5O_alloc_new_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh, @@ -111,121 +202,185 @@ static unsigned H5O_new_mesg(H5F_t *f, H5O_t *oh, unsigned *flags, static herr_t H5O_write_mesg(H5O_t *oh, unsigned idx, const H5O_class_t *type, const void *mesg, unsigned flags, unsigned update_flags, unsigned * oh_flags_ptr); -static herr_t H5O_iterate_real(const H5G_entry_t *ent, const H5O_class_t *type, +static herr_t H5O_iterate_real(const H5O_loc_t *loc, const H5O_class_t *type, H5AC_protect_t prot, hbool_t internal, void *op, void *op_data, hid_t dxpl_id); static void * H5O_copy_mesg_file(const H5O_class_t *type, H5F_t *file_src, void *mesg_src, H5F_t *file_dst, hid_t dxpl_id, H5SL_t *map_list, void *udata); -static herr_t H5O_post_copy_mesg_file(const H5O_class_t *type, H5F_t *file_src, - const void *mesg_src, H5G_entry_t *loc_dst, - hid_t dxpl_id, H5SL_t *map_list); -static herr_t H5O_copy_header_real(const H5G_entry_t *ent_src, - H5G_entry_t *ent_dst /*out */, hid_t dxpl_id, H5SL_t *map_list); +static herr_t H5O_copy_header_real(const H5O_loc_t *oloc_src, + H5O_loc_t *oloc_dst /*out */, hid_t dxpl_id, H5SL_t *map_list); static herr_t H5O_copy_free_addrmap_cb(void *item, void *key, void *op_data); -/* Metadata cache callbacks */ -static H5O_t *H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_udata1, - void *_udata2); -static herr_t H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5O_t *oh); -static herr_t H5O_dest(H5F_t *f, H5O_t *oh); -static herr_t H5O_clear(H5F_t *f, H5O_t *oh, hbool_t destroy); -static herr_t H5O_compute_size(const H5F_t *f, const H5O_t *oh, size_t *size_ptr); - -/* H5O inherits cache-like properties from H5AC */ -static const H5AC_class_t H5AC_OHDR[1] = {{ - H5AC_OHDR_ID, - (H5AC_load_func_t)H5O_load, - (H5AC_flush_func_t)H5O_flush, - (H5AC_dest_func_t)H5O_dest, - (H5AC_clear_func_t)H5O_clear, - (H5AC_size_func_t)H5O_compute_size, -}}; + +/*------------------------------------------------------------------------- + * Function: H5O_init + * + * Purpose: Initialize the interface from some other package. + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Wednesday, September 28, 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_init(void) +{ + herr_t ret_value = SUCCEED; /* Return value */ -/* ID to type mapping */ -static const H5O_class_t *const message_type_g[] = { - H5O_NULL, /*0x0000 Null */ - H5O_SDSPACE, /*0x0001 Simple Dimensionality */ - NULL, /*0x0002 Data space (fiber bundle?) */ - H5O_DTYPE, /*0x0003 Data Type */ - H5O_FILL, /*0x0004 Old data storage -- fill value */ - H5O_FILL_NEW, /*0x0005 New Data storage -- fill value */ - NULL, /*0x0006 Data storage -- compact object */ - H5O_EFL, /*0x0007 Data storage -- external data files */ - H5O_LAYOUT, /*0x0008 Data Layout */ -#ifdef H5O_ENABLE_BOGUS - H5O_BOGUS, /*0x0009 "Bogus" */ -#else /* H5O_ENABLE_BOGUS */ - NULL, /*0x0009 "Bogus" */ -#endif /* H5O_ENABLE_BOGUS */ - NULL, /*0x000A Not assigned */ - H5O_PLINE, /*0x000B Data storage -- filter pipeline */ - H5O_ATTR, /*0x000C Attribute list */ - H5O_NAME, /*0x000D Object name */ - H5O_MTIME, /*0x000E Object modification date and time */ - H5O_SHARED, /*0x000F Shared header message */ - H5O_CONT, /*0x0010 Object header continuation */ - H5O_STAB, /*0x0011 Symbol table */ - H5O_MTIME_NEW, /*0x0012 New Object modification date and time */ -}; + FUNC_ENTER_NOAPI(H5O_init, FAIL) + /* FUNC_ENTER() does all the work */ -/* Library private variables */ +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_init() */ -/* - * An array of functions indexed by symbol table entry cache type - * (H5G_type_t) that are called to retrieve constant messages cached in the - * symbol table entry. + +/*------------------------------------------------------------------------- + * Function: H5O_init_interface + * + * Purpose: Initialize the H5O interface. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Tuesday, January 6, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- */ -static void *(*H5O_fast_g[H5G_NCACHED]) (const H5G_cache_t *, - const H5O_class_t *, - void *); +static herr_t +H5O_init_interface(void) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_init_interface) -/* Declare a free list to manage the H5O_t struct */ -H5FL_DEFINE_STATIC(H5O_t); + /* + * Initialize the type info table. Begin with the most general types and + * end with the most specific. For instance, any object that has a data + * type message is a datatype but only some of them are datasets. + */ + H5O_register_type(H5G_TYPE, H5T_isa, "datatype"); + H5O_register_type(H5G_GROUP, H5G_isa, "group"); + H5O_register_type(H5G_DATASET, H5D_isa, "dataset"); -/* Declare a free list to manage the H5O_mesg_t sequence information */ -H5FL_SEQ_DEFINE_STATIC(H5O_mesg_t); + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5O_init_interface() */ -/* Declare a free list to manage the H5O_chunk_t sequence information */ -H5FL_SEQ_DEFINE_STATIC(H5O_chunk_t); + +/*------------------------------------------------------------------------- + * Function: H5O_term_interface + * + * Purpose: Terminates the H5O interface + * + * Return: Success: Positive if anything is done that might + * affect other interfaces; zero otherwise. + * + * Failure: Negative. + * + * Programmer: Quincey Koziol + * Monday, September 19, 2005 + * + *------------------------------------------------------------------------- + */ +int +H5O_term_interface(void) +{ + int n = 0; -/* Declare a free list to manage the chunk image information */ -H5FL_BLK_DEFINE_STATIC(chunk_image); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_term_interface) -/* Declare external the free list for time_t's */ -H5FL_EXTERN(time_t); + if(H5_interface_initialize_g) { + size_t u; -/* Declare extern the free list for H5O_cont_t's */ -H5FL_EXTERN(H5O_cont_t); + /* Empty the object type table */ + for(u = 0; u < H5O_ntypes_g; u++) + H5MM_xfree(H5O_type_g[u].desc); + H5O_ntypes_g = H5O_atypes_g = 0; + H5O_type_g = H5MM_xfree(H5O_type_g); -/* Declare a free list to manage the H5O_addr_map_t struct */ -H5FL_DEFINE_STATIC(H5O_addr_map_t); + /* Mark closed */ + H5_interface_initialize_g = 0; + n = 1; /*H5O*/ + } /* end if */ + + FUNC_LEAVE_NOAPI(n) +} /* H5O_term_interface() */ /*------------------------------------------------------------------------- - * Function: H5O_init_interface + * Function: H5O_register_type * - * Purpose: Initialize the H5O interface. + * Purpose: Register a new object type so H5O_get_type() can detect it. + * One should always register a general type before a more + * specific type. For instance, any object that has a datatype + * message is a datatype, but only some of those objects are + * datasets. * - * Return: Non-negative on success/Negative on failure + * Return: Success: Non-negative * - * Programmer: Robb Matzke - * Tuesday, January 6, 1998 + * Failure: Negative * - * Modifications: + * Programmer: Quincey Koziol + * Monday, September 19, 2005 * *------------------------------------------------------------------------- */ static herr_t -H5O_init_interface(void) +H5O_register_type(H5G_obj_t type, htri_t(*isa)(H5O_loc_t *, hid_t), const char *_desc) { - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_init_interface); + char *desc = NULL; + size_t i; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5O_register_type) + + HDassert(type >= 0); + HDassert(isa); + HDassert(_desc); + + /* Copy the description */ + if(NULL == (desc = H5MM_strdup(_desc))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for object type description") /* - * Initialize functions that decode messages from symbol table entries. + * If the type is already registered then just update its entry without + * moving it to the end */ - H5O_fast_g[H5G_CACHED_STAB] = H5O_stab_fast; + for(i = 0; i < H5O_ntypes_g; i++) { + if (H5O_type_g[i].type == type) { + H5O_type_g[i].isa = isa; + H5MM_xfree(H5O_type_g[i].desc); + H5O_type_g[i].desc = desc; + HGOTO_DONE(SUCCEED); + } /* end if */ + } /* end for */ - FUNC_LEAVE_NOAPI(SUCCEED); -} + /* Increase table size */ + if(H5O_ntypes_g >= H5O_atypes_g) { + size_t n = MAX(32, 2 * H5O_atypes_g); + H5O_typeinfo_t *x = H5MM_realloc(H5O_type_g, n * sizeof(H5O_typeinfo_t)); + + if (!x) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for objec type table") + H5O_atypes_g = n; + H5O_type_g = x; + } /* end if */ + + /* Add a new entry */ + H5O_type_g[H5O_ntypes_g].type = type; + H5O_type_g[H5O_ntypes_g].isa = isa; + H5O_type_g[H5O_ntypes_g].desc = desc; /*already copied*/ + H5O_ntypes_g++; + +done: + if(ret_value < 0) + H5MM_xfree(desc); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_register_type() */ /*------------------------------------------------------------------------- @@ -246,47 +401,38 @@ H5O_init_interface(void) * matzke@llnl.gov * Aug 5 1997 * - * Modifications: - * - * Bill Wendling, 1. November 2002 - * Separated the create function into two different functions. One - * which allocates space and an initialization function which - * does the rest of the work (initializes, caches, and opens the - * object header). - * *------------------------------------------------------------------------- */ herr_t -H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, H5G_entry_t *ent/*out*/) +H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, H5O_loc_t *loc/*out*/) { haddr_t header; herr_t ret_value = SUCCEED; /* return value */ - FUNC_ENTER_NOAPI(H5O_create, FAIL); + FUNC_ENTER_NOAPI(H5O_create, FAIL) /* check args */ - assert(f); - assert(ent); + HDassert(f); + HDassert(loc); - size_hint = H5O_ALIGN (MAX (H5O_MIN_SIZE, size_hint)); + size_hint = H5O_ALIGN(MAX(H5O_MIN_SIZE, size_hint)); /* allocate disk space for header and first chunk */ - if (HADDR_UNDEF == (header = H5MF_alloc(f, H5FD_MEM_OHDR, dxpl_id, - (hsize_t)H5O_SIZEOF_HDR(f) + size_hint))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, - "file allocation failed for object header header"); + if(HADDR_UNDEF == (header = H5MF_alloc(f, H5FD_MEM_OHDR, dxpl_id, + (hsize_t)H5O_SIZEOF_HDR(f) + size_hint))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for object header header") /* initialize the object header */ - if (H5O_init(f, dxpl_id, size_hint, ent, header) != SUCCEED) - HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to initialize object header"); + if(H5O_new(f, dxpl_id, size_hint, loc, header) != SUCCEED) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to initialize object header") done: - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_create() */ /*------------------------------------------------------------------------- - * Function: H5O_init + * Function: H5O_new * * Purpose: Initialize a new object header, sets the link count to 0, * and caches the header. The object header is opened for @@ -301,35 +447,28 @@ done: * Programmer: Bill Wendling * 1, November 2002 * - * Modifications: - * - * JRM -- 6/6/05 - * Removed code modifying the is_dirty field of the - * cache_info. This field is now managed by the cache - * proper. - * *------------------------------------------------------------------------- */ static herr_t -H5O_init(H5F_t *f, hid_t dxpl_id, size_t size_hint, H5G_entry_t *ent/*out*/, haddr_t header) +H5O_new(H5F_t *f, hid_t dxpl_id, size_t size_hint, H5O_loc_t *loc/*out*/, haddr_t header) { H5O_t *oh = NULL; haddr_t tmp_addr; herr_t ret_value = SUCCEED; /* return value */ - FUNC_ENTER_NOAPI_NOINIT(H5O_init); + FUNC_ENTER_NOAPI_NOINIT(H5O_new) /* check args */ - assert(f); - assert(ent); + HDassert(f); + HDassert(loc); size_hint = H5O_ALIGN(MAX(H5O_MIN_SIZE, size_hint)); - ent->file = f; - ent->header = header; + loc->file = f; + loc->addr = header; /* allocate the object header and fill in header fields */ - if (NULL == (oh = H5FL_MALLOC(H5O_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + if(NULL == (oh = H5FL_MALLOC(H5O_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") oh->version = H5O_VERSION; oh->nlink = 0; @@ -338,23 +477,23 @@ H5O_init(H5F_t *f, hid_t dxpl_id, size_t size_hint, H5G_entry_t *ent/*out*/, had oh->nchunks = 1; oh->alloc_nchunks = H5O_NCHUNKS; - if (NULL == (oh->chunk = H5FL_SEQ_MALLOC(H5O_chunk_t, (size_t)oh->alloc_nchunks))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + if(NULL == (oh->chunk = H5FL_SEQ_MALLOC(H5O_chunk_t, (size_t)oh->alloc_nchunks))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") - tmp_addr = ent->header + (hsize_t)H5O_SIZEOF_HDR(f); + tmp_addr = loc->addr + (hsize_t)H5O_SIZEOF_HDR(f); oh->chunk[0].dirty = TRUE; oh->chunk[0].addr = tmp_addr; oh->chunk[0].size = size_hint; - if (NULL == (oh->chunk[0].image = H5FL_BLK_CALLOC(chunk_image, size_hint))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + if(NULL == (oh->chunk[0].image = H5FL_BLK_CALLOC(chunk_image, size_hint))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") /* create the message list and initialize the first message */ oh->nmesgs = 1; oh->alloc_nmesgs = H5O_NMESGS; - if (NULL == (oh->mesg = H5FL_SEQ_CALLOC(H5O_mesg_t, (size_t)oh->alloc_nmesgs))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + if(NULL == (oh->mesg = H5FL_SEQ_CALLOC(H5O_mesg_t, (size_t)oh->alloc_nmesgs))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") oh->mesg[0].type = H5O_NULL; oh->mesg[0].dirty = TRUE; @@ -364,21 +503,21 @@ H5O_init(H5F_t *f, hid_t dxpl_id, size_t size_hint, H5G_entry_t *ent/*out*/, had oh->mesg[0].chunkno = 0; /* cache it */ - if (H5AC_set(f, dxpl_id, H5AC_OHDR, ent->header, oh, H5AC__NO_FLAGS_SET) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to cache object header"); + if(H5AC_set(f, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to cache object header") /* open it */ - if (H5O_open(ent) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open object header"); + if(H5O_open(loc) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open object header") done: - if(ret_value<0 && oh) { - if(H5O_dest(f,oh)<0) - HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy object header data"); + if(ret_value < 0 && oh) { + if(H5O_dest(f, oh) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy object header data") } /* end if */ - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_new() */ /*------------------------------------------------------------------------- @@ -392,32 +531,30 @@ done: * Programmer: Robb Matzke * Monday, January 5, 1998 * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t -H5O_open(const H5G_entry_t *obj_ent) +H5O_open(const H5O_loc_t *loc) { - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5O_open, FAIL); + FUNC_ENTER_NOAPI(H5O_open, FAIL) /* Check args */ - assert(obj_ent); - assert(obj_ent->file); + HDassert(loc); + HDassert(loc->file); #ifdef H5O_DEBUG if (H5DEBUG(O)) - HDfprintf(H5DEBUG(O), "> %a\n", obj_ent->header); + HDfprintf(H5DEBUG(O), "> %a\n", loc->addr); #endif /* Increment open-lock counters */ - obj_ent->file->nopen_objs++; + loc->file->nopen_objs++; done: - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_open() */ /*------------------------------------------------------------------------- @@ -430,565 +567,51 @@ done: * Programmer: Robb Matzke * Monday, January 5, 1998 * - * Modifications: - * - * Pedro Vicente, <pvn@ncsa.uiuc.edu> 22 Aug 2002 - * Added `id to name' support. - * *------------------------------------------------------------------------- */ herr_t -H5O_close(H5G_entry_t *obj_ent) +H5O_close(H5O_loc_t *loc) { - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5O_close, FAIL); + FUNC_ENTER_NOAPI(H5O_close, FAIL) /* Check args */ - assert(obj_ent); - assert(obj_ent->file); - assert(obj_ent->file->nopen_objs > 0); + HDassert(loc); + HDassert(loc->file); + HDassert(loc->file->nopen_objs > 0); /* Decrement open-lock counters */ - --obj_ent->file->nopen_objs; + --loc->file->nopen_objs; #ifdef H5O_DEBUG if (H5DEBUG(O)) { - if (obj_ent->file->file_id < 0 && 1==obj_ent->file->shared->nrefs) { + if(loc->file->file_id < 0 && 1 == loc->file->shared->nrefs) { HDfprintf(H5DEBUG(O), "< %a auto %lu remaining\n", - obj_ent->header, - (unsigned long)(obj_ent->file->nopen_objs)); + loc->addr, + (unsigned long)(loc->file->nopen_objs)); } else { - HDfprintf(H5DEBUG(O), "< %a\n", obj_ent->header); + HDfprintf(H5DEBUG(O), "< %a\n", loc->addr); } - } + } /* end if */ #endif /* * If the file open object count has reached the number of open mount points * (each of which has a group open in the file) attempt to close the file. */ - if(obj_ent->file->nopen_objs == obj_ent->file->mtab.nmounts) { + if(loc->file->nopen_objs == loc->file->mtab.nmounts) { /* Attempt to close down the file hierarchy */ - if(H5F_try_close(obj_ent->file) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "problem attempting file close") + if(H5F_try_close(loc->file) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCLOSEFILE, FAIL, "problem attempting file close") } /* end if */ - /* Free the ID to name buffers */ - H5G_free_ent_name(obj_ent); - done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_close() */ /*------------------------------------------------------------------------- - * Function: H5O_load - * - * Purpose: Loads an object header from disk. - * - * Return: Success: Pointer to the new object header. - * - * Failure: NULL - * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Aug 5 1997 - * - * Modifications: - * - * Robb Matzke, 1997-08-30 - * Plugged memory leaks that occur during error handling. - * - * Robb Matzke, 1998-01-07 - * Able to distinguish between constant and variable messages. - * - * Robb Matzke, 1999-07-28 - * The ADDR argument is passed by value. - * - * Quincey Koziol, 2002-7-180 - * Added dxpl parameter to allow more control over I/O from metadata - * cache. - *------------------------------------------------------------------------- - */ -static H5O_t * -H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1, - void UNUSED * _udata2) -{ - H5O_t *oh = NULL; - H5O_t *ret_value; - uint8_t buf[16], *p; - size_t mesg_size; - size_t hdr_size; - unsigned id; - int mesgno; - unsigned curmesg = 0, nmesgs; - unsigned chunkno; - haddr_t chunk_addr; - size_t chunk_size; - uint8_t flags; - - FUNC_ENTER_NOAPI(H5O_load, NULL); - - /* check args */ - assert(f); - assert(H5F_addr_defined(addr)); - assert(!_udata1); - assert(!_udata2); - - /* allocate ohdr and init chunk list */ - if (NULL==(oh = H5FL_CALLOC(H5O_t))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - - /* read fixed-lenth part of object header */ - hdr_size = H5O_SIZEOF_HDR(f); - assert(hdr_size<=sizeof(buf)); - if (H5F_block_read(f, H5FD_MEM_OHDR, addr, hdr_size, dxpl_id, buf) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header"); - p = buf; - - /* decode version */ - oh->version = *p++; - if (H5O_VERSION != oh->version) - HGOTO_ERROR(H5E_OHDR, H5E_VERSION, NULL, "bad object header version number"); - - /* reserved */ - p++; - - /* decode number of messages */ - UINT16DECODE(p, nmesgs); - - /* decode link count */ - UINT32DECODE(p, oh->nlink); - - /* decode first chunk info */ - chunk_addr = addr + (hsize_t)hdr_size; - UINT32DECODE(p, chunk_size); - - /* build the message array */ - oh->alloc_nmesgs = MAX(H5O_NMESGS, nmesgs); - if (NULL==(oh->mesg=H5FL_SEQ_CALLOC(H5O_mesg_t,(size_t)oh->alloc_nmesgs))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - - /* read each chunk from disk */ - while (H5F_addr_defined(chunk_addr)) { - /* increase chunk array size */ - if (oh->nchunks >= oh->alloc_nchunks) { - unsigned na = oh->alloc_nchunks + H5O_NCHUNKS; - H5O_chunk_t *x = H5FL_SEQ_REALLOC (H5O_chunk_t, oh->chunk, (size_t)na); - - if (!x) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - oh->alloc_nchunks = na; - oh->chunk = x; - } - - /* read the chunk raw data */ - chunkno = oh->nchunks++; - oh->chunk[chunkno].dirty = FALSE; - oh->chunk[chunkno].addr = chunk_addr; - oh->chunk[chunkno].size = chunk_size; - if (NULL==(oh->chunk[chunkno].image = H5FL_BLK_MALLOC(chunk_image,chunk_size))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - if (H5F_block_read(f, H5FD_MEM_OHDR, chunk_addr, chunk_size, dxpl_id, - oh->chunk[chunkno].image) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header data"); - - /* load messages from this chunk */ - for (p = oh->chunk[chunkno].image; p < oh->chunk[chunkno].image + chunk_size; p += mesg_size) { - UINT16DECODE(p, id); - UINT16DECODE(p, mesg_size); - assert (mesg_size==H5O_ALIGN (mesg_size)); - flags = *p++; - p += 3; /*reserved*/ - - /* Try to detect invalidly formatted object header messages */ - if (p + mesg_size > oh->chunk[chunkno].image + chunk_size) - HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "corrupt object header"); - - /* Skip header messages we don't know about */ - /* (Usually from future versions of the library */ - if (id >= NELMTS(message_type_g) || NULL == message_type_g[id]) - continue; - - if (H5O_NULL_ID == id && oh->nmesgs > 0 && - H5O_NULL_ID == oh->mesg[oh->nmesgs - 1].type->id && - oh->mesg[oh->nmesgs - 1].chunkno == chunkno) { - /* combine adjacent null messages */ - mesgno = oh->nmesgs - 1; - oh->mesg[mesgno].raw_size += H5O_SIZEOF_MSGHDR(f) + mesg_size; - } else { - /* new message */ - if (oh->nmesgs >= nmesgs) - HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "corrupt object header"); - mesgno = oh->nmesgs++; - oh->mesg[mesgno].type = message_type_g[id]; - oh->mesg[mesgno].dirty = FALSE; - oh->mesg[mesgno].flags = flags; - oh->mesg[mesgno].native = NULL; - oh->mesg[mesgno].raw = p; - oh->mesg[mesgno].raw_size = mesg_size; - oh->mesg[mesgno].chunkno = chunkno; - } - } - - assert(p == oh->chunk[chunkno].image + chunk_size); - - /* decode next object header continuation message */ - for (chunk_addr = HADDR_UNDEF; !H5F_addr_defined(chunk_addr) && curmesg < oh->nmesgs; ++curmesg) { - if (H5O_CONT_ID == oh->mesg[curmesg].type->id) { - H5O_cont_t *cont; - - cont = (H5O_CONT->decode) (f, dxpl_id, oh->mesg[curmesg].raw, NULL); - oh->mesg[curmesg].native = cont; - chunk_addr = cont->addr; - chunk_size = cont->size; - cont->chunkno = oh->nchunks; /*the next chunk to allocate */ - } - } - } - - /* Set return value */ - ret_value = oh; - -done: - if (!ret_value && oh) { - if(H5O_dest(f,oh)<0) - HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, NULL, "unable to destroy object header data"); - } - - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5O_flush - * - * Purpose: Flushes (and destroys) an object header. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Aug 5 1997 - * - * Modifications: - * - * Robb Matzke, 1998-01-07 - * Handles constant vs non-constant messages. - * - * rky, 1998-08-28 - * Only p0 writes metadata to disk. - * - * Robb Matzke, 1999-07-28 - * The ADDR argument is passed by value. - * - * Quincey Koziol, 2002-7-180 - * Added dxpl parameter to allow more control over I/O from metadata - * cache. - *------------------------------------------------------------------------- - */ -static herr_t -H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5O_t *oh) -{ - uint8_t buf[16], *p; - int id; - unsigned u; - H5O_mesg_t *curr_msg; /* Pointer to current message being operated on */ - herr_t (*encode)(H5F_t*, uint8_t*, const void*) = NULL; - unsigned combine=0; /* Whether to combine the object header prefix & the first chunk */ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5O_flush, FAIL); - - /* check args */ - assert(f); - assert(H5F_addr_defined(addr)); - assert(oh); - - /* flush */ - if (oh->cache_info.is_dirty) { - p = buf; - - /* encode version */ - *p++ = oh->version; - - /* reserved */ - *p++ = 0; - - /* encode number of messages */ - UINT16ENCODE(p, oh->nmesgs); - - /* encode link count */ - UINT32ENCODE(p, oh->nlink); - - /* encode body size */ - UINT32ENCODE(p, oh->chunk[0].size); - - /* zero to alignment */ - HDmemset (p, 0, (size_t)(H5O_SIZEOF_HDR(f)-12)); - - /* write the object header prefix */ - - /* Check if we can combine the object header prefix & the first chunk into one I/O operation */ - if(oh->chunk[0].dirty && (addr+H5O_SIZEOF_HDR(f))==oh->chunk[0].addr) { - combine=1; - } /* end if */ - else { - if (H5F_block_write(f, H5FD_MEM_OHDR, addr, (size_t)H5O_SIZEOF_HDR(f), - dxpl_id, buf) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header hdr to disk"); - } /* end else */ - - /* encode messages */ - for (u = 0, curr_msg=&oh->mesg[0]; u < oh->nmesgs; u++,curr_msg++) { - if (curr_msg->dirty) { - p = curr_msg->raw - H5O_SIZEOF_MSGHDR(f); - - id = curr_msg->type->id; - UINT16ENCODE(p, id); - assert (curr_msg->raw_size<H5O_MAX_SIZE); - UINT16ENCODE(p, curr_msg->raw_size); - *p++ = curr_msg->flags; - *p++ = 0; /*reserved*/ - *p++ = 0; /*reserved*/ - *p++ = 0; /*reserved*/ - - if (curr_msg->native) { - assert(curr_msg->type->encode); - - /* allocate file space for chunks that have none yet */ - if (H5O_CONT_ID == curr_msg->type->id && - !H5F_addr_defined(((H5O_cont_t *)(curr_msg->native))->addr)) { - /* We now allocate disk space on insertion, instead - * of on flush from the cache, so this case is now an - * error. -- JRM - */ - HGOTO_ERROR(H5E_OHDR, H5E_SYSTEM, FAIL, - "File space for message not allocated!?!"); - } - - /* - * Encode the message. If the message is shared then we - * encode a Shared Object message instead of the object - * which is being shared. - */ - assert(curr_msg->raw >= - oh->chunk[curr_msg->chunkno].image); - assert (curr_msg->raw_size == - H5O_ALIGN (curr_msg->raw_size)); - assert(curr_msg->raw + curr_msg->raw_size <= - oh->chunk[curr_msg->chunkno].image + - oh->chunk[curr_msg->chunkno].size); - if (curr_msg->flags & H5O_FLAG_SHARED) { - encode = H5O_SHARED->encode; - } else { - encode = curr_msg->type->encode; - } - if ((encode)(f, curr_msg->raw, curr_msg->native)<0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "unable to encode object header message"); - } - curr_msg->dirty = FALSE; - oh->chunk[curr_msg->chunkno].dirty = TRUE; - } - } - - /* write each chunk to disk */ - for (u = 0; u < oh->nchunks; u++) { - if (oh->chunk[u].dirty) { - assert(H5F_addr_defined(oh->chunk[u].addr)); - if(u==0 && combine) { - /* Allocate space for the combined prefix and first chunk */ - if((p=H5FL_BLK_MALLOC(chunk_image,(H5O_SIZEOF_HDR(f)+oh->chunk[u].size)))==NULL) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - - /* Copy in the prefix */ - HDmemcpy(p,buf,(size_t)H5O_SIZEOF_HDR(f)); - - /* Copy in the first chunk */ - HDmemcpy(p+H5O_SIZEOF_HDR(f),oh->chunk[u].image,oh->chunk[u].size); - - /* Write the combined prefix/chunk out */ - if (H5F_block_write(f, H5FD_MEM_OHDR, addr, - (H5O_SIZEOF_HDR(f)+oh->chunk[u].size), - dxpl_id, p) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header data to disk"); - - /* Release the memory for the combined prefix/chunk */ - p = H5FL_BLK_FREE(chunk_image,p); - } /* end if */ - else { - if (H5F_block_write(f, H5FD_MEM_OHDR, oh->chunk[u].addr, - (oh->chunk[u].size), - dxpl_id, oh->chunk[u].image) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header data to disk"); - } /* end else */ - oh->chunk[u].dirty = FALSE; - } /* end if */ - } /* end for */ - oh->cache_info.is_dirty = FALSE; - } - - if (destroy) { - if(H5O_dest(f,oh)<0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy object header data"); - } - -done: - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5O_dest - * - * Purpose: Destroys an object header. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Jan 15 2003 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5O_dest(H5F_t UNUSED *f, H5O_t *oh) -{ - unsigned i; - - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_dest); - - /* check args */ - assert(oh); - - /* Verify that node is clean */ - assert (oh->cache_info.is_dirty==FALSE); - - /* destroy chunks */ - for (i = 0; i < oh->nchunks; i++) { - /* Verify that chunk is clean */ - assert (oh->chunk[i].dirty==0); - - oh->chunk[i].image = H5FL_BLK_FREE(chunk_image,oh->chunk[i].image); - } - if(oh->chunk) - oh->chunk = H5FL_SEQ_FREE(H5O_chunk_t,oh->chunk); - - /* destroy messages */ - for (i = 0; i < oh->nmesgs; i++) { - /* Verify that message is clean */ - assert (oh->mesg[i].dirty==0); - - H5O_free_mesg(&oh->mesg[i]); - } - if(oh->mesg) - oh->mesg = H5FL_SEQ_FREE(H5O_mesg_t,oh->mesg); - - /* destroy object header */ - H5FL_FREE(H5O_t,oh); - - FUNC_LEAVE_NOAPI(SUCCEED); -} /* end H5O_dest() */ - - -/*------------------------------------------------------------------------- - * Function: H5O_clear - * - * Purpose: Mark a object header in memory as non-dirty. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 20 2003 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5O_clear(H5F_t *f, H5O_t *oh, hbool_t destroy) -{ - unsigned u; /* Local index variable */ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI_NOINIT(H5O_clear); - - /* check args */ - assert(oh); - - /* Mark chunks as clean */ - for (u = 0; u < oh->nchunks; u++) - oh->chunk[u].dirty=FALSE; - - /* Mark messages as clean */ - for (u = 0; u < oh->nmesgs; u++) - oh->mesg[u].dirty=FALSE; - - /* Mark whole header as clean */ - oh->cache_info.is_dirty=FALSE; - - if (destroy) - if (H5O_dest(f, oh) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy object header data"); - -done: - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5O_clear() */ - - -/*------------------------------------------------------------------------- - * Function: H5O_compute_size - * - * Purpose: Compute the size in bytes of the specified instance of - * H5O_t on disk, and return it in *len_ptr. On failure, - * the value of *len_ptr is undefined. - * - * The value returned will probably be low unless the object - * has just been flushed, as we simply total up the size of - * the header with the sizes of the chunks. Thus any message - * that has been added since the last flush will not be - * reflected in the total. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: John Mainzer - * 5/13/04 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5O_compute_size(const H5F_t *f, const H5O_t *oh, size_t *size_ptr) -{ - unsigned u; - size_t size; - - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_compute_size); - - /* check args */ - HDassert(f); - HDassert(oh); - HDassert(size_ptr); - - size = H5O_SIZEOF_HDR(f); - - for (u = 0; u < oh->nchunks; u++) - size += oh->chunk[u].size; - - HDassert(size >= H5O_SIZEOF_HDR(f)); - - *size_ptr = size; - - FUNC_LEAVE_NOAPI(SUCCEED); -} /* H5O_compute_size() */ - - -/*------------------------------------------------------------------------- * Function: H5O_reset * * Purpose: Some message data structures have internal fields that @@ -1018,12 +641,12 @@ H5O_reset(unsigned type_id, void *native) FUNC_ENTER_NOAPI(H5O_reset,FAIL); /* check args */ - assert(type_id<NELMTS(message_type_g)); + assert(type_id < NELMTS(message_type_g)); type=message_type_g[type_id]; /* map the type ID to the actual type object */ assert(type); /* Call the "real" reset routine */ - if((ret_value=H5O_reset_real(type, native))<0) + if((ret_value=H5O_reset_real(type, native)) < 0) HGOTO_ERROR(H5E_OHDR, H5E_READERROR, FAIL, "unable to reset object header"); done: @@ -1098,7 +721,7 @@ H5O_free (unsigned type_id, void *mesg) FUNC_ENTER_NOAPI(H5O_free, NULL); /* check args */ - assert(type_id<NELMTS(message_type_g)); + assert(type_id < NELMTS(message_type_g)); type=message_type_g[type_id]; /* map the type ID to the actual type object */ assert(type); @@ -1122,7 +745,7 @@ done: * *------------------------------------------------------------------------- */ -static herr_t +herr_t H5O_free_mesg(H5O_mesg_t *mesg) { FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_free_mesg) @@ -1153,8 +776,6 @@ H5O_free_mesg(H5O_mesg_t *mesg) * Programmer: Robb Matzke * Thursday, May 21, 1998 * - * Modifications: - * *------------------------------------------------------------------------- */ void * @@ -1163,15 +784,15 @@ H5O_free_real(const H5O_class_t *type, void *msg_native) FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_free_real) /* check args */ - assert(type); + HDassert(type); - if (msg_native) { + if(msg_native) { H5O_reset_real(type, msg_native); if (NULL!=(type->free)) (type->free)(msg_native); else H5MM_xfree (msg_native); - } + } /* end if */ FUNC_LEAVE_NOAPI(NULL) } /* end H5O_free_real() */ @@ -1207,7 +828,7 @@ H5O_copy (unsigned type_id, const void *mesg, void *dst) FUNC_ENTER_NOAPI(H5O_copy, NULL); /* check args */ - assert(type_id<NELMTS(message_type_g)); + assert(type_id < NELMTS(message_type_g)); type=message_type_g[type_id]; /* map the type ID to the actual type object */ assert(type); @@ -1273,91 +894,80 @@ done: * matzke@llnl.gov * Aug 5 1997 * - * Modifications: - * - * Robb Matzke, 1998-08-27 - * This function can also be used to obtain the current number of links - * if zero is passed for ADJUST. If that's the case then we don't check - * for write access on the file. - * - * John Mainzer, 6/6/05 - * Modified function to use the new dirtied parameter to - * H5AC_unprotect() instead of modfying the is_dirty field. - * *------------------------------------------------------------------------- */ int -H5O_link(const H5G_entry_t *ent, int adjust, hid_t dxpl_id) +H5O_link(const H5O_loc_t *loc, int adjust, hid_t dxpl_id) { H5O_t *oh = NULL; - unsigned oh_flags=H5AC__NO_FLAGS_SET; /* used to indicate whether the + unsigned oh_flags = H5AC__NO_FLAGS_SET; /* used to indicate whether the * object was deleted as a result * of this action. */ int ret_value = FAIL; - FUNC_ENTER_NOAPI(H5O_link, FAIL); + FUNC_ENTER_NOAPI(H5O_link, FAIL) /* check args */ - assert(ent); - assert(ent->file); - assert(H5F_addr_defined(ent->header)); - if (adjust!=0 && 0==(ent->file->intent & H5F_ACC_RDWR)) - HGOTO_ERROR (H5E_OHDR, H5E_WRITEERROR, FAIL, "no write intent on file"); + HDassert(loc); + HDassert(loc->file); + HDassert(H5F_addr_defined(loc->addr)); + if(adjust != 0 && 0 == (loc->file->intent & H5F_ACC_RDWR)) + HGOTO_ERROR (H5E_OHDR, H5E_WRITEERROR, FAIL, "no write intent on file") /* get header */ - if (NULL == (oh = H5AC_protect(ent->file, dxpl_id, H5AC_OHDR, ent->header, + if(NULL == (oh = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE))) - HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header"); + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header") /* adjust link count */ - if (adjust<0) { - if (oh->nlink + adjust < 0) - HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "link count would be negative"); + if(adjust < 0) { + if(oh->nlink + adjust < 0) + HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "link count would be negative") oh->nlink += adjust; oh_flags |= H5AC__DIRTIED_FLAG; /* Check if the object should be deleted */ - if(oh->nlink==0) { + if(oh->nlink == 0) { /* Check if the object is still open by the user */ - if(H5FO_opened(ent->file,ent->header)!=NULL) { + if(H5FO_opened(loc->file, loc->addr) != NULL) { /* Flag the object to be deleted when it's closed */ - if(H5FO_mark(ent->file,ent->header,TRUE)<0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't mark object for deletion"); + if(H5FO_mark(loc->file, loc->addr, TRUE) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't mark object for deletion") } /* end if */ else { /* Delete object right now */ - if(H5O_delete_oh(ent->file,dxpl_id,oh)<0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't delete object from file"); + if(H5O_delete_oh(loc->file, dxpl_id, oh) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't delete object from file") /* Mark the object header as deleted */ oh_flags = H5C__DELETED_FLAG; } /* end else */ } /* end if */ - } else if (adjust>0) { + } else if (adjust > 0) { /* A new object, or one that will be deleted */ - if(oh->nlink==0) { + if(oh->nlink == 0) { /* Check if the object is current open, but marked for deletion */ - if(H5FO_marked(ent->file,ent->header)>0) { + if(H5FO_marked(loc->file, loc->addr) > 0) { /* Remove "delete me" flag on the object */ - if(H5FO_mark(ent->file,ent->header,FALSE)<0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't mark object for deletion"); + if(H5FO_mark(loc->file, loc->addr, FALSE) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't mark object for deletion") } /* end if */ } /* end if */ oh->nlink += adjust; oh_flags |= H5AC__DIRTIED_FLAG; - } + } /* end if */ /* Set return value */ ret_value = oh->nlink; done: - if (oh && H5AC_unprotect(ent->file, dxpl_id, H5AC_OHDR, ent->header, oh, oh_flags) < 0) - HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header"); + if (oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0) + HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header") - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_link() */ /*------------------------------------------------------------------------- @@ -1373,36 +983,30 @@ done: * Programmer: Robb Matzke * Tuesday, April 21, 1998 * - * Modifications: - * Changed to use IDs for types, instead of type objects, then - * call "real" routine. - * Quincey Koziol - * Feb 14 2003 - * *------------------------------------------------------------------------- */ int -H5O_count (H5G_entry_t *ent, unsigned type_id, hid_t dxpl_id) +H5O_count(H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id) { const H5O_class_t *type; /* Actual H5O class type for the ID */ int ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5O_count, FAIL); + FUNC_ENTER_NOAPI(H5O_count, FAIL) /* Check args */ - assert (ent); - assert (ent->file); - assert (H5F_addr_defined(ent->header)); - assert(type_id<NELMTS(message_type_g)); - type=message_type_g[type_id]; /* map the type ID to the actual type object */ - assert (type); + HDassert(loc); + HDassert(loc->file); + HDassert(H5F_addr_defined(loc->addr)); + HDassert(type_id < NELMTS(message_type_g)); + type = message_type_g[type_id]; /* map the type ID to the actual type object */ + HDassert(type); /* Call the "real" count routine */ - if((ret_value=H5O_count_real(ent, type, dxpl_id))<0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTCOUNT, FAIL, "unable to count object header messages"); + if((ret_value = H5O_count_real(loc, type, dxpl_id)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOUNT, FAIL, "unable to count object header messages") done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_count() */ @@ -1419,43 +1023,41 @@ done: * Programmer: Robb Matzke * Tuesday, April 21, 1998 * - * Modifications: - * *------------------------------------------------------------------------- */ static int -H5O_count_real (H5G_entry_t *ent, const H5O_class_t *type, hid_t dxpl_id) +H5O_count_real(H5O_loc_t *loc, const H5O_class_t *type, hid_t dxpl_id) { H5O_t *oh = NULL; int acc; unsigned u; int ret_value; - FUNC_ENTER_NOAPI(H5O_count_real, FAIL); + FUNC_ENTER_NOAPI(H5O_count_real, FAIL) /* Check args */ - assert (ent); - assert (ent->file); - assert (H5F_addr_defined(ent->header)); - assert (type); + HDassert(loc); + HDassert(loc->file); + HDassert(H5F_addr_defined(loc->addr)); + HDassert(type); /* Load the object header */ - if (NULL == (oh = H5AC_protect(ent->file, dxpl_id, H5AC_OHDR, ent->header, NULL, NULL, H5AC_READ))) - HGOTO_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header"); + if(NULL == (oh = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ))) + HGOTO_ERROR (H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header") /* Loop over all messages, counting the ones of the type looked for */ - for (u=acc=0; u<oh->nmesgs; u++) - if (oh->mesg[u].type==type) + for(u = acc = 0; u < oh->nmesgs; u++) + if(oh->mesg[u].type == type) acc++; /* Set return value */ - ret_value=acc; + ret_value = acc; done: - if (oh && H5AC_unprotect(ent->file, dxpl_id, H5AC_OHDR, ent->header, oh, H5AC__NO_FLAGS_SET) != SUCCEED) - HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header"); + if (oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) != SUCCEED) + HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header") - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_count_real() */ @@ -1475,35 +1077,29 @@ done: * Programmer: Robb Matzke * Monday, November 2, 1998 * - * Modifications: - * Changed to use IDs for types, instead of type objects, then - * call "real" routine. - * Quincey Koziol - * Feb 14 2003 - * *------------------------------------------------------------------------- */ htri_t -H5O_exists(H5G_entry_t *ent, unsigned type_id, int sequence, hid_t dxpl_id) +H5O_exists(H5O_loc_t *loc, unsigned type_id, int sequence, hid_t dxpl_id) { const H5O_class_t *type; /* Actual H5O class type for the ID */ htri_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5O_exists, FAIL); + FUNC_ENTER_NOAPI(H5O_exists, FAIL) - assert(ent); - assert(ent->file); - assert(type_id<NELMTS(message_type_g)); - type=message_type_g[type_id]; /* map the type ID to the actual type object */ - assert(type); - assert(sequence>=0); + HDassert(loc); + HDassert(loc->file); + HDassert(type_id < NELMTS(message_type_g)); + type = message_type_g[type_id]; /* map the type ID to the actual type object */ + HDassert(type); + HDassert(sequence >= 0); /* Call the "real" exists routine */ - if((ret_value=H5O_exists_real(ent, type, sequence, dxpl_id))<0) - HGOTO_ERROR(H5E_OHDR, H5E_READERROR, FAIL, "unable to verify object header message"); + if((ret_value = H5O_exists_real(loc, type, sequence, dxpl_id)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_READERROR, FAIL, "unable to verify object header message") done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_exists() */ @@ -1523,48 +1119,42 @@ done: * Programmer: Robb Matzke * Monday, November 2, 1998 * - * Modifications: - * - * John Mainzer, 6/6/05 - * Modified function to use the new dirtied parameter to - * H5AC_unprotect() instead of modfying the is_dirty field. - * *------------------------------------------------------------------------- */ static htri_t -H5O_exists_real(H5G_entry_t *ent, const H5O_class_t *type, int sequence, hid_t dxpl_id) +H5O_exists_real(H5O_loc_t *loc, const H5O_class_t *type, int sequence, hid_t dxpl_id) { - H5O_t *oh=NULL; + H5O_t *oh = NULL; unsigned u; htri_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5O_exists_real); + FUNC_ENTER_NOAPI_NOINIT(H5O_exists_real) - assert(ent); - assert(ent->file); - assert(type); - assert(sequence>=0); + HDassert(loc); + HDassert(loc->file); + HDassert(type); + HDassert(sequence >= 0); /* Load the object header */ - if (NULL == (oh = H5AC_protect(ent->file, dxpl_id, H5AC_OHDR, ent->header, NULL, NULL, H5AC_READ))) - HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header"); + if(NULL == (oh = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header") /* Scan through the messages looking for the right one */ - for (u=0; u<oh->nmesgs; u++) { - if (type->id!=oh->mesg[u].type->id) + for(u = 0; u < oh->nmesgs; u++) { + if(type->id != oh->mesg[u].type->id) continue; - if (--sequence<0) + if(--sequence < 0) break; - } + } /* end for */ /* Set return value */ - ret_value=(sequence<0); + ret_value = (sequence < 0); done: - if (oh && H5AC_unprotect(ent->file, dxpl_id, H5AC_OHDR, ent->header, oh, H5AC__NO_FLAGS_SET) != SUCCEED) - HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header"); + if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) != SUCCEED) + HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header") - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_exists_real() */ @@ -1589,37 +1179,31 @@ done: * matzke@llnl.gov * Aug 6 1997 * - * Modifications: - * Changed to use IDs for types, instead of type objects, then - * call "real" routine. - * Quincey Koziol - * Feb 14 2003 - * *------------------------------------------------------------------------- */ void * -H5O_read(const H5G_entry_t *ent, unsigned type_id, int sequence, void *mesg, hid_t dxpl_id) +H5O_read(const H5O_loc_t *loc, unsigned type_id, int sequence, void *mesg, hid_t dxpl_id) { const H5O_class_t *type; /* Actual H5O class type for the ID */ void *ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5O_read, NULL); + FUNC_ENTER_NOAPI(H5O_read, NULL) /* check args */ - assert(ent); - assert(ent->file); - assert(H5F_addr_defined(ent->header)); - assert(type_id<NELMTS(message_type_g)); - type=message_type_g[type_id]; /* map the type ID to the actual type object */ - assert(type); - assert(sequence >= 0); + HDassert(loc); + HDassert(loc->file); + HDassert(H5F_addr_defined(loc->addr)); + HDassert(type_id < NELMTS(message_type_g)); + type = message_type_g[type_id]; /* map the type ID to the actual type object */ + HDassert(type); + HDassert(sequence >= 0); /* Call the "real" read routine */ - if((ret_value=H5O_read_real(ent, type, sequence, mesg, dxpl_id))==NULL) - HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to load object header"); + if((ret_value = H5O_read_real(loc, type, sequence, mesg, dxpl_id)) == NULL) + HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to load object header") done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_read() */ @@ -1644,58 +1228,33 @@ done: * matzke@llnl.gov * Aug 6 1997 * - * Modifications: - * - * Bill Wendling, 2003-09-30 - * Protect the object header and pass it into the H5O_find_in_ohdr - * function. This is done because the H5O_find_in_ohdr used to - * protect the ohdr, find the message, and then unprotect it. This - * saves time and also helps the FPHDF5 stuff, where unprotecting - * actually destroys the object in the cache. - * - * John Mainzer, 6/6/05 - * Modified function to use the new dirtied parameter to - * H5AC_unprotect() instead of modfying the is_dirty field. - * *------------------------------------------------------------------------- */ void * -H5O_read_real(const H5G_entry_t *ent, const H5O_class_t *type, int sequence, void *mesg, hid_t dxpl_id) +H5O_read_real(const H5O_loc_t *loc, const H5O_class_t *type, int sequence, void *mesg, hid_t dxpl_id) { H5O_t *oh = NULL; int idx; - const H5G_cache_t *cache = NULL; - H5G_type_t cache_type; void *ret_value = NULL; - FUNC_ENTER_NOAPI_NOINIT(H5O_read_real); + FUNC_ENTER_NOAPI_NOINIT(H5O_read_real) /* check args */ - assert(ent); - assert(ent->file); - assert(H5F_addr_defined(ent->header)); - assert(type); - assert(sequence >= 0); - - /* can we get it from the symbol table entry? */ - cache = H5G_ent_cache(ent, &cache_type); - - if (H5O_fast_g[cache_type]) { - ret_value = (H5O_fast_g[cache_type]) (cache, type, mesg); - if (ret_value) - HGOTO_DONE(ret_value); - H5E_clear_stack(NULL); /*don't care, try reading from header */ - } + HDassert(loc); + HDassert(loc->file); + HDassert(H5F_addr_defined(loc->addr)); + HDassert(type); + HDassert(sequence >= 0); /* copy the message to the user-supplied buffer */ - if (NULL == (oh = H5AC_protect(ent->file, dxpl_id, H5AC_OHDR, ent->header, NULL, NULL, H5AC_READ))) - HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "unable to load object header"); + if(NULL == (oh = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "unable to load object header") /* can we get it from the object header? */ - if ((idx = H5O_find_in_ohdr(ent->file, dxpl_id, oh, &type, sequence)) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, NULL, "unable to find message in object header"); + if((idx = H5O_find_in_ohdr(loc->file, dxpl_id, oh, &type, sequence)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, NULL, "unable to find message in object header") - if (oh->mesg[idx].flags & H5O_FLAG_SHARED) { + if(oh->mesg[idx].flags & H5O_FLAG_SHARED) { /* * If the message is shared then then the native pointer points to an * H5O_SHARED message. We use that information to look up the real @@ -1704,7 +1263,7 @@ H5O_read_real(const H5G_entry_t *ent, const H5O_class_t *type, int sequence, voi H5O_shared_t *shared; shared = (H5O_shared_t *)(oh->mesg[idx].native); - ret_value=H5O_shared_read(ent->file,dxpl_id,shared,type,mesg); + ret_value = H5O_shared_read(loc->file, dxpl_id, shared, type, mesg); } else { /* * The message is not shared, but rather exists in the object @@ -1712,15 +1271,15 @@ H5O_read_real(const H5G_entry_t *ent, const H5O_class_t *type, int sequence, voi * the raw message) so we must copy the native message before * returning. */ - if (NULL==(ret_value = (type->copy) (oh->mesg[idx].native, mesg, 0))) - HGOTO_ERROR (H5E_OHDR, H5E_CANTINIT, NULL, "unable to copy message to user space"); - } + if(NULL==(ret_value = (type->copy) (oh->mesg[idx].native, mesg, 0))) + HGOTO_ERROR (H5E_OHDR, H5E_CANTINIT, NULL, "unable to copy message to user space") + } /* end else */ done: - if (oh && H5AC_unprotect(ent->file, dxpl_id, H5AC_OHDR, ent->header, oh, H5AC__NO_FLAGS_SET) < 0) - HDONE_ERROR(H5E_OHDR, H5E_PROTECT, NULL, "unable to release object header"); + if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_OHDR, H5E_PROTECT, NULL, "unable to release object header") - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_read_real() */ @@ -1750,7 +1309,6 @@ static unsigned H5O_find_in_ohdr(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_class_t **type_p, int sequence) { unsigned u; - const H5O_class_t *type = NULL; unsigned ret_value; FUNC_ENTER_NOAPI_NOINIT(H5O_find_in_ohdr); @@ -1775,17 +1333,7 @@ H5O_find_in_ohdr(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_class_t **type_p, * Decode the message if necessary. If the message is shared then decode * a shared message, ignoring the message type. */ - if (oh->mesg[u].flags & H5O_FLAG_SHARED) - type = H5O_SHARED; - else - type = oh->mesg[u].type; - - if (NULL == oh->mesg[u].native) { - assert(type->decode); - oh->mesg[u].native = (type->decode) (f, dxpl_id, oh->mesg[u].raw, NULL); - if (NULL == oh->mesg[u].native) - HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, UFAIL, "unable to decode message"); - } + LOAD_NATIVE(f, dxpl_id, &(oh->mesg[u])) /* * Return the message type. If this is a shared message then return the @@ -1833,45 +1381,33 @@ done: * matzke@llnl.gov * Aug 6 1997 * - * Modifications: - * - * Robb Matzke, 7 Jan 1998 - * Handles constant vs non-constant messages. Once a message is made - * constant it can never become non-constant. Constant messages cannot - * be modified. - * - * Changed to use IDs for types, instead of type objects, then - * call "real" routine. - * Quincey Koziol - * Feb 14 2003 - * *------------------------------------------------------------------------- */ int -H5O_modify(H5G_entry_t *ent, unsigned type_id, int overwrite, +H5O_modify(H5O_loc_t *loc, unsigned type_id, int overwrite, unsigned flags, unsigned update_flags, const void *mesg, hid_t dxpl_id) { const H5O_class_t *type; /* Actual H5O class type for the ID */ int ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5O_modify, FAIL); + FUNC_ENTER_NOAPI(H5O_modify, FAIL) /* check args */ - assert(ent); - assert(ent->file); - assert(H5F_addr_defined(ent->header)); - assert(type_id<NELMTS(message_type_g)); - type=message_type_g[type_id]; /* map the type ID to the actual type object */ - assert(type); - assert(mesg); - assert (0==(flags & ~H5O_FLAG_BITS)); + HDassert(loc); + HDassert(loc->file); + HDassert(H5F_addr_defined(loc->addr)); + HDassert(type_id < NELMTS(message_type_g)); + type = message_type_g[type_id]; /* map the type ID to the actual type object */ + HDassert(type); + HDassert(mesg); + HDassert(0 == (flags & ~H5O_FLAG_BITS)); /* Call the "real" modify routine */ - if((ret_value= H5O_modify_real(ent, type, overwrite, flags, update_flags, mesg, dxpl_id))<0) - HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header"); + if((ret_value = H5O_modify_real(loc, type, overwrite, flags, update_flags, mesg, dxpl_id)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header message") done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_modify() */ @@ -1907,25 +1443,13 @@ done: * matzke@llnl.gov * Aug 6 1997 * - * Modifications: - * - * Robb Matzke, 7 Jan 1998 - * Handles constant vs non-constant messages. Once a message is made - * constant it can never become non-constant. Constant messages cannot - * be modified. - * - * John Mainzer, 6/6/05 - * Updated function to use the new dirtied parameter of - * H5AC_unprotect() instead of manipulating the is_dirty - * field of the cache info directly. - * *------------------------------------------------------------------------- */ static int -H5O_modify_real(H5G_entry_t *ent, const H5O_class_t *type, int overwrite, +H5O_modify_real(H5O_loc_t *loc, const H5O_class_t *type, int overwrite, unsigned flags, unsigned update_flags, const void *mesg, hid_t dxpl_id) { - H5O_t *oh=NULL; + H5O_t *oh = NULL; unsigned oh_flags = H5AC__NO_FLAGS_SET; int sequence; unsigned idx; /* Index of message to modify */ @@ -1936,67 +1460,67 @@ H5O_modify_real(H5G_entry_t *ent, const H5O_class_t *type, int overwrite, FUNC_ENTER_NOAPI_NOINIT(H5O_modify_real) /* check args */ - assert(ent); - assert(ent->file); - assert(H5F_addr_defined(ent->header)); - assert(type); - assert(mesg); - assert (0==(flags & ~H5O_FLAG_BITS)); + HDassert(loc); + HDassert(loc->file); + HDassert(H5F_addr_defined(loc->addr)); + HDassert(type); + HDassert(mesg); + HDassert(0 == (flags & ~H5O_FLAG_BITS)); - if (0==(ent->file->intent & H5F_ACC_RDWR)) - HGOTO_ERROR (H5E_OHDR, H5E_WRITEERROR, FAIL, "no write intent on file"); + if(0 == (loc->file->intent & H5F_ACC_RDWR)) + HGOTO_ERROR (H5E_OHDR, H5E_WRITEERROR, FAIL, "no write intent on file") - if (NULL == (oh = H5AC_protect(ent->file, dxpl_id, H5AC_OHDR, ent->header, NULL, NULL, H5AC_WRITE))) - HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header"); + if(NULL == (oh = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header") /* Count similar messages */ - for (idx = 0, sequence = -1, idx_msg=&oh->mesg[0]; idx < oh->nmesgs; idx++, idx_msg++) { - if (type->id != idx_msg->type->id) + for(idx = 0, sequence = -1, idx_msg=&oh->mesg[0]; idx < oh->nmesgs; idx++, idx_msg++) { + if(type->id != idx_msg->type->id) continue; - if (++sequence == overwrite) + if(++sequence == overwrite) break; } /* end for */ /* Was the right message found? */ - if (overwrite >= 0 && (idx >= oh->nmesgs || sequence != overwrite)) { + if(overwrite >= 0 && (idx >= oh->nmesgs || sequence != overwrite)) { /* But can we insert a new one with this sequence number? */ - if (overwrite == sequence + 1) + if(overwrite == sequence + 1) overwrite = -1; else - HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "message not found"); + HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "message not found") } /* end if */ /* Check for creating new message */ - if (overwrite < 0) { + if(overwrite < 0) { /* Create a new message */ - if((idx=H5O_new_mesg(ent->file,oh,&flags,type,mesg,&sh_mesg,&type,&mesg,dxpl_id,&oh_flags))==UFAIL) - HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to create new message"); + if((idx = H5O_new_mesg(loc->file, oh, &flags, type, mesg, &sh_mesg, &type, &mesg, dxpl_id, &oh_flags)) == UFAIL) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to create new message") /* Set the correct sequence number for the message created */ sequence++; - } else if (oh->mesg[idx].flags & H5O_FLAG_CONSTANT) { - HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to modify constant message"); - } else if (oh->mesg[idx].flags & H5O_FLAG_SHARED) { - HGOTO_ERROR (H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to modify shared (constant) message"); + } else if(oh->mesg[idx].flags & H5O_FLAG_CONSTANT) { + HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to modify constant message") + } else if(oh->mesg[idx].flags & H5O_FLAG_SHARED) { + HGOTO_ERROR (H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to modify shared (constant) message") } /* Write the information to the message */ - if(H5O_write_mesg(oh,idx,type,mesg,flags,update_flags,&oh_flags)<0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to write message"); + if(H5O_write_mesg(oh, idx, type, mesg, flags, update_flags, &oh_flags) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to write message") /* Update the modification time message if any */ - if(update_flags&H5O_UPDATE_TIME) - H5O_touch_oh(ent->file, dxpl_id, oh, FALSE, &oh_flags); + if(update_flags & H5O_UPDATE_TIME) + H5O_touch_oh(loc->file, dxpl_id, oh, FALSE, &oh_flags); /* Set return value */ ret_value = sequence; done: - if (oh && H5AC_unprotect(ent->file, dxpl_id, H5AC_OHDR, ent->header, oh, oh_flags) < 0) - HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header"); + if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0) + HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header") - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_modify_real() */ @@ -2016,30 +1540,28 @@ done: * koziol@ncsa.uiuc.edu * Dec 31 2002 * - * Modifications: - * *------------------------------------------------------------------------- */ H5O_t * -H5O_protect(H5G_entry_t *ent, hid_t dxpl_id) +H5O_protect(H5O_loc_t *loc, hid_t dxpl_id) { H5O_t *ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5O_protect, NULL); + FUNC_ENTER_NOAPI(H5O_protect, NULL) /* check args */ - assert(ent); - assert(ent->file); - assert(H5F_addr_defined(ent->header)); + HDassert(loc); + HDassert(loc->file); + HDassert(H5F_addr_defined(loc->addr)); - if (0==(ent->file->intent & H5F_ACC_RDWR)) - HGOTO_ERROR (H5E_OHDR, H5E_WRITEERROR, NULL, "no write intent on file"); + if(0 == (loc->file->intent & H5F_ACC_RDWR)) + HGOTO_ERROR (H5E_OHDR, H5E_WRITEERROR, NULL, "no write intent on file") - if (NULL == (ret_value = H5AC_protect(ent->file, dxpl_id, H5AC_OHDR, ent->header, NULL, NULL, H5AC_WRITE))) - HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "unable to load object header"); + if(NULL == (ret_value = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "unable to load object header") done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_protect() */ @@ -2058,33 +1580,26 @@ done: * koziol@ncsa.uiuc.edu * Dec 31 2002 * - * Modifications: - * - * John Mainzer, 6/6/05 - * Updated function to use the new dirtied parameter of - * H5AC_unprotect() instead of manipulating the is_dirty - * field of the cache info directly. - * *------------------------------------------------------------------------- */ herr_t -H5O_unprotect(H5G_entry_t *ent, H5O_t *oh, hid_t dxpl_id, unsigned oh_flags) +H5O_unprotect(H5O_loc_t *loc, H5O_t *oh, hid_t dxpl_id, unsigned oh_flags) { - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5O_unprotect, FAIL); + FUNC_ENTER_NOAPI(H5O_unprotect, FAIL) /* check args */ - assert(ent); - assert(ent->file); - assert(H5F_addr_defined(ent->header)); - assert(oh); + HDassert(loc); + HDassert(loc->file); + HDassert(H5F_addr_defined(loc->addr)); + HDassert(oh); - if (H5AC_unprotect(ent->file, dxpl_id, H5AC_OHDR, ent->header, oh, oh_flags) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header"); + if(H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header") done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_unprotect() */ @@ -2128,7 +1643,7 @@ H5O_append(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned type_id, unsigned flags, /* check args */ assert(f); assert(oh); - assert(type_id<NELMTS(message_type_g)); + assert(type_id < NELMTS(message_type_g)); type=message_type_g[type_id]; /* map the type ID to the actual type object */ assert(type); assert(0==(flags & ~H5O_FLAG_BITS)); @@ -2136,7 +1651,7 @@ H5O_append(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned type_id, unsigned flags, assert(oh_flags_ptr); /* Call the "real" append routine */ - if((ret_value=H5O_append_real( f, dxpl_id, oh, type, flags, mesg, oh_flags_ptr))<0) + if((ret_value=H5O_append_real( f, dxpl_id, oh, type, flags, mesg, oh_flags_ptr)) < 0) HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to append to object header"); done: @@ -2159,13 +1674,6 @@ done: * koziol@ncsa.uiuc.edu * Dec 31 2002 * - * Modifications: - * - * John Mainzer, 6/6/05 - * Updated function to use the new dirtied parameter of - * H5AC_unprotect() instead of manipulating the is_dirty - * of the cache info. - * *------------------------------------------------------------------------- */ static int @@ -2191,7 +1699,7 @@ H5O_append_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_class_t *type, HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to create new message"); /* Write the information to the message */ - if(H5O_write_mesg(oh,idx,type,mesg,flags,0,oh_flags_ptr)<0) + if(H5O_write_mesg(oh,idx,type,mesg,flags,0,oh_flags_ptr) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to write message"); /* Set return value */ @@ -2213,14 +1721,6 @@ done: * Programmer: Quincey Koziol * Friday, September 3, 2003 * - * Modifications: - * - * John Mainzer, 6/7/05 - * Modified function to use the new dirtied parameter to - * H5AC_unprotect() instead of modfying the is_dirty field. - * In this case, that requires the addition of the oh_dirtied_ptr - * parameter to track whether *oh is dirty. - * *------------------------------------------------------------------------- */ static unsigned @@ -2250,7 +1750,7 @@ H5O_new_mesg(H5F_t *f, H5O_t *oh, unsigned *flags, const H5O_class_t *orig_type, if (NULL==orig_type->get_share) HGOTO_ERROR (H5E_OHDR, H5E_UNSUPPORTED, UFAIL, "message class is not sharable"); - if ((orig_type->get_share)(f, orig_mesg, sh_mesg/*out*/)<0) { + if ((orig_type->get_share)(f, orig_mesg, sh_mesg/*out*/) < 0) { /* * If the message isn't shared then turn off the shared bit * and treat it as an unshared message. @@ -2270,14 +1770,14 @@ H5O_new_mesg(H5F_t *f, H5O_t *oh, unsigned *flags, const H5O_class_t *orig_type, /* Compute the size needed to store the message on disk */ if ((size = ((*new_type)->raw_size) (f, *new_mesg)) >=H5O_MAX_SIZE) - HGOTO_ERROR (H5E_OHDR, H5E_CANTINIT, UFAIL, "object header message is too large (16k max)"); + HGOTO_ERROR (H5E_OHDR, H5E_CANTINIT, UFAIL, "object header message is too large"); /* Allocate space in the object headed for the message */ if ((ret_value = H5O_alloc(f, dxpl_id, oh, orig_type, size, oh_flags_ptr)) == UFAIL) HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, UFAIL, "unable to allocate space for message"); /* Increment any links in message */ - if((*new_type)->link && ((*new_type)->link)(f,dxpl_id,(*new_mesg))<0) + if((*new_type)->link && ((*new_type)->link)(f,dxpl_id,(*new_mesg)) < 0) HGOTO_ERROR (H5E_OHDR, H5E_LINK, UFAIL, "unable to adjust shared object link count"); done: @@ -2353,18 +1853,6 @@ done: * Programmer: Robb Matzke * Monday, July 27, 1998 * - * Modifications: - * - * John Mainzer, 6/6/05 - * Modified function to use the new dirtied parameter to - * H5AC_unprotect() instead of modfying the is_dirty field. - * In this case, that requires the addition of the oh_dirtied_ptr - * parameter to track whether *oh is dirty. - * - * John Mainzer, 8/20/05 - * Added dxpl_id parameter needed by the revised version of - * H5O_alloc(). - * *------------------------------------------------------------------------- */ herr_t @@ -2375,9 +1863,6 @@ H5O_touch_oh(H5F_t *f, unsigned * oh_flags_ptr) { unsigned idx; -#ifdef H5_HAVE_GETTIMEOFDAY - struct timeval now_tv; -#endif /* H5_HAVE_GETTIMEOFDAY */ time_t now; size_t size; herr_t ret_value=SUCCEED; /* Return value */ @@ -2388,14 +1873,18 @@ H5O_touch_oh(H5F_t *f, assert(oh_flags_ptr); /* Look for existing message */ - for (idx=0; idx<oh->nmesgs; idx++) { + for (idx=0; idx < oh->nmesgs; idx++) { if (H5O_MTIME==oh->mesg[idx].type || H5O_MTIME_NEW==oh->mesg[idx].type) break; } #ifdef H5_HAVE_GETTIMEOFDAY - HDgettimeofday(&now_tv,NULL); - now=now_tv.tv_sec; + { + struct timeval now_tv; + + HDgettimeofday(&now_tv, NULL); + now = now_tv.tv_sec; + } #else /* H5_HAVE_GETTIMEOFDAY */ now = HDtime(NULL); #endif /* H5_HAVE_GETTIMEOFDAY */ @@ -2447,35 +1936,35 @@ done: *------------------------------------------------------------------------- */ herr_t -H5O_touch(H5G_entry_t *ent, hbool_t force, hid_t dxpl_id) +H5O_touch(H5O_loc_t *loc, hbool_t force, hid_t dxpl_id) { H5O_t *oh = NULL; unsigned oh_flags = H5AC__NO_FLAGS_SET; - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5O_touch, FAIL); + FUNC_ENTER_NOAPI(H5O_touch, FAIL) /* check args */ - assert(ent); - assert(ent->file); - assert(H5F_addr_defined(ent->header)); - if (0==(ent->file->intent & H5F_ACC_RDWR)) - HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "no write intent on file"); + HDassert(loc); + HDassert(loc->file); + HDassert(H5F_addr_defined(loc->addr)); + if(0 == (loc->file->intent & H5F_ACC_RDWR)) + HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "no write intent on file") /* Get the object header */ - if (NULL==(oh=H5AC_protect(ent->file, dxpl_id, H5AC_OHDR, ent->header, NULL, NULL, H5AC_WRITE))) - HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header"); + if(NULL == (oh = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header") /* Create/Update the modification time message */ - if (H5O_touch_oh(ent->file, dxpl_id, oh, force, &oh_flags)<0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to update object modificaton time"); + if(H5O_touch_oh(loc->file, dxpl_id, oh, force, &oh_flags) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to update object modificaton time") done: - if (oh && H5AC_unprotect(ent->file, dxpl_id, H5AC_OHDR, ent->header, oh, oh_flags)<0) - HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header"); + if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0) + HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header") - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_touch() */ #ifdef H5O_ENABLE_BOGUS @@ -2490,46 +1979,35 @@ done: * <koziol@ncsa.uiuc.edu> * Tuesday, January 21, 2003 * - * Modifications: - * - * John Mainzer, 6/16/05 - * Modified function to use the new dirtied parameter to - * H5AC_unprotect() instead of modfying the is_dirty field. - * In this case, that requires the addition of the oh_dirtied_ptr - * parameter to track whether *oh is dirty. - * - * John Mainzer, 8/20/05 - * Added dxpl_id parameter needed by call to H5O_alloc(). - * *------------------------------------------------------------------------- */ herr_t H5O_bogus_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh, hbool_t * oh_flags_ptr) { int idx; - size_t size; - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER(H5O_bogus_oh, FAIL); + FUNC_ENTER(H5O_bogus_oh, FAIL) - assert(f); - assert(oh); - assert(oh_flags_ptr); + HDassert(f); + HDassert(oh); + HDassert(oh_flags_ptr); /* Look for existing message */ - for (idx=0; idx<oh->nmesgs; idx++) - if (H5O_BOGUS==oh->mesg[idx].type) + for(idx = 0; idx < oh->nmesgs; idx++) + if(H5O_BOGUS == oh->mesg[idx].type) break; /* Create a new message */ - if (idx==oh->nmesgs) { - size = (H5O_BOGUS->raw_size)(f, NULL); - if ((idx=H5O_alloc(f, dxpl_id, oh, H5O_BOGUS, size, oh_flags_ptr))<0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to allocate space for 'bogus' message"); + if(idx == oh->nmesgs) { + size_t size = (H5O_BOGUS->raw_size)(f, NULL); + + if((idx = H5O_alloc(f, dxpl_id, oh, H5O_BOGUS, size, oh_flags_ptr)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to allocate space for 'bogus' message") /* Allocate the native message in memory */ - if (NULL==(oh->mesg[idx].native = H5MM_malloc(sizeof(H5O_bogus_t)))) - HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "memory allocation failed for 'bogus' message"); + if(NULL == (oh->mesg[idx].native = H5MM_malloc(sizeof(H5O_bogus_t)))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "memory allocation failed for 'bogus' message") /* Update the native part */ ((H5O_bogus_t *)(oh->mesg[idx].native))->u = H5O_BOGUS_VALUE; @@ -2541,7 +2019,7 @@ H5O_bogus_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh, hbool_t * oh_flags_ptr) } /* end if */ done: - FUNC_LEAVE(ret_value); + FUNC_LEAVE(ret_value) } /* end H5O_bogus_oh() */ @@ -2556,45 +2034,39 @@ done: * <koziol@ncsa.uiuc.edu> * Tuesday, January 21, 2003 * - * Modifications: - * - * John Mainzer, 6/16/05 - * Modified function to use the new dirtied parameter to - * H5AC_unprotect() instead of modfying the is_dirty field. - * *------------------------------------------------------------------------- */ herr_t -H5O_bogus(H5G_entry_t *ent, hid_t dxpl_id) +H5O_bogus(H5O_loc_t *loc, hid_t dxpl_id) { H5O_t *oh = NULL; unsigned oh_flags = H5AC__NO_FLAGS_SET; herr_t ret_value = SUCCEED; - FUNC_ENTER(H5O_bogus, FAIL); + FUNC_ENTER(H5O_bogus, FAIL) /* check args */ - assert(ent); - assert(ent->file); - assert(H5F_addr_defined(ent->header)); + HDassert(loc); + HDassert(loc->file); + HDassert(H5F_addr_defined(loc->addr)); /* Verify write access to the file */ - if (0==(ent->file->intent & H5F_ACC_RDWR)) - HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "no write intent on file"); + if(0 == (loc->file->intent & H5F_ACC_RDWR)) + HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "no write intent on file") /* Get the object header */ - if (NULL==(oh=H5AC_protect(ent->file, dxpl_id, H5AC_OHDR, ent->header, NULL, NULL, H5AC_WRITE))) - HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header"); + if(NULL == (oh = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header") /* Create the "bogus" message */ - if (H5O_bogus_oh(ent->file, dxpl_id, oh, &oh_flags)<0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to update object 'bogus' message"); + if(H5O_bogus_oh(ent->file, dxpl_id, oh, &oh_flags) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to update object 'bogus' message") done: - if (oh && H5AC_unprotect(ent->file, dxpl_id, H5AC_OHDR, ent->header, oh, oh_flags)<0) - HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header"); + if(oh && H5AC_unprotect(ent->file, dxpl_id, H5AC_OHDR, ent->header, oh, oh_flags) < 0) + HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header") - FUNC_LEAVE(ret_value); + FUNC_LEAVE(ret_value) } /* end H5O_bogus() */ #endif /* H5O_ENABLE_BOGUS */ @@ -2630,7 +2102,7 @@ done: *------------------------------------------------------------------------- */ herr_t -H5O_remove(H5G_entry_t *ent, unsigned type_id, int sequence, hbool_t adj_link, hid_t dxpl_id) +H5O_remove(H5O_loc_t *loc, unsigned type_id, int sequence, hbool_t adj_link, hid_t dxpl_id) { const H5O_class_t *type; /* Actual H5O class type for the ID */ herr_t ret_value; /* Return value */ @@ -2638,15 +2110,15 @@ H5O_remove(H5G_entry_t *ent, unsigned type_id, int sequence, hbool_t adj_link, h FUNC_ENTER_NOAPI(H5O_remove, FAIL) /* check args */ - HDassert(ent); - HDassert(ent->file); - HDassert(H5F_addr_defined(ent->header)); + HDassert(loc); + HDassert(loc->file); + HDassert(H5F_addr_defined(loc->addr)); HDassert(type_id < NELMTS(message_type_g)); type = message_type_g[type_id]; /* map the type ID to the actual type object */ HDassert(type); /* Call the "real" remove routine */ - if((ret_value = H5O_remove_real(ent, type, sequence, NULL, NULL, adj_link, dxpl_id))<0) + if((ret_value = H5O_remove_real(loc, type, sequence, NULL, NULL, adj_link, dxpl_id)) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to remove object header message") done: @@ -2672,7 +2144,7 @@ done: *------------------------------------------------------------------------- */ herr_t -H5O_remove_op(H5G_entry_t *ent, unsigned type_id, +H5O_remove_op(const H5O_loc_t *loc, unsigned type_id, int sequence, H5O_operator_t op, void *op_data, hbool_t adj_link, hid_t dxpl_id) { const H5O_class_t *type; /* Actual H5O class type for the ID */ @@ -2681,15 +2153,15 @@ H5O_remove_op(H5G_entry_t *ent, unsigned type_id, FUNC_ENTER_NOAPI(H5O_remove_op, FAIL) /* check args */ - HDassert(ent); - HDassert(ent->file); - HDassert(H5F_addr_defined(ent->header)); + HDassert(loc); + HDassert(loc->file); + HDassert(H5F_addr_defined(loc->addr)); HDassert(type_id < NELMTS(message_type_g)); type = message_type_g[type_id]; /* map the type ID to the actual type object */ HDassert(type); /* Call the "real" remove routine */ - if((ret_value = H5O_remove_real(ent, type, H5O_ALL, op, op_data, adj_link, dxpl_id))<0) + if((ret_value = H5O_remove_real(loc, type, sequence, op, op_data, adj_link, dxpl_id)) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to remove object header message") done: @@ -2710,8 +2182,6 @@ done: * koziol@ncsa.uiuc.edu * Sep 6 2005 * - * Modifications: - * *------------------------------------------------------------------------- */ static herr_t @@ -2731,12 +2201,12 @@ H5O_remove_cb(H5O_mesg_t *mesg/*in,out*/, unsigned idx, unsigned * oh_flags_ptr, if(udata->op) { /* Call the iterator callback */ if((try_remove = (udata->op)(mesg->native, idx, udata->op_data)) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, H5O_ITER_ERROR, "unable to delete file space for object header message") + HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, H5O_ITER_ERROR, "object header message deletion callback failed") } /* end if */ else { /* If there's no callback routine, does the sequence # match? */ - if ((int)idx == udata->sequence || H5O_ALL == udata->sequence) - try_remove = TRUE; + if((int)idx == udata->sequence || H5O_ALL == udata->sequence) + try_remove = H5O_ITER_STOP; } /* end else */ /* Try removing the message, if indicated */ @@ -2745,12 +2215,12 @@ H5O_remove_cb(H5O_mesg_t *mesg/*in,out*/, unsigned idx, unsigned * oh_flags_ptr, * Keep track of how many times we failed trying to remove constant * messages. */ - if (mesg->flags & H5O_FLAG_CONSTANT) { + if(mesg->flags & H5O_FLAG_CONSTANT) { udata->nfailed++; } /* end if */ else { /* Free any space referred to in the file from this message */ - if(H5O_delete_mesg(udata->f, udata->dxpl_id, mesg, udata->adj_link)<0) + if(H5O_delete_mesg(udata->f, udata->dxpl_id, mesg, udata->adj_link) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, H5O_ITER_ERROR, "unable to delete file space for object header message") /* Free any native information */ @@ -2768,7 +2238,7 @@ H5O_remove_cb(H5O_mesg_t *mesg/*in,out*/, unsigned idx, unsigned * oh_flags_ptr, } /* end else */ /* Break out now, if we've found the correct message */ - if(udata->sequence != H5O_ALL) + if(udata->sequence == H5O_FIRST || udata->sequence != H5O_ALL) HGOTO_DONE(H5O_ITER_STOP) } /* end if */ @@ -2795,19 +2265,10 @@ done: * matzke@llnl.gov * Aug 28 1997 * - * Modifications: - * - * Robb Matzke, 7 Jan 1998 - * Does not remove constant messages. - * - * John Mainzer, 6/6/05 - * Modified function to use the new dirtied parameter to - * H5AC_unprotect() instead of modfying the is_dirty field. - * *------------------------------------------------------------------------- */ static herr_t -H5O_remove_real(H5G_entry_t *ent, const H5O_class_t *type, int sequence, +H5O_remove_real(const H5O_loc_t *loc, const H5O_class_t *type, int sequence, H5O_operator_t op, void *op_data, hbool_t adj_link, hid_t dxpl_id) { H5O_iter_ud1_t udata; /* User data for iterator */ @@ -2816,15 +2277,15 @@ H5O_remove_real(H5G_entry_t *ent, const H5O_class_t *type, int sequence, FUNC_ENTER_NOAPI_NOINIT(H5O_remove_real) /* check args */ - HDassert(ent); - HDassert(ent->file); + HDassert(loc); + HDassert(loc->file); HDassert(type); - if (0==(ent->file->intent & H5F_ACC_RDWR)) + if (0==(loc->file->intent & H5F_ACC_RDWR)) HGOTO_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file") /* Set up iterator operator data */ - udata.f = ent->file; + udata.f = loc->file; udata.dxpl_id = dxpl_id; udata.sequence = sequence; udata.nfailed = 0; @@ -2833,11 +2294,11 @@ H5O_remove_real(H5G_entry_t *ent, const H5O_class_t *type, int sequence, udata.adj_link = adj_link; /* Iterate over the messages, deleting appropriate one(s) */ - if(H5O_iterate_real(ent, type, H5AC_WRITE, TRUE, (void *)H5O_remove_cb, &udata, dxpl_id) < 0) + if(H5O_iterate_real(loc, type, H5AC_WRITE, TRUE, (void *)H5O_remove_cb, &udata, dxpl_id) < 0) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "error iterating over messages") /* Fail if we tried to remove any constant messages */ - if (udata.nfailed) + if(udata.nfailed) HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to remove constant message(s)") done: @@ -2847,6 +2308,517 @@ done: /*------------------------------------------------------------------------- * + * Function: H5O_move_msgs_forward + * + * Purpose: Move messages toward first chunk + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Oct 17 2005 + * + *------------------------------------------------------------------------- + */ +static htri_t +H5O_move_msgs_forward(H5F_t *f, H5O_t *oh, hid_t dxpl_id) +{ + hbool_t packed_msg; /* Flag to indicate that messages were packed */ + hbool_t did_packing = FALSE; /* Whether any messages were packed */ + htri_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5O_move_msgs_forward) + + /* check args */ + HDassert(oh != NULL); + + /* Loop until no messages packed */ + /* (Double loop is not very efficient, but it would be some extra work to add + * a list of messages to each chunk -QAK) + */ + do { + H5O_mesg_t *curr_msg; /* Pointer to current message to operate on */ + unsigned u; /* Local index variable */ + + /* Reset packed messages flag */ + packed_msg = FALSE; + + /* Scan through messages for messages that can be moved earlier in chunks */ + for(u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++) { + if(H5O_NULL_ID == curr_msg->type->id) { + H5O_chunk_t *chunk; /* Pointer to chunk that null message is in */ + + /* Check if null message is not last in chunk */ + chunk = &(oh->chunk[curr_msg->chunkno]); + if((curr_msg->raw + curr_msg->raw_size) != (chunk->image + chunk->size)) { + H5O_mesg_t *nonnull_msg; /* Pointer to current message to operate on */ + unsigned v; /* Local index variable */ + + /* Loop over messages again, looking for the message in the chunk after the null message */ + for(v = 0, nonnull_msg = &oh->mesg[0]; v < oh->nmesgs; v++, nonnull_msg++) { + /* Locate message that is immediately after the null message */ + if((curr_msg->chunkno == nonnull_msg->chunkno) && + ((curr_msg->raw + curr_msg->raw_size) == (nonnull_msg->raw - H5O_SIZEOF_MSGHDR(f)))) { + /* Don't swap messages if the second message is also a null message */ + /* (We'll merge them together later, in another routine) */ + if(H5O_NULL_ID != nonnull_msg->type->id) { + /* Make certain non-null message has been translated into native form */ + /* (So that when we mark it dirty, it will get copied back into raw chunk image) */ + LOAD_NATIVE(f, dxpl_id, nonnull_msg) + + /* Adjust non-null message's offset in chunk */ + nonnull_msg->raw = curr_msg->raw; + + /* Adjust null message's offset in chunk */ + curr_msg->raw = nonnull_msg->raw + + nonnull_msg->raw_size + H5O_SIZEOF_MSGHDR(f); + + /* Mark messages dirty */ + curr_msg->dirty = TRUE; + nonnull_msg->dirty = TRUE; + + /* Set the flag to indicate that the null message + * was packed - if its not at the end its chunk, + * we'll move it again on the next pass. + */ + packed_msg = TRUE; + } /* end if */ + + /* Break out of loop */ + break; + } /* end if */ + } /* end for */ + /* Should have been message after null message */ + HDassert(v < oh->nmesgs); + } /* end if */ + } /* end if */ + else { + H5O_mesg_t *null_msg; /* Pointer to current message to operate on */ + unsigned v; /* Local index variable */ + + /* Loop over messages again, looking for large enough null message in earlier chunk */ + for(v = 0, null_msg = &oh->mesg[0]; v < oh->nmesgs; v++, null_msg++) { + if(H5O_NULL_ID == null_msg->type->id && curr_msg->chunkno > null_msg->chunkno + && curr_msg->raw_size <= null_msg->raw_size) { + unsigned old_chunkno; /* Old message information */ + uint8_t *old_raw; + size_t old_raw_size; + + /* Keep old information about non-null message */ + old_chunkno = curr_msg->chunkno; + old_raw = curr_msg->raw; + old_raw_size = curr_msg->raw_size; + + /* Make certain non-null message has been translated into native form */ + /* (So that when we mark it dirty, it will get copied back into raw chunk image) */ + LOAD_NATIVE(f, dxpl_id, curr_msg) + + /* Change information for non-null message */ + if(curr_msg->raw_size == null_msg->raw_size) { + /* Point non-null message at null message's space */ + curr_msg->chunkno = null_msg->chunkno; + curr_msg->raw = null_msg->raw; + + /* Mark non-null message dirty */ + curr_msg->dirty = TRUE; + + /* Point null message at old non-null space */ + /* (Instead of freeing it and allocating new message) */ + null_msg->chunkno = old_chunkno; + null_msg->raw = old_raw; + + /* Mark null message dirty */ + null_msg->dirty = TRUE; + } /* end if */ + else { + unsigned new_null_msg; /* Message index for new null message */ + + /* Point non-null message at null message's space */ + curr_msg->chunkno = null_msg->chunkno; + curr_msg->raw = null_msg->raw; + + /* Mark non-null message dirty */ + curr_msg->dirty = TRUE; + + /* Adjust null message's size & offset */ + null_msg->raw += curr_msg->raw_size + H5O_SIZEOF_MSGHDR(f); + null_msg->raw_size -= curr_msg->raw_size + H5O_SIZEOF_MSGHDR(f); + + /* Mark null message dirty */ + null_msg->dirty = TRUE; + + /* Create new null message for previous location of non-null message */ + if(oh->nmesgs >= oh->alloc_nmesgs) { + unsigned na = oh->alloc_nmesgs + H5O_NMESGS; + H5O_mesg_t *x = H5FL_SEQ_REALLOC(H5O_mesg_t, oh->mesg, (size_t)na); + + if(NULL == x) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + oh->alloc_nmesgs = na; + oh->mesg = x; + } /* end if */ + + /* Get message # for new message */ + new_null_msg = oh->nmesgs++; + + /* Initialize new null message */ + oh->mesg[new_null_msg].type = H5O_NULL; + oh->mesg[new_null_msg].dirty = TRUE; + oh->mesg[new_null_msg].native = NULL; + oh->mesg[new_null_msg].raw = old_raw; + oh->mesg[new_null_msg].raw_size = old_raw_size; + oh->mesg[new_null_msg].chunkno = old_chunkno; + } /* end else */ + + /* Indicate that we packed messages */ + packed_msg = TRUE; + + /* Break out of loop */ + /* (If it's possible to move messge to even ealier chunk + * we'll get it on the next pass - QAK) + */ + break; + } /* end if */ + } /* end for */ + + /* If we packed messages, get out of loop and start over */ + /* (Don't know if this has any benefit one way or the other -QAK) */ + if(packed_msg) + break; + } /* end else */ + } /* end for */ + + /* If we did any packing, remember that */ + if(packed_msg) + did_packing = TRUE; + } while(packed_msg); + + /* Set return value */ + ret_value = did_packing; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5O_move_msgs_forward() */ + + +/*------------------------------------------------------------------------- + * + * Function: H5O_merge_null + * + * Purpose: Merge neighboring null messages in an object header + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Oct 10 2005 + * + *------------------------------------------------------------------------- + */ +static htri_t +H5O_merge_null(H5F_t *f, H5O_t *oh) +{ + hbool_t merged_msg; /* Flag to indicate that messages were merged */ + hbool_t did_merging = FALSE; /* Whether any messages were merged */ + htri_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_merge_null) + + /* check args */ + HDassert(oh != NULL); + + /* Loop until no messages merged */ + /* (Double loop is not very efficient, but it would be some extra work to add + * a list of messages to each chunk -QAK) + */ + do { + H5O_mesg_t *curr_msg; /* Pointer to current message to operate on */ + unsigned u; /* Local index variable */ + + /* Reset merged messages flag */ + merged_msg = FALSE; + + /* Scan messages for adjacent null messages & merge them */ + for(u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++) { + if(H5O_NULL_ID == curr_msg->type->id) { + H5O_mesg_t *curr_msg2; /* Pointer to current message to operate on */ + unsigned v; /* Local index variable */ + + /* Loop over messages again, looking for null message in same chunk */ + for(v = 0, curr_msg2 = &oh->mesg[0]; v < oh->nmesgs; v++, curr_msg2++) { + if(u != v && H5O_NULL_ID == curr_msg2->type->id && curr_msg->chunkno == curr_msg2->chunkno) { + + /* Check for second message after first message */ + if((curr_msg->raw + curr_msg->raw_size) == (curr_msg2->raw - H5O_SIZEOF_MSGHDR(f))) { + /* Extend first null message length to cover second null message */ + curr_msg->raw_size += (H5O_SIZEOF_MSGHDR(f) + curr_msg2->raw_size); + + /* Message has been merged */ + merged_msg = TRUE; + } /* end if */ + /* Check for second message befre first message */ + else if((curr_msg->raw - H5O_SIZEOF_MSGHDR(f)) == (curr_msg2->raw + curr_msg2->raw_size)) { + /* Adjust first message address and extend length to cover second message */ + curr_msg->raw -= (H5O_SIZEOF_MSGHDR(f) + curr_msg2->raw_size); + curr_msg->raw_size += (H5O_SIZEOF_MSGHDR(f) + curr_msg2->raw_size); + + /* Message has been merged */ + merged_msg = TRUE; + } /* end if */ + + /* Second message has been merged, delete it */ + if(merged_msg) { + /* Release any information/memory for second message */ + H5O_free_mesg(curr_msg2); + + /* Mark first message as dirty */ + curr_msg->dirty = TRUE; + + /* Remove second message from list of messages */ + if(v < (oh->nmesgs - 1)) + HDmemmove(&oh->mesg[v], &oh->mesg[v + 1], ((oh->nmesgs - 1) - v) * sizeof(H5O_mesg_t)); + + /* Decrement # of messages */ + /* (Don't bother reducing size of message array for now -QAK) */ + oh->nmesgs--; + + /* Get out of loop */ + break; + } /* end if */ + } /* end if */ + } /* end for */ + + /* Get out of loop if we merged messages */ + if(merged_msg) + break; + } /* end if */ + } /* end for */ + + /* If we did any merging, remember that */ + if(merged_msg) + did_merging = TRUE; + } while(merged_msg); + + /* Set return value */ + ret_value = did_merging; + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5O_merge_null() */ + + +/*------------------------------------------------------------------------- + * + * Function: H5O_remove_empty_chunks + * + * Purpose: Attempt to eliminate empty chunks from object header. + * + * This examines a chunk to see if it's empty + * and removes it (and the continuation message that points to it) + * from the object header. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Oct 17 2005 + * + *------------------------------------------------------------------------- + */ +static htri_t +H5O_remove_empty_chunks(H5F_t *f, H5O_t *oh, hid_t dxpl_id) +{ + hbool_t deleted_chunk; /* Whether to a chunk was deleted */ + hbool_t did_deleting = FALSE; /* Whether any chunks were deleted */ + htri_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5O_remove_empty_chunks) + + /* check args */ + HDassert(oh != NULL); + + /* Loop until no chunks are freed */ + do { + H5O_mesg_t *null_msg; /* Pointer to null message found */ + H5O_mesg_t *cont_msg; /* Pointer to continuation message found */ + unsigned u, v; /* Local index variables */ + + /* Reset 'chunk deleted' flag */ + deleted_chunk = FALSE; + + /* Scan messages for null messages that fill an entire chunk */ + for(u = 0, null_msg = &oh->mesg[0]; u < oh->nmesgs; u++, null_msg++) { + /* If a null message takes up an entire object header chunk (and + * its not the "base" chunk), delete that chunk from object header + */ + if(H5O_NULL_ID == null_msg->type->id && null_msg->chunkno > 0 && + (H5O_SIZEOF_MSGHDR(f) + null_msg->raw_size) == oh->chunk[null_msg->chunkno].size) { + H5O_mesg_t *curr_msg; /* Pointer to current message to operate on */ + unsigned null_msg_no; /* Message # for null message */ + unsigned deleted_chunkno; /* Chunk # to delete */ + + /* Locate continuation message that points to chunk */ + for(v = 0, cont_msg = &oh->mesg[0]; v < oh->nmesgs; v++, cont_msg++) { + if(H5O_CONT_ID == cont_msg->type->id) { + /* Decode current continuation message if necessary */ + if(NULL == cont_msg->native) { + HDassert(H5O_CONT->decode); + cont_msg->native = (H5O_CONT->decode) (f, dxpl_id, cont_msg->raw); + if(NULL == cont_msg->native) + HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "unable to decode message") + } /* end if */ + + /* Check for correct chunk to delete */ + if(oh->chunk[null_msg->chunkno].addr == ((H5O_cont_t *)(cont_msg->native))->addr) + break; + } /* end if */ + } /* end for */ + /* Must be a continuation message that points to chunk containing null message */ + HDassert(v < oh->nmesgs); + HDassert(cont_msg); + + /* Initialize information about null message */ + null_msg_no = u; + deleted_chunkno = null_msg->chunkno; + + /* + * Convert continuation message into a null message + */ + + /* Free space for chunk referred to in the file from the continuation message */ + if(H5O_delete_mesg(f, dxpl_id, cont_msg, TRUE) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, H5O_ITER_ERROR, "unable to delete file space for object header message") + + /* Free any native information */ + H5O_free_mesg(cont_msg); + + /* Change message type to nil and zero it */ + cont_msg->type = H5O_NULL; + HDmemset(cont_msg->raw, 0, cont_msg->raw_size); + + /* Indicate that the continuation message was modified */ + cont_msg->dirty = TRUE; + + /* + * Remove chunk from object header's data structure + */ + + /* Free memory for chunk image */ + H5FL_BLK_FREE(chunk_image, oh->chunk[null_msg->chunkno].image); + + /* Remove chunk from list of chunks */ + if(null_msg->chunkno < (oh->nchunks - 1)) + HDmemmove(&oh->chunk[null_msg->chunkno], &oh->chunk[null_msg->chunkno + 1], ((oh->nchunks - 1) - null_msg->chunkno) * sizeof(H5O_chunk_t)); + + /* Decrement # of chunks */ + /* (Don't bother reducing size of chunk array for now -QAK) */ + oh->nchunks--; + + /* + * Delete null message (in empty chunk that was be freed) from list of messages + */ + + /* Release any information/memory for message */ + H5O_free_mesg(null_msg); + + /* Remove null message from list of messages */ + if(null_msg_no < (oh->nmesgs - 1)) + HDmemmove(&oh->mesg[null_msg_no], &oh->mesg[null_msg_no + 1], ((oh->nmesgs - 1) - null_msg_no) * sizeof(H5O_mesg_t)); + + /* Decrement # of messages */ + /* (Don't bother reducing size of message array for now -QAK) */ + oh->nmesgs--; + + /* Adjust chunk # for messages in chunks after deleted chunk */ + for(u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++) { + HDassert(curr_msg->chunkno != deleted_chunkno); + if(curr_msg->chunkno > deleted_chunkno) + curr_msg->chunkno--; + } /* end for */ + + /* Found chunk to delete */ + deleted_chunk = TRUE; + break; + } /* end if */ + } /* end for */ + + /* If we deleted any chunks, remember that */ + if(deleted_chunk) + did_deleting = TRUE; + } while(deleted_chunk); + + /* Set return value */ + ret_value = did_deleting; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5O_remove_empty_chunks() */ + + +/*------------------------------------------------------------------------- + * + * Function: H5O_condense_header + * + * Purpose: Attempt to eliminate empty chunks from object header. + * + * Currently, this just examines a chunk to see if it's empty + * and removes it from the object header. It's possible that + * a more sophiticated algorithm would repack messages from + * one chunk to another. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Oct 4 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_condense_header(H5F_t *f, H5O_t *oh, hid_t dxpl_id) +{ + hbool_t rescan_header; /* Whether to rescan header */ + htri_t result; /* Result from packing/merging/etc */ + herr_t ret_value = SUCCEED; /* return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5O_condense_header) + + /* check args */ + HDassert(oh != NULL); + + /* Loop until no changed to the object header messages & chunks */ + do { + /* Reset 'rescan chunks' flag */ + rescan_header = FALSE; + + /* Scan for messages that can be moved earlier in chunks */ + result = H5O_move_msgs_forward(f, oh, dxpl_id); + if(result < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTPACK, FAIL, "can't move header messages forward") + if(result > 0) + rescan_header = TRUE; + + /* Scan for adjacent null messages & merge them */ + result = H5O_merge_null(f, oh); + if(result < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTPACK, FAIL, "can't pack null header messages") + if(result > 0) + rescan_header = TRUE; + + /* Scan for empty chunks to remove */ + result = H5O_remove_empty_chunks(f, oh, dxpl_id); + if(result < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTPACK, FAIL, "can't remove empty chunk") + if(result > 0) + rescan_header = TRUE; + } while(rescan_header); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5O_condense_header() */ + + +/*------------------------------------------------------------------------- + * * Function: H5O_alloc_extend_chunk * * Purpose: Attempt to extend a chunk that is allocated on disk. @@ -2993,9 +2965,8 @@ H5O_alloc_extend_chunk(H5F_t *f, HDassert(((H5O_cont_t *)(oh->mesg[u].native))->size == old_size); ((H5O_cont_t *)(oh->mesg[u].native))->size = oh->chunk[chunkno].size; - /* Flag continuation message & it's chunk as dirty */ + /* Flag continuation message as dirty */ oh->mesg[u].dirty = TRUE; - oh->chunk[oh->mesg[u].chunkno].dirty = TRUE; } /* end if */ } /* end for */ @@ -3031,17 +3002,6 @@ done: * matzke@llnl.gov * Aug 7 1997 * - * Modifications: - * - * John Mainzer, 8/17/05 - * Reworked function to allocate file space immediately, - * instead of just allocating core space (as it used to). - * This change was necessary, as we were allocating file - * space on metadata cache eviction, which need not be - * synchronized across all processes. As a result, - * different processes were allocating different file - * locations to the same chunk. - * *------------------------------------------------------------------------- */ static unsigned @@ -3051,8 +3011,10 @@ H5O_alloc_new_chunk(H5F_t *f, size_t size) { size_t cont_size; /*continuation message size */ - int found_null = (-1); /*best fit null message */ - int found_other = (-1); /*best fit other message */ + int found_null = (-1); /*best fit null message */ + int found_attr = (-1); /*best fit attribute message */ + int found_link = (-1); /*best fit link message */ + int found_other = (-1); /*best fit other message */ unsigned idx; /*message number */ uint8_t *p = NULL; /*ptr into new chunk */ H5O_cont_t *cont = NULL; /*native continuation message */ @@ -3061,11 +3023,11 @@ H5O_alloc_new_chunk(H5F_t *f, haddr_t new_chunk_addr; unsigned ret_value; /*return value */ - FUNC_ENTER_NOAPI_NOINIT(H5O_alloc_new_chunk); + FUNC_ENTER_NOAPI_NOINIT(H5O_alloc_new_chunk) /* check args */ - HDassert (oh); - HDassert (size > 0); + HDassert(oh); + HDassert(size > 0); size = H5O_ALIGN(size); /* @@ -3073,36 +3035,60 @@ H5O_alloc_new_chunk(H5F_t *f, * continuation message. Failing that, find the smallest message * that could be moved to make room for the continuation message. * Don't ever move continuation message from one chunk to another. + * Prioritize attribute and link messages moving to later chunks, + * instead of more "important" messages. */ cont_size = H5O_ALIGN (H5F_SIZEOF_ADDR(f) + H5F_SIZEOF_SIZE(f)); - for (u=0; u<oh->nmesgs; u++) { - if (H5O_NULL_ID == oh->mesg[u].type->id) { - if (cont_size == oh->mesg[u].raw_size) { - found_null = u; - break; - } else if (oh->mesg[u].raw_size >= cont_size && - (found_null < 0 || - (oh->mesg[u].raw_size < - oh->mesg[found_null].raw_size))) { - found_null = u; - } - } else if (H5O_CONT_ID == oh->mesg[u].type->id) { - /*don't consider continuation messages */ - } else if (oh->mesg[u].raw_size >= cont_size && + for(u = 0; u < oh->nmesgs; u++) { + int msg_id = oh->mesg[u].type->id; /* Temp. copy of message type ID */ + + if(H5O_NULL_ID == msg_id) { + if(cont_size == oh->mesg[u].raw_size) { + found_null = u; + break; + } else if(oh->mesg[u].raw_size >= cont_size && + (found_null < 0 || + oh->mesg[u].raw_size < oh->mesg[found_null].raw_size)) { + found_null = u; + } + } else if(H5O_CONT_ID == msg_id) { + /*don't consider continuation messages */ + } else if(H5O_ATTR_ID == msg_id) { + if(oh->mesg[u].raw_size >= cont_size && + (found_attr < 0 || + oh->mesg[u].raw_size < oh->mesg[found_attr].raw_size)) + found_attr = u; + } else if(H5O_LINK_ID == msg_id) { + if(oh->mesg[u].raw_size >= cont_size && + (found_link < 0 || + oh->mesg[u].raw_size < oh->mesg[found_link].raw_size)) + found_link = u; + } else { + if(oh->mesg[u].raw_size >= cont_size && (found_other < 0 || - oh->mesg[u].raw_size < oh->mesg[found_other].raw_size)) { - found_other = u; - } - } - assert(found_null >= 0 || found_other >= 0); + oh->mesg[u].raw_size < oh->mesg[found_other].raw_size)) + found_other = u; + } /* end else */ + } /* end for */ + HDassert(found_null >= 0 || found_attr >= 0 || found_link >= 0 || found_other >= 0); /* * If we must move some other message to make room for the null * message, then make sure the new chunk has enough room for that * other message. + * + * Move attributes first, then link messages, then other messages. + * */ - if (found_null < 0) + if(found_null < 0) { + if(found_attr >= 0) + found_other = found_attr; + else if(found_link >= 0) + found_other = found_link; + + HDassert(found_other >= 0); size += H5O_SIZEOF_MSGHDR(f) + oh->mesg[found_other].raw_size; + } /* end if */ /* * The total chunk size must include the requested space plus enough @@ -3110,7 +3096,7 @@ H5O_alloc_new_chunk(H5F_t *f, * multiple of the alignment size. */ size = MAX(H5O_MIN_SIZE, size + H5O_SIZEOF_MSGHDR(f)); - assert (size == H5O_ALIGN (size)); + HDassert(size == H5O_ALIGN (size)); /* allocate space in file to hold the new chunk */ new_chunk_addr = H5MF_alloc(f, H5FD_MEM_OHDR, dxpl_id, (hsize_t)size); @@ -3120,47 +3106,46 @@ H5O_alloc_new_chunk(H5F_t *f, /* * Create the new chunk giving it a file address. */ - if ( oh->nchunks >= oh->alloc_nchunks ) { - + if(oh->nchunks >= oh->alloc_nchunks) { unsigned na = oh->alloc_nchunks + H5O_NCHUNKS; H5O_chunk_t *x = H5FL_SEQ_REALLOC (H5O_chunk_t, oh->chunk, (size_t)na); - if (!x) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, "memory allocation failed"); + if(!x) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, "memory allocation failed") oh->alloc_nchunks = na; oh->chunk = x; - } + } /* end if */ chunkno = oh->nchunks++; oh->chunk[chunkno].dirty = TRUE; oh->chunk[chunkno].addr = new_chunk_addr; oh->chunk[chunkno].size = size; if (NULL==(oh->chunk[chunkno].image = p = H5FL_BLK_CALLOC(chunk_image,size))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, UFAIL, "memory allocation failed"); + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, "memory allocation failed") /* * Make sure we have enough space for all possible new messages * that could be generated below. */ - if (oh->nmesgs + 3 > oh->alloc_nmesgs) { - int old_alloc=oh->alloc_nmesgs; + if(oh->nmesgs + 3 > oh->alloc_nmesgs) { + int old_alloc = oh->alloc_nmesgs; unsigned na = oh->alloc_nmesgs + MAX (H5O_NMESGS, 3); H5O_mesg_t *x = H5FL_SEQ_REALLOC (H5O_mesg_t, oh->mesg, (size_t)na); - if (!x) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, UFAIL, "memory allocation failed"); + if(!x) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, "memory allocation failed") oh->alloc_nmesgs = na; oh->mesg = x; /* Set new object header info to zeros */ HDmemset(&oh->mesg[old_alloc], 0, (oh->alloc_nmesgs-old_alloc)*sizeof(H5O_mesg_t)); - } + } /* end if */ /* * Describe the messages of the new chunk. */ - if (found_null < 0) { + if(found_null < 0) { found_null = u = oh->nmesgs++; oh->mesg[u].type = H5O_NULL; oh->mesg[u].dirty = TRUE; @@ -3178,7 +3163,7 @@ H5O_alloc_new_chunk(H5F_t *f, oh->mesg[found_other].chunkno = chunkno; p += H5O_SIZEOF_MSGHDR(f) + oh->mesg[found_other].raw_size; size -= H5O_SIZEOF_MSGHDR(f) + oh->mesg[found_other].raw_size; - } + } /* end if */ idx = oh->nmesgs++; oh->mesg[idx].type = H5O_NULL; oh->mesg[idx].dirty = TRUE; @@ -3192,7 +3177,7 @@ H5O_alloc_new_chunk(H5F_t *f, * is larger than the continuation message, then split it into * two null messages. */ - if (oh->mesg[found_null].raw_size > cont_size) { + if(oh->mesg[found_null].raw_size > cont_size) { u = oh->nmesgs++; oh->mesg[u].type = H5O_NULL; oh->mesg[u].dirty = TRUE; @@ -3206,7 +3191,7 @@ H5O_alloc_new_chunk(H5F_t *f, oh->mesg[found_null].dirty = TRUE; oh->mesg[found_null].raw_size = cont_size; - } + } /* end if */ /* * Initialize the continuation message. @@ -3221,10 +3206,10 @@ H5O_alloc_new_chunk(H5F_t *f, oh->mesg[found_null].native = cont; /* Set return value */ - ret_value=idx; + ret_value = idx; done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5O_alloc_new_chunk() */ @@ -3241,23 +3226,6 @@ done: * matzke@llnl.gov * Aug 6 1997 * - * Modifications: - * - * John Mainzer, 6/7/05 - * Modified function to use the new dirtied parameter to - * H5AC_unprotect() instead of modfying the is_dirty field directly. - * In this case, that requires the addition of the oh_dirtied_ptr - * parameter to track whether *oh is dirty. - * - * John Mainzer, 8/19/05 - * Reworked the function to allocate disk space immediately instead - * of waiting to cache eviction time. This is necessary since cache - * evictions need not be synchronized across the processes in the - * PHDF5 case. - * - * Note the use of a revised versions of H5O_alloc_new_chunk() and - * H5O_alloc_extend_chunk(). - * *------------------------------------------------------------------------- */ static unsigned @@ -3268,25 +3236,24 @@ H5O_alloc(H5F_t *f, size_t size, unsigned * oh_flags_ptr) { - unsigned idx; H5O_mesg_t *msg; /* Pointer to newly allocated message */ size_t aligned_size = H5O_ALIGN(size); - htri_t tri_result; + unsigned idx; /* Index of message which fits allocation */ unsigned ret_value; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5O_alloc); + FUNC_ENTER_NOAPI_NOINIT(H5O_alloc) /* check args */ - HDassert (oh); - HDassert (type); - HDassert (oh_flags_ptr); + HDassert(oh); + HDassert(type); + HDassert(oh_flags_ptr); /* look for a null message which is large enough */ - for (idx = 0; idx < oh->nmesgs; idx++) { - if (H5O_NULL_ID == oh->mesg[idx].type->id && + for(idx = 0; idx < oh->nmesgs; idx++) { + if(H5O_NULL_ID == oh->mesg[idx].type->id && oh->mesg[idx].raw_size >= aligned_size) break; - } + } /* end for */ #ifdef LATER /* @@ -3299,7 +3266,7 @@ H5O_alloc(H5F_t *f, #endif /* if we didn't find one, then allocate more header space */ - if (idx >= oh->nmesgs) { + if(idx >= oh->nmesgs) { unsigned chunkno; /* check to see if we can extend one of the chunks. If we can, @@ -3308,62 +3275,56 @@ H5O_alloc(H5F_t *f, * Note that in this new version of this function, all chunks * must have file space allocated to them. */ - for (chunkno = 0; chunkno < oh->nchunks; chunkno++) { - HDassert( H5F_addr_defined(oh->chunk[chunkno].addr) ); - - tri_result = H5O_alloc_extend_chunk(f, oh, chunkno, size, &idx); + for(chunkno = 0; chunkno < oh->nchunks; chunkno++) { + htri_t tri_result; - if ( tri_result == TRUE ) { + HDassert(H5F_addr_defined(oh->chunk[chunkno].addr)); + tri_result = H5O_alloc_extend_chunk(f, oh, chunkno, size, &idx); + if(tri_result == TRUE) break; - - } else if ( tri_result == FALSE ) { - + else if(tri_result == FALSE) idx = UFAIL; - - } else { - - HGOTO_ERROR(H5E_OHDR, H5E_SYSTEM, UFAIL, \ - "H5O_alloc_extend_chunk failed unexpectedly"); - } - } + else + HGOTO_ERROR(H5E_OHDR, H5E_SYSTEM, UFAIL, "H5O_alloc_extend_chunk failed unexpectedly") + } /* end for */ /* if idx is still UFAIL, we were not able to extend a chunk. * Create a new one. */ - if(idx == UFAIL) { + if(idx == UFAIL) if((idx = H5O_alloc_new_chunk(f, dxpl_id, oh, size)) == UFAIL) HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, UFAIL, "unable to create a new object header data chunk") - } - } + } /* end if */ /* Set pointer to newly allocated message */ msg = &(oh->mesg[idx]); /* do we need to split the null message? */ - if (msg->raw_size > aligned_size) { + if(msg->raw_size > aligned_size) { H5O_mesg_t *null_msg; /* Pointer to null message */ - size_t mesg_size = aligned_size+ H5O_SIZEOF_MSGHDR(f); /* Total size of newly allocated message */ + size_t mesg_size = aligned_size + H5O_SIZEOF_MSGHDR(f); /* Total size of newly allocated message */ HDassert(msg->raw_size - aligned_size >= H5O_SIZEOF_MSGHDR(f)); - if (oh->nmesgs >= oh->alloc_nmesgs) { - int old_alloc=oh->alloc_nmesgs; + /* Check if we need to extend message table */ + if(oh->nmesgs >= oh->alloc_nmesgs) { + int old_alloc = oh->alloc_nmesgs; unsigned na = oh->alloc_nmesgs + H5O_NMESGS; H5O_mesg_t *x = H5FL_SEQ_REALLOC(H5O_mesg_t, oh->mesg, (size_t)na); - if (!x) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, UFAIL, "memory allocation failed"); - oh->alloc_nmesgs = na; - oh->mesg = x; + if(!x) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, "memory allocation failed") + oh->alloc_nmesgs = na; + oh->mesg = x; /* Set new object header info to zeros */ - HDmemset(&oh->mesg[old_alloc],0, + HDmemset(&oh->mesg[old_alloc], 0, (oh->alloc_nmesgs-old_alloc)*sizeof(H5O_mesg_t)); /* "Retarget" local 'msg' pointer into newly allocated array of messages */ - msg=&oh->mesg[idx]; - } + msg = &oh->mesg[idx]; + } /* end if */ null_msg = &(oh->mesg[oh->nmesgs++]); null_msg->type = H5O_NULL; null_msg->dirty = TRUE; @@ -3372,7 +3333,7 @@ H5O_alloc(H5F_t *f, null_msg->raw_size = msg->raw_size - mesg_size; null_msg->chunkno = msg->chunkno; msg->raw_size = aligned_size; - } + } /* end if */ /* initialize the new message */ msg->type = type; @@ -3385,7 +3346,7 @@ H5O_alloc(H5F_t *f, ret_value = idx; done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* H5O_alloc() */ #ifdef NOT_YET @@ -3427,9 +3388,9 @@ H5O_share (H5F_t *f, hid_t dxpl_id, const H5O_class_t *type, const void *mesg, if ((size = (type->raw_size)(f, mesg))>0) { if (NULL==(buf = H5MM_malloc (size))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - if ((type->encode)(f, buf, mesg)<0) + if ((type->encode)(f, buf, mesg) < 0) HGOTO_ERROR (H5E_OHDR, H5E_CANTENCODE, FAIL, "unable to encode message"); - if (H5HG_insert (f, dxpl_id, size, buf, hobj)<0) + if (H5HG_insert (f, dxpl_id, size, buf, hobj) < 0) HGOTO_ERROR (H5E_OHDR, H5E_CANTINIT, FAIL, "unable to store message in global heap"); } @@ -3454,8 +3415,6 @@ done: * koziol@ncsa.uiuc.edu * Feb 13 2003 * - * Modifications: - * *------------------------------------------------------------------------- */ size_t @@ -3467,7 +3426,7 @@ H5O_raw_size(unsigned type_id, const H5F_t *f, const void *mesg) FUNC_ENTER_NOAPI(H5O_raw_size,0) /* Check args */ - HDassert(type_id<NELMTS(message_type_g)); + HDassert(type_id < NELMTS(message_type_g)); type=message_type_g[type_id]; /* map the type ID to the actual type object */ HDassert(type); HDassert(type->raw_size); @@ -3506,7 +3465,7 @@ H5O_mesg_size(unsigned type_id, const H5F_t *f, const void *mesg) FUNC_ENTER_NOAPI(H5O_mesg_size,0) /* Check args */ - HDassert(type_id<NELMTS(message_type_g)); + HDassert(type_id < NELMTS(message_type_g)); type=message_type_g[type_id]; /* map the type ID to the actual type object */ HDassert(type); HDassert(type->raw_size); @@ -3553,23 +3512,23 @@ H5O_get_share(unsigned type_id, H5F_t *f, const void *mesg, H5O_shared_t *share) const H5O_class_t *type; /* Actual H5O class type for the ID */ herr_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5O_get_share,FAIL); + FUNC_ENTER_NOAPI(H5O_get_share,FAIL) /* Check args */ - assert(type_id<NELMTS(message_type_g)); - type=message_type_g[type_id]; /* map the type ID to the actual type object */ - assert (type); - assert (type->get_share); - assert (f); - assert (mesg); - assert (share); + HDassert(type_id < NELMTS(message_type_g)); + type = message_type_g[type_id]; /* map the type ID to the actual type object */ + HDassert(type); + HDassert(type->get_share); + HDassert(f); + HDassert(mesg); + HDassert(share); /* Compute the raw data size for the mesg */ - if ((ret_value = (type->get_share)(f, mesg, share))<0) - HGOTO_ERROR (H5E_OHDR, H5E_CANTGET, FAIL, "unable to retrieve shared message information"); + if((ret_value = (type->get_share)(f, mesg, share)) < 0) + HGOTO_ERROR (H5E_OHDR, H5E_CANTGET, FAIL, "unable to retrieve shared message information") done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_get_share() */ @@ -3587,36 +3546,33 @@ done: * koziol@ncsa.uiuc.edu * Mar 19 2003 * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t H5O_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr) { - H5O_t *oh=NULL; /* Object header information */ - herr_t ret_value=SUCCEED; /* Return value */ + H5O_t *oh = NULL; /* Object header information */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5O_delete,FAIL); + FUNC_ENTER_NOAPI(H5O_delete,FAIL) /* Check args */ - assert (f); - assert(H5F_addr_defined(addr)); + HDassert(f); + HDassert(H5F_addr_defined(addr)); /* Get the object header information */ - if (NULL == (oh = H5AC_protect(f, dxpl_id, H5AC_OHDR, addr, NULL, NULL, H5AC_WRITE))) - HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header"); + if(NULL == (oh = H5AC_protect(f, dxpl_id, H5AC_OHDR, addr, NULL, NULL, H5AC_WRITE))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header") /* Delete object */ - if(H5O_delete_oh(f,dxpl_id,oh)<0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't delete object from file"); + if(H5O_delete_oh(f, dxpl_id, oh) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't delete object from file") done: - if (oh && - H5AC_unprotect(f, dxpl_id, H5AC_OHDR, addr, oh, H5AC__DIRTIED_FLAG | H5C__DELETED_FLAG)<0) - HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header"); + if(oh && H5AC_unprotect(f, dxpl_id, H5AC_OHDR, addr, oh, H5AC__DIRTIED_FLAG | H5C__DELETED_FLAG) < 0) + HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header") - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_delete() */ @@ -3635,54 +3591,36 @@ done: * koziol@ncsa.uiuc.edu * Mar 19 2003 * - * Modifications: - * *------------------------------------------------------------------------- */ static herr_t H5O_delete_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh) { H5O_mesg_t *curr_msg; /* Pointer to current message being operated on */ - H5O_chunk_t *curr_chk; /* Pointer to current chunk being operated on */ unsigned u; - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5O_delete_oh); + FUNC_ENTER_NOAPI_NOINIT(H5O_delete_oh) /* Check args */ - assert (f); - assert (oh); + HDassert(f); + HDassert(oh); /* Walk through the list of object header messages, asking each one to * delete any file space used */ - for (u = 0, curr_msg=&oh->mesg[0]; u < oh->nmesgs; u++,curr_msg++) { + for(u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++) { /* Free any space referred to in the file from this message */ - if(H5O_delete_mesg(f, dxpl_id, curr_msg, TRUE)<0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete file space for object header message"); + if(H5O_delete_mesg(f, dxpl_id, curr_msg, TRUE) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete file space for object header message") } /* end for */ - /* Free all the chunks for the object header */ - for (u = 0, curr_chk=&oh->chunk[0]; u < oh->nchunks; u++,curr_chk++) { - haddr_t chk_addr; /* Actual address of chunk */ - hsize_t chk_size; /* Actual size of chunk */ - - if(u==0) { - chk_addr = curr_chk->addr - H5O_SIZEOF_HDR(f); - chk_size = curr_chk->size + H5O_SIZEOF_HDR(f); - } /* end if */ - else { - chk_addr = curr_chk->addr; - chk_size = curr_chk->size; - } /* end else */ - - /* Free the file space for the chunk */ - if (H5MF_xfree(f, H5FD_MEM_OHDR, dxpl_id, chk_addr, chk_size)<0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free object header"); - } /* end for */ + /* Free main (first) object header "chunk" */ + if(H5MF_xfree(f, H5FD_MEM_OHDR, dxpl_id, (oh->chunk[0].addr - H5O_SIZEOF_HDR(f)), (hsize_t)(oh->chunk[0].size + H5O_SIZEOF_HDR(f))) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free object header") done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_delete_oh() */ @@ -3699,8 +3637,6 @@ done: * koziol@ncsa.uiuc.edu * September 26 2003 * - * Modifications: - * *------------------------------------------------------------------------- */ static herr_t @@ -3709,15 +3645,15 @@ H5O_delete_mesg(H5F_t *f, hid_t dxpl_id, H5O_mesg_t *mesg, hbool_t adj_link) const H5O_class_t *type; /* Type of object to free */ herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5O_delete_mesg); + FUNC_ENTER_NOAPI_NOINIT(H5O_delete_mesg) /* Check args */ - assert (f); - assert (mesg); + HDassert(f); + HDassert(mesg); /* Get the message to free's type */ if(mesg->flags & H5O_FLAG_SHARED) - type=H5O_SHARED; + type = H5O_SHARED; else type = mesg->type; @@ -3726,19 +3662,19 @@ H5O_delete_mesg(H5F_t *f, hid_t dxpl_id, H5O_mesg_t *mesg, hbool_t adj_link) /* * Decode the message if necessary. */ - if (NULL == mesg->native) { - assert(type->decode); - mesg->native = (type->decode) (f, dxpl_id, mesg->raw, NULL); - if (NULL == mesg->native) - HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "unable to decode message"); + if(NULL == mesg->native) { + HDassert(type->decode); + mesg->native = (type->decode) (f, dxpl_id, mesg->raw); + if(NULL == mesg->native) + HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "unable to decode message") } /* end if */ - if ((type->del)(f, dxpl_id, mesg->native, adj_link)<0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete file space for object header message"); + if((type->del)(f, dxpl_id, mesg->native, adj_link) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete file space for object header message") } /* end if */ done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_delete_msg() */ @@ -3753,57 +3689,51 @@ done: * koziol@ncsa.uiuc.edu * Oct 7 2003 * - * Modifications: - * - * John Mainzer, 6/16/05 - * Modified function to use the new dirtied parameter to - * H5AC_unprotect() instead of modfying the is_dirty field. - * *------------------------------------------------------------------------- */ herr_t -H5O_get_info(H5G_entry_t *ent, H5O_stat_t *ostat, hid_t dxpl_id) +H5O_get_info(H5O_loc_t *loc, H5O_stat_t *ostat, hid_t dxpl_id) { - H5O_t *oh=NULL; /* Object header information */ + H5O_t *oh = NULL; /* Object header information */ H5O_mesg_t *curr_msg; /* Pointer to current message being operated on */ hsize_t total_size; /* Total amount of space used in file */ hsize_t free_space; /* Free space in object header */ unsigned u; /* Local index variable */ - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5O_get_info,FAIL); + FUNC_ENTER_NOAPI(H5O_get_info,FAIL) /* Check args */ - assert (ent); - assert (ostat); + HDassert(loc); + HDassert(ostat); /* Get the object header information */ - if (NULL == (oh = H5AC_protect(ent->file, dxpl_id, H5AC_OHDR, ent->header, NULL, NULL, H5AC_READ))) - HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header"); + if(NULL == (oh = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header") /* Iterate over all the messages, accumulating the total size & free space */ - total_size=H5O_SIZEOF_HDR(ent->file); - free_space=0; - for (u = 0, curr_msg=&oh->mesg[0]; u < oh->nmesgs; u++,curr_msg++) { + total_size = H5O_SIZEOF_HDR(loc->file); + free_space = 0; + for(u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++) { /* Accumulate the size for this message */ - total_size+= H5O_SIZEOF_MSGHDR(ent->file) + curr_msg->raw_size; + total_size += H5O_SIZEOF_MSGHDR(loc->file) + curr_msg->raw_size; /* Check for this message being free space */ - if (H5O_NULL_ID == curr_msg->type->id) - free_space+= H5O_SIZEOF_MSGHDR(ent->file) + curr_msg->raw_size; + if(H5O_NULL_ID == curr_msg->type->id) + free_space+= H5O_SIZEOF_MSGHDR(loc->file) + curr_msg->raw_size; } /* end for */ /* Set the information for this object header */ - ostat->size=total_size; - ostat->free=free_space; - ostat->nmesgs=oh->nmesgs; - ostat->nchunks=oh->nchunks; + ostat->size = total_size; + ostat->free = free_space; + ostat->nmesgs = oh->nmesgs; + ostat->nchunks = oh->nchunks; done: - if (oh && H5AC_unprotect(ent->file, dxpl_id, H5AC_OHDR, ent->header, oh, H5AC__NO_FLAGS_SET)<0) - HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header"); + if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header") - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_get_info() */ @@ -3834,12 +3764,12 @@ H5O_encode(H5F_t *f, unsigned char *buf, void *obj, unsigned type_id) FUNC_ENTER_NOAPI(H5O_encode,FAIL); /* check args */ - assert(type_id<NELMTS(message_type_g)); + assert(type_id < NELMTS(message_type_g)); type=message_type_g[type_id]; /* map the type ID to the actual type object */ assert(type); /* Encode */ - if ((type->encode)(f, buf, obj)<0) + if ((type->encode)(f, buf, obj) < 0) HGOTO_ERROR (H5E_OHDR, H5E_CANTENCODE, FAIL, "unable to encode message"); done: @@ -3874,12 +3804,12 @@ H5O_decode(H5F_t *f, const unsigned char *buf, unsigned type_id) FUNC_ENTER_NOAPI(H5O_decode,NULL); /* check args */ - assert(type_id<NELMTS(message_type_g)); + assert(type_id < NELMTS(message_type_g)); type=message_type_g[type_id]; /* map the type ID to the actual type object */ assert(type); /* decode */ - if((ret_value = (type->decode)(f, 0, buf, NULL))==NULL) + if((ret_value = (type->decode)(f, 0, buf))==NULL) HGOTO_ERROR (H5E_OHDR, H5E_CANTDECODE, NULL, "unable to decode message"); done: @@ -3925,24 +3855,24 @@ done: *------------------------------------------------------------------------- */ herr_t -H5O_iterate(const H5G_entry_t *ent, unsigned type_id, H5O_operator_t op, +H5O_iterate(const H5O_loc_t *loc, unsigned type_id, H5O_operator_t op, void *op_data, hid_t dxpl_id) { - const H5O_class_t *type; /* Actual H5O class type for the ID */ - herr_t ret_value=0; /* Return value */ + const H5O_class_t *type; /* Actual H5O class type for the ID */ + herr_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5O_iterate, FAIL) /* check args */ - HDassert(ent); - HDassert(ent->file); - HDassert(H5F_addr_defined(ent->header)); - HDassert(type_id<NELMTS(message_type_g)); - type=message_type_g[type_id]; /* map the type ID to the actual type object */ + HDassert(loc); + HDassert(loc->file); + HDassert(H5F_addr_defined(loc->addr)); + HDassert(type_id < NELMTS(message_type_g)); + type = message_type_g[type_id]; /* map the type ID to the actual type object */ HDassert(type); /* Call the "real" iterate routine */ - if((ret_value=H5O_iterate_real(ent, type, H5AC_READ, FALSE, (void *)op, op_data, dxpl_id))<0) + if((ret_value = H5O_iterate_real(loc, type, H5AC_READ, FALSE, (void *)op, op_data, dxpl_id)) < 0) HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "unable to iterate over object header messages") done: @@ -3984,49 +3914,37 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5O_iterate_real(const H5G_entry_t *ent, const H5O_class_t *type, H5AC_protect_t prot, +H5O_iterate_real(const H5O_loc_t *loc, const H5O_class_t *type, H5AC_protect_t prot, hbool_t internal, void *op, void *op_data, hid_t dxpl_id) { - H5O_t *oh=NULL; /* Pointer to actual object header */ + H5O_t *oh = NULL; /* Pointer to actual object header */ unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Start iteration with no flags set on object header */ unsigned idx; /* Absolute index of current message in all messages */ unsigned sequence; /* Relative index of current message for messages of type */ H5O_mesg_t *idx_msg; /* Pointer to current message */ - herr_t ret_value=0; /* Return value */ + herr_t ret_value = H5O_ITER_CONT; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_iterate_real) /* check args */ - HDassert(ent); - HDassert(ent->file); - HDassert(H5F_addr_defined(ent->header)); + HDassert(loc); + HDassert(loc->file); + HDassert(H5F_addr_defined(loc->addr)); HDassert(type); HDassert(op); /* Protect the object header to iterate over */ - if (NULL == (oh = H5AC_protect(ent->file, dxpl_id, H5AC_OHDR, ent->header, NULL, NULL, prot))) + if (NULL == (oh = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, prot))) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header"); /* Iterate over messages */ - for (sequence = 0, idx = 0, idx_msg = &oh->mesg[0]; idx < oh->nmesgs; idx++, idx_msg++) { - if (type->id == idx_msg->type->id) { + for(sequence = 0, idx = 0, idx_msg = &oh->mesg[0]; idx < oh->nmesgs && !ret_value; idx++, idx_msg++) { + if(type->id == idx_msg->type->id) { /* * Decode the message if necessary. If the message is shared then decode * a shared message, ignoring the message type. */ - if (NULL == idx_msg->native) { - const H5O_class_t *decode_type; - - if (idx_msg->flags & H5O_FLAG_SHARED) - decode_type = H5O_SHARED; - else - decode_type = type; - - /* Decode the message if necessary */ - HDassert(decode_type->decode); - if (NULL == (idx_msg->native = (decode_type->decode) (ent->file, dxpl_id, idx_msg->raw, NULL))) - HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "unable to decode message") - } /* end if */ + LOAD_NATIVE(loc->file, dxpl_id, idx_msg) /* Check for making an "internal" (i.e. within the H5O package) callback */ if(internal) { @@ -4040,27 +3958,155 @@ H5O_iterate_real(const H5G_entry_t *ent, const H5O_class_t *type, H5AC_protect_t break; } /* end else */ + /* Check for error from iterator */ + if(ret_value < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "iterator function failed") + /* Increment sequence value for message type */ sequence++; } /* end if */ } /* end for */ - /* Check if object header was modified */ - if(oh_flags & H5AC__DIRTIED_FLAG) { - /* Shouldn't be able to modify object header if we don't have write access */ - HDassert(prot == H5AC_WRITE); - H5O_touch_oh(ent->file, dxpl_id, oh, FALSE, &oh_flags); - } /* end if */ - done: - if (oh && H5AC_unprotect(ent->file, dxpl_id, H5AC_OHDR, ent->header, oh, oh_flags) < 0) - HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header") + if(oh) { + /* Check if object header was modified */ + if(oh_flags & H5AC__DIRTIED_FLAG) { + /* Shouldn't be able to modify object header if we don't have write access */ + HDassert(prot == H5AC_WRITE); + + /* Try to condense object header info */ + if(H5O_condense_header(loc->file, oh, dxpl_id) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTPACK, FAIL, "can't pack object header") + + H5O_touch_oh(loc->file, dxpl_id, oh, FALSE, &oh_flags); + } /* end if */ + + if(H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0) + HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header") + } /* end if */ FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_iterate_real() */ /*------------------------------------------------------------------------- + * Function: H5O_obj_type + * + * Purpose: Returns the type of object pointed to by `loc'. + * + * Return: Success: An object type defined in H5Gpublic.h + * Failure: H5G_UNKNOWN + * + * Programmer: Robb Matzke + * Wednesday, November 4, 1998 + * + *------------------------------------------------------------------------- + */ +H5G_obj_t +H5O_obj_type(H5O_loc_t *loc, hid_t dxpl_id) +{ + size_t i; /* Local index variable */ + H5G_obj_t ret_value = H5G_UNKNOWN; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_obj_type, H5G_UNKNOWN) + + /* Test whether entry qualifies as a particular type of object */ + /* (Note: loop is in reverse order, to test specific objects first) */ + for(i = H5O_ntypes_g; i > 0; --i) { + htri_t isa; /* Is entry a particular type? */ + + if((isa = (H5O_type_g[i-1].isa)(loc, dxpl_id)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, H5G_UNKNOWN, "unable to determine object type") + else if(isa) + HGOTO_DONE(H5O_type_g[i-1].type) + } /* end for */ + + if(0 == i) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, H5G_UNKNOWN, "unable to determine object type") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_obj_type() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_loc_reset + * + * Purpose: Reset a object location to an empty state + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Monday, September 19, 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_loc_reset(H5O_loc_t *loc) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_loc_reset) + + /* Check arguments */ + HDassert(loc); + + /* Clear the object location to an empty state */ + HDmemset(loc, 0, sizeof(H5O_loc_t)); + loc->addr = HADDR_UNDEF; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5O_loc_reset() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_loc_copy + * + * Purpose: Copy object location information + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Monday, September 19, 2005 + * + * Notes: 'depth' parameter determines how much of the group entry + * structure we want to copy. The values are: + * H5O_COPY_SHALLOW - Copy all the field values from the source + * to the destination, but not copying objects pointed to. + * (Destination "takes ownership" of objects pointed to) + * H5O_COPY_DEEP - Copy all the fields from the source to + * the destination, deep copying objects pointed to. + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_loc_copy(H5O_loc_t *dst, const H5O_loc_t *src, H5O_copy_depth_t depth) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_loc_copy) + + /* Check arguments */ + HDassert(src); + HDassert(dst); + HDassert(depth == H5O_COPY_SHALLOW || depth == H5O_COPY_DEEP); + + /* Copy the top level information */ + HDmemcpy(dst, src, sizeof(H5O_loc_t)); + + /* Deep copy the names */ + if(depth == H5G_COPY_DEEP) { + /* Nothing currently */ + ; + } else if(depth == H5G_COPY_SHALLOW) { + /* Discarding 'const' qualifier OK - QAK */ + H5O_loc_reset((H5O_loc_t *)src); + } /* end if */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5O_loc_copy() */ + + +/*------------------------------------------------------------------------- * Function: H5O_copy_mesg_file * * Purpose: Copies a message to file. If MESG is is the null pointer then a null @@ -4100,47 +4146,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5O_post_copy_mesg_file - * - * Purpose: Copies what's left to file after the object a meesage is copied. - * This function is need for situations like copying symbol tables. - * Copying a member of symbol table requires the parent object header - * exists in file. For this case, the first round of the message will - * create symbol table enttries but will not go deep copying member - * objects in the symbol table. The post copy will do that. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Peter Cao - * September 28, 2005 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5O_post_copy_mesg_file (const H5O_class_t *type, H5F_t *file_src, - const void *mesg_src, H5G_entry_t *loc_dst, - hid_t dxpl_id, H5SL_t *map_list) -{ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI_NOINIT(H5O_post_copy_mesg_file) - - /* check args */ - HDassert(type); - HDassert(file_src); - HDassert(mesg_src); - HDassert(loc_dst->file); - HDassert(map_list); - - if(type->post_copy_file && (type->post_copy_file)(file_src, mesg_src, loc_dst, dxpl_id, map_list) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to copy object header message to file") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5O_post_copy_mesg_file */ - - -/*------------------------------------------------------------------------- * Function: H5O_copy_header_real * * Purpose: copy header object from one location to another. @@ -4150,48 +4155,49 @@ done: * Programmer: Peter Cao * May 30, 2005 * - * Modifications: - * *------------------------------------------------------------------------- */ static herr_t -H5O_copy_header_real(const H5G_entry_t *ent_src, - H5G_entry_t *ent_dst /*out */, hid_t dxpl_id, H5SL_t *map_list) +H5O_copy_header_real(const H5O_loc_t *oloc_src, + H5O_loc_t *oloc_dst /*out */, hid_t dxpl_id, H5SL_t *map_list) { - H5O_addr_map_t *addr_map; /* Address mapping of object copied */ - uint8_t buf[16], *p; - H5O_t *oh = NULL; - unsigned chunkno = 0, mesgno = 0; - size_t chunk_size, hdr_size; - haddr_t addr_new; - H5O_mesg_t *mesg_src; - H5O_chunk_t *chunk; - herr_t ret_value = SUCCEED; + H5O_addr_map_t *addr_map = NULL; /* Address mapping of object copied */ + uint8_t buf[16], *p; + H5O_t *oh_src = NULL; /* Object header for source object */ + H5O_t *oh_dst = NULL; /* Object header for destination object */ + unsigned chunkno = 0, mesgno = 0; + size_t chunk_size, hdr_size; + haddr_t addr_new; + H5O_mesg_t *mesg_src; /* Message in source object header */ + H5O_mesg_t *mesg_dst; /* Message in source object header */ + H5O_chunk_t *chunk = NULL; + unsigned dst_oh_flags = H5AC__NO_FLAGS_SET; /* used to indicate whether destination header was modified */ + herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI_NOINIT(H5O_copy_header_real) - HDassert(ent_src); - HDassert(ent_src->file); - HDassert(H5F_addr_defined(ent_src->header)); - HDassert(ent_dst->file); + HDassert(oloc_src); + HDassert(oloc_src->file); + HDassert(H5F_addr_defined(oloc_src->addr)); + HDassert(oloc_dst->file); HDassert(map_list); - if(NULL == (oh = H5AC_protect(ent_src->file, dxpl_id, H5AC_OHDR, ent_src->header, NULL, NULL, H5AC_READ))) + if(NULL == (oh_src = H5AC_protect(oloc_src->file, dxpl_id, H5AC_OHDR, oloc_src->addr, NULL, NULL, H5AC_READ))) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header") /* get the size of the file header of the destination file */ - hdr_size = H5O_SIZEOF_HDR(ent_dst->file); + hdr_size = H5O_SIZEOF_HDR(oloc_dst->file); /* allocate memory space for the destitnation chunks */ - if(NULL == (chunk = H5FL_SEQ_MALLOC(H5O_chunk_t, (size_t)oh->nchunks))) + if(NULL == (chunk = H5FL_SEQ_MALLOC(H5O_chunk_t, (size_t)oh_src->nchunks))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") /* Allocate space for the first chunk */ - if(HADDR_UNDEF == (addr_new = H5MF_alloc(ent_dst->file, H5FD_MEM_OHDR, dxpl_id, (hsize_t)hdr_size + oh->chunk[0].size))) + if(HADDR_UNDEF == (addr_new = H5MF_alloc(oloc_dst->file, H5FD_MEM_OHDR, dxpl_id, (hsize_t)hdr_size + oh_src->chunk[0].size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for object header") /* Return the first chunk address */ - ent_dst->header = addr_new; + oloc_dst->addr = addr_new; /* Set chunk's address */ chunk[0].addr = addr_new + (hsize_t)hdr_size; @@ -4206,13 +4212,13 @@ H5O_copy_header_real(const H5G_entry_t *ent_src, *p++ = 0; /* encode number of messages */ - UINT16ENCODE(p, oh->nmesgs); + UINT16ENCODE(p, oh_src->nmesgs); /* encode link count (at zero initially) */ UINT32ENCODE(p, 0); /* encode body size */ - UINT32ENCODE(p, oh->chunk[0].size); + UINT32ENCODE(p, oh_src->chunk[0].size); /* zero to alignment */ HDmemset(p, 0, (size_t)(hdr_size-12)); @@ -4221,17 +4227,17 @@ H5O_copy_header_real(const H5G_entry_t *ent_src, because continuation chunk message will need to know the chunk address of address of continuation block. */ - for(chunkno = 1; chunkno < oh->nchunks; chunkno++) { - if(HADDR_UNDEF == (chunk[chunkno].addr = H5MF_alloc(ent_dst->file, H5FD_MEM_OHDR, dxpl_id, (hsize_t)oh->chunk[chunkno].size))) + for(chunkno = 1; chunkno < oh_src->nchunks; chunkno++) { + if(HADDR_UNDEF == (chunk[chunkno].addr = H5MF_alloc(oloc_dst->file, H5FD_MEM_OHDR, dxpl_id, (hsize_t)oh_src->chunk[chunkno].size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for object header") } /* end for */ /* Loop through chunks to copy chunk information */ - for(chunkno = 0; chunkno < oh->nchunks; chunkno++) { - chunk_size = oh->chunk[chunkno].size; + for(chunkno = 0; chunkno < oh_src->nchunks; chunkno++) { + chunk_size = oh_src->chunk[chunkno].size; /* copy chunk information */ - chunk[chunkno].dirty = oh->chunk[chunkno].dirty; + chunk[chunkno].dirty = oh_src->chunk[chunkno].dirty; chunk[chunkno].size = chunk_size; /* create memory image for the new chunk */ @@ -4242,13 +4248,13 @@ H5O_copy_header_real(const H5G_entry_t *ent_src, /* (This copies over all the messages which don't require special * callbacks to fix them up.) */ - HDmemcpy(chunk[chunkno].image, oh->chunk[chunkno].image, chunk_size); + HDmemcpy(chunk[chunkno].image, oh_src->chunk[chunkno].image, chunk_size); /* Loop through messages, to fix up any which refer to addresses in the source file, etc. */ - for(mesgno = 0; mesgno < oh->nmesgs; mesgno++) { + for(mesgno = 0; mesgno < oh_src->nmesgs; mesgno++) { const H5O_class_t *copy_type; - mesg_src = &(oh->mesg[mesgno]); + mesg_src = &(oh_src->mesg[mesgno]); /* check if the message belongs to this chunk */ if(mesg_src->chunkno != chunkno) @@ -4271,31 +4277,31 @@ H5O_copy_header_real(const H5G_entry_t *ent_src, if(NULL == mesg_src->native) { /* Decode the message if necessary */ HDassert(copy_type->decode); - if(NULL == (mesg_src->native = (copy_type->decode)(ent_src->file, dxpl_id, mesg_src->raw, NULL))) + if(NULL == (mesg_src->native = (copy_type->decode)(oloc_src->file, dxpl_id, mesg_src->raw))) HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "unable to decode a message") } /* end if (NULL == mesg_src->native) */ /* Copy the source message */ if(H5O_CONT_ID == copy_type->id) { - if((dst_native = H5O_copy_mesg_file(copy_type, ent_src->file, mesg_src->native, - ent_dst->file, dxpl_id, map_list, chunk)) == NULL) + if((dst_native = H5O_copy_mesg_file(copy_type, oloc_src->file, mesg_src->native, + oloc_dst->file, dxpl_id, map_list, chunk)) == NULL) HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object header message") } /* end if */ else { - if((dst_native = H5O_copy_mesg_file(copy_type, ent_src->file, mesg_src->native, - ent_dst->file, dxpl_id, map_list, NULL)) == NULL) + if((dst_native = H5O_copy_mesg_file(copy_type, oloc_src->file, mesg_src->native, + oloc_dst->file, dxpl_id, map_list, NULL)) == NULL) HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object header message") } /* end else */ /* Calculate address in destination raw chunk */ - p = chunk[chunkno].image + (mesg_src->raw - oh->chunk[chunkno].image); + p = chunk[chunkno].image + (mesg_src->raw - oh_src->chunk[chunkno].image); /* * Encode the message. If the message is shared then we * encode a Shared Object message instead of the object * which is being shared. */ - if((copy_type->encode)(ent_dst->file, p, dst_native) < 0) + if((copy_type->encode)(oloc_dst->file, p, dst_native) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "unable to encode object header message") /* Release native destination info */ @@ -4305,52 +4311,98 @@ H5O_copy_header_real(const H5G_entry_t *ent_src, /* Write the object header to the file if this is the first chunk */ if(chunkno == 0) - if(H5F_block_write(ent_dst->file, H5FD_MEM_OHDR, addr_new, hdr_size, dxpl_id, buf) < 0) + if(H5F_block_write(oloc_dst->file, H5FD_MEM_OHDR, addr_new, hdr_size, dxpl_id, buf) < 0) HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header hdr to disk") /* Write this chunk into disk */ - if(H5F_block_write(ent_dst->file, H5FD_MEM_OHDR, chunk[chunkno].addr, chunk[chunkno].size, dxpl_id, chunk[chunkno].image) < 0) + if(H5F_block_write(oloc_dst->file, H5FD_MEM_OHDR, chunk[chunkno].addr, chunk[chunkno].size, dxpl_id, chunk[chunkno].image) < 0) HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header data to disk") } /* end of chunkno loop */ + + /* Protect destination object header, so we can modify messages in it */ + if(NULL == (oh_dst = H5AC_protect(oloc_dst->file, dxpl_id, H5AC_OHDR, oloc_dst->addr, NULL, NULL, H5AC_WRITE))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header") + HDassert(oh_dst->nmesgs == oh_src->nmesgs); + /* Allocate space for the address mapping of the object copied */ if(NULL == (addr_map = H5FL_MALLOC(H5O_addr_map_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") /* Insert the address mapping for the new object into the copied list */ /* (Do this here, because "post copy" possibly checks it) */ - addr_map->src_addr = ent_src->header; - addr_map->dst_addr = ent_dst->header; + addr_map->src_addr = oloc_src->addr; + addr_map->dst_addr = oloc_dst->addr; + addr_map->is_locked = TRUE; /* We've locked the object currently */ + addr_map->inc_ref_count = 0; /* Start with no additional ref counts to add */ if(H5SL_insert(map_list, addr_map, &(addr_map->src_addr)) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert object into skip list") /* "post copy" loop over messages */ - for(mesgno = 0; mesgno < oh->nmesgs; mesgno++) { + for(mesgno = 0; mesgno < oh_src->nmesgs; mesgno++) { const H5O_class_t *copy_type; - mesg_src = &(oh->mesg[mesgno]); + mesg_src = &(oh_src->mesg[mesgno]); - if (mesg_src->flags & H5O_FLAG_SHARED) + if(mesg_src->flags & H5O_FLAG_SHARED) copy_type = H5O_SHARED; else copy_type = mesg_src->type; HDassert(copy_type); - if(mesg_src->native) { - if((H5O_post_copy_mesg_file(copy_type, ent_src->file, mesg_src->native, - ent_dst, dxpl_id, map_list)) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object header message") + if(copy_type->post_copy_file && mesg_src->native) { + hbool_t modified = FALSE; + + /* Get destination message */ + mesg_dst = &(oh_dst->mesg[mesgno]); + HDassert(mesg_dst->type == mesg_src->type); + + /* Make certain the destination's native info is available */ + LOAD_NATIVE(oloc_dst->file, dxpl_id, mesg_dst) + + /* Perform "post copy" operation on messge */ + if((copy_type->post_copy_file)(oloc_src->file, mesg_src->native, oloc_dst, mesg_dst->native, &modified, dxpl_id, map_list) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to perform 'post copy' operation on message") + + /* Mark message and header as dirty if the destination message was modified */ + if(modified) { + mesg_dst->dirty = TRUE; + dst_oh_flags |= H5AC__DIRTIED_FLAG; + } /* end if */ } /* end if */ } /* end for */ done: - /* Release pointer to object header itself */ - if(oh != NULL) { - for(chunkno = 0; chunkno < oh->nchunks; chunkno++) - H5FL_BLK_FREE(chunk_image, chunk[chunkno].image); - H5FL_SEQ_FREE(H5O_chunk_t, chunk); + /* Release pointer to source object header and it's derived objects */ + if(oh_src != NULL) { + /* Release all the chunks used to copy messages */ + if(chunk) { + for(chunkno = 0; chunkno < oh_src->nchunks; chunkno++) + H5FL_BLK_FREE(chunk_image, chunk[chunkno].image); + H5FL_SEQ_FREE(H5O_chunk_t, chunk); + } /* end if */ + + /* Unprotect the source object header */ + if(H5AC_unprotect(oloc_src->file, dxpl_id, H5AC_OHDR, oloc_src->addr, oh_src, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header") + } /* end if */ + + /* Release pointer to destination object header */ + if(oh_dst != NULL) { + /* Perform operations on address mapping for object, if it's in use */ + if(addr_map) { + /* Indicate that the destination address will no longer be locked */ + addr_map->is_locked = FALSE; + + /* Increment object header's reference count, if any descendents have created links to link to this object */ + if(addr_map->inc_ref_count) { + oh_dst->nlink += addr_map->inc_ref_count; + dst_oh_flags |= H5AC__DIRTIED_FLAG; + } /* end if */ + } /* end if */ - if(H5AC_unprotect(ent_src->file, dxpl_id, H5AC_OHDR, ent_src->header, oh, H5AC__NO_FLAGS_SET) < 0) + /* Unprotect the destination object header */ + if(H5AC_unprotect(oloc_dst->file, dxpl_id, H5AC_OHDR, oloc_dst->addr, oh_dst, dst_oh_flags) < 0) HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header") } /* end if */ @@ -4372,39 +4424,56 @@ done: *------------------------------------------------------------------------- */ herr_t -H5O_copy_header_map(const H5G_entry_t *ent_src, - H5G_entry_t *ent_dst /*out */, hid_t dxpl_id, H5SL_t *map_list) +H5O_copy_header_map(const H5O_loc_t *oloc_src, + H5O_loc_t *oloc_dst /*out */, hid_t dxpl_id, H5SL_t *map_list) { H5O_addr_map_t *addr_map; /* Address mapping of object copied */ + hbool_t inc_link; /* Whether to increment the link count for the object */ herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(H5O_copy_header_map, FAIL) /* Sanity check */ - HDassert(ent_src); - HDassert(ent_dst); - HDassert(ent_dst->file); + HDassert(oloc_src); + HDassert(oloc_dst); + HDassert(oloc_dst->file); HDassert(map_list); /* Look up the address of the object to copy in the skip list */ - addr_map = (H5O_addr_map_t *)H5SL_search(map_list, &(ent_src->header)); + addr_map = (H5O_addr_map_t *)H5SL_search(map_list, &(oloc_src->addr)); /* Check if address is already in list of objects copied */ if(addr_map == NULL) { /* Copy object for the first time */ /* Copy object referred to */ - if(H5O_copy_header_real(ent_src, ent_dst, dxpl_id, map_list) < 0) + if(H5O_copy_header_real(oloc_src, oloc_dst, dxpl_id, map_list) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object") + + /* When an object is copied for the first time, increment it's link */ + inc_link = TRUE; } /* end if */ else { /* Object has already been copied, set it's address in destination file */ - ent_dst->header = addr_map->dst_addr; + oloc_dst->addr = addr_map->dst_addr; + + /* If the object is locked currently (because we are copying a group + * hierarchy and this is a link to a group higher in the hierarchy), + * increment it's deferred reference count instead of incrementing the + * reference count now. + */ + if(addr_map->is_locked) { + addr_map->inc_ref_count++; + inc_link = FALSE; + } /* end if */ + else + inc_link = TRUE; } /* end else */ - /* Increment destination object's link count */ - if(H5O_link(ent_dst, 1, dxpl_id) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to increment object link count") + /* Increment destination object's link count, if allowed */ + if(inc_link) + if(H5O_link(oloc_dst, 1, dxpl_id) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to increment object link count") done: FUNC_LEAVE_NOAPI(ret_value) @@ -4457,25 +4526,24 @@ H5O_copy_free_addrmap_cb(void *item, void UNUSED *key, void UNUSED *op_data) *------------------------------------------------------------------------- */ herr_t -H5O_copy_header(const H5G_entry_t *ent_src, - H5G_entry_t *ent_dst /*out */, hid_t dxpl_id) +H5O_copy_header(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, hid_t dxpl_id) { - H5SL_t *map_list = NULL; /* Skip list to hold address mappings */ - herr_t ret_value = SUCCEED; + H5SL_t *map_list = NULL; /* Skip list to hold address mappings */ + herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(H5O_copy_header, FAIL) - HDassert(ent_src); - HDassert(ent_src->file); - HDassert(H5F_addr_defined(ent_src->header)); - HDassert(ent_dst->file); + HDassert(oloc_src); + HDassert(oloc_src->file); + HDassert(H5F_addr_defined(oloc_src->addr)); + HDassert(oloc_dst->file); /* Create a skip list to keep track of which objects are copied */ if((map_list = H5SL_create(H5SL_TYPE_HADDR, 0.5, 16)) == NULL) HGOTO_ERROR(H5E_SLIST, H5E_CANTCREATE, FAIL, "cannot make skip list") /* copy the object from the source file to the destination file */ - if(H5O_copy_header_real(ent_src, ent_dst, dxpl_id, map_list) < 0) + if(H5O_copy_header_real(oloc_src, oloc_dst, dxpl_id, map_list) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object") done: @@ -4511,7 +4579,7 @@ H5O_debug_id(hid_t type_id, H5F_t *f, hid_t dxpl_id, const void *mesg, FILE *str FUNC_ENTER_NOAPI(H5O_debug_id,FAIL); /* Check args */ - assert(type_id>=0 && type_id<(hid_t)(sizeof(message_type_g)/sizeof(message_type_g[0]))); + assert(type_id>=0 && type_id < (hid_t)(sizeof(message_type_g)/sizeof(message_type_g[0]))); type=message_type_g[type_id]; /* map the type ID to the actual type object */ assert(type); assert(type->debug); @@ -4522,7 +4590,7 @@ H5O_debug_id(hid_t type_id, H5F_t *f, hid_t dxpl_id, const void *mesg, FILE *str assert(fwidth >= 0); /* Call the debug method in the class */ - if ((ret_value = (type->debug)(f, dxpl_id, mesg, stream, indent, fwidth))<0) + if ((ret_value = (type->debug)(f, dxpl_id, mesg, stream, indent, fwidth)) < 0) HGOTO_ERROR (H5E_OHDR, H5E_BADTYPE, FAIL, "unable to debug message"); done: @@ -4531,7 +4599,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5O_debug + * Function: H5O_debug_real * * Purpose: Prints debugging info about an object header. * @@ -4541,38 +4609,28 @@ done: * matzke@llnl.gov * Aug 6 1997 * - * Modifications: - * Robb Matzke, 1999-07-28 - * The ADDR argument is passed by value. - * - * John Mainzer, 6/16/05 - * Modified function to use the new dirtied parameter to - * H5AC_unprotect() instead of modfying the is_dirty field. *------------------------------------------------------------------------- */ herr_t -H5O_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int fwidth) +H5O_debug_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, haddr_t addr, FILE *stream, int indent, int fwidth) { - H5O_t *oh = NULL; unsigned i, chunkno; size_t mesg_total = 0, chunk_total = 0; int *sequence; haddr_t tmp_addr; - herr_t ret_value = SUCCEED; - void *(*decode)(H5F_t*, hid_t, const uint8_t*, H5O_shared_t*); + void *(*decode)(H5F_t*, hid_t, const uint8_t*); herr_t (*debug)(H5F_t*, hid_t, const void*, FILE*, int, int)=NULL; + herr_t ret_value = SUCCEED; - FUNC_ENTER_NOAPI(H5O_debug, FAIL); + FUNC_ENTER_NOAPI(H5O_debug_real, FAIL) /* check args */ - assert(f); - assert(H5F_addr_defined(addr)); - assert(stream); - assert(indent >= 0); - assert(fwidth >= 0); - - if (NULL == (oh = H5AC_protect(f, dxpl_id, H5AC_OHDR, addr, NULL, NULL, H5AC_READ))) - HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header"); + HDassert(f); + HDassert(oh); + HDassert(H5F_addr_defined(addr)); + HDassert(stream); + HDassert(indent >= 0); + HDassert(fwidth >= 0); /* debug */ HDfprintf(stream, "%*sObject Header...\n", indent, ""); @@ -4597,7 +4655,7 @@ H5O_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int f (unsigned) (oh->nchunks), (unsigned) (oh->alloc_nchunks)); /* debug each chunk */ - for (i=0, chunk_total=0; i<oh->nchunks; i++) { + for (i=0, chunk_total=0; i < oh->nchunks; i++) { chunk_total += oh->chunk[i].size; HDfprintf(stream, "%*sChunk %d...\n", indent, "", i); @@ -4619,7 +4677,7 @@ H5O_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int f /* debug each message */ if (NULL==(sequence = H5MM_calloc(NELMTS(message_type_g)*sizeof(int)))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - for (i=0, mesg_total=0; i<oh->nmesgs; i++) { + for (i=0, mesg_total=0; i < oh->nmesgs; i++) { mesg_total += H5O_SIZEOF_MSGHDR(f) + oh->mesg[i].raw_size; HDfprintf(stream, "%*sMessage %d...\n", indent, "", i); @@ -4638,6 +4696,9 @@ H5O_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int f (unsigned) (oh->mesg[i].type->id), oh->mesg[i].type->name, sequence[oh->mesg[i].type->id]++); + HDfprintf (stream, "%*s%-*s %d\n", indent+3, "", MAX (0, fwidth-3), + "Dirty:", + (int)(oh->mesg[i].dirty)); HDfprintf (stream, "%*s%-*s %s\n", indent+3, "", MAX (0, fwidth-3), "Shared:", (oh->mesg[i].flags & H5O_FLAG_SHARED) ? "Yes" : "No"); @@ -4658,6 +4719,9 @@ H5O_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int f chunkno = oh->mesg[i].chunkno; if (chunkno >= oh->nchunks) HDfprintf(stream, "*** BAD CHUNK NUMBER\n"); + HDfprintf(stream, "%*s%-*s %u\n", indent + 3, "", MAX(0, fwidth - 3), + "Raw data offset in chunk:", + (unsigned) (oh->mesg[i].raw - oh->chunk[chunkno].image)); /* check the size */ if ((oh->mesg[i].raw + oh->mesg[i].raw_size > @@ -4675,7 +4739,7 @@ H5O_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int f debug = oh->mesg[i].type->debug; } if (NULL==oh->mesg[i].native && decode) - oh->mesg[i].native = (decode)(f, dxpl_id, oh->mesg[i].raw, NULL); + oh->mesg[i].native = (decode)(f, dxpl_id, oh->mesg[i].raw); if (NULL==oh->mesg[i].native) debug = NULL; @@ -4692,17 +4756,9 @@ H5O_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int f H5O_shared_t *shared = (H5O_shared_t*)(oh->mesg[i].native); void *mesg = NULL; - if (shared->in_gh) { - void *p = H5HG_read (f, dxpl_id, oh->mesg[i].native, NULL); - mesg = (oh->mesg[i].type->decode)(f, dxpl_id, p, oh->mesg[i].native); - H5MM_xfree (p); - } else { - mesg = H5O_read_real(&(shared->u.ent), oh->mesg[i].type, 0, NULL, dxpl_id); - } - if (oh->mesg[i].type->debug) { - (oh->mesg[i].type->debug)(f, dxpl_id, mesg, stream, indent+3, - MAX (0, fwidth-3)); - } + mesg = H5O_read_real(&(shared->oloc), oh->mesg[i].type, 0, NULL, dxpl_id); + if (oh->mesg[i].type->debug) + (oh->mesg[i].type->debug)(f, dxpl_id, mesg, stream, indent+3, MAX (0, fwidth-3)); H5O_free_real(oh->mesg[i].type, mesg); } } @@ -4712,8 +4768,48 @@ H5O_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int f HDfprintf(stream, "*** TOTAL SIZE DOES NOT MATCH ALLOCATED SIZE!\n"); done: - if (oh && H5AC_unprotect(f, dxpl_id, H5AC_OHDR, addr, oh, H5AC__NO_FLAGS_SET) < 0) - HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header"); + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_debug_real() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_debug + * + * Purpose: Prints debugging info about an object header. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 6 1997 + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int fwidth) +{ + H5O_t *oh = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(H5O_debug, FAIL) + + /* check args */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(stream); + HDassert(indent >= 0); + HDassert(fwidth >= 0); + + if(NULL == (oh = H5AC_protect(f, dxpl_id, H5AC_OHDR, addr, NULL, NULL, H5AC_READ))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header") + + /* debug */ + H5O_debug_real(f, dxpl_id, oh, addr, stream, indent, fwidth); + +done: + if(oh && H5AC_unprotect(f, dxpl_id, H5AC_OHDR, addr, oh, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_debug() */ - FUNC_LEAVE_NOAPI(ret_value); -} diff --git a/src/H5Oattr.c b/src/H5Oattr.c index 9ac5570..4d97b12 100644 --- a/src/H5Oattr.c +++ b/src/H5Oattr.c @@ -28,7 +28,7 @@ /* PRIVATE PROTOTYPES */ static herr_t H5O_attr_encode (H5F_t *f, uint8_t *p, const void *mesg); -static void *H5O_attr_decode (H5F_t *f, hid_t dxpl_id, const uint8_t *p, H5O_shared_t *sh); +static void *H5O_attr_decode (H5F_t *f, hid_t dxpl_id, const uint8_t *p); static void *H5O_attr_copy (const void *_mesg, void *_dest, unsigned update_flags); static size_t H5O_attr_size (const H5F_t *f, const void *_mesg); static herr_t H5O_attr_reset (void *_mesg); @@ -105,7 +105,7 @@ H5FL_EXTERN(H5S_extent_t); * --------------------------------------------------------------------------*/ static void * -H5O_attr_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p, H5O_shared_t UNUSED *sh) +H5O_attr_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p) { H5A_t *attr = NULL; H5S_extent_t *extent; /*extent dimensionality information */ @@ -155,7 +155,7 @@ H5O_attr_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p, H5O_shared_t UNUSED * H5O_shared_t *shared; /* Shared information */ /* Get the shared information */ - if (NULL == (shared = (H5O_SHARED->decode) (f, dxpl_id, p, NULL))) + if (NULL == (shared = (H5O_SHARED->decode) (f, dxpl_id, p))) HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, NULL, "unable to decode shared message"); /* Get the actual datatype information */ @@ -166,7 +166,7 @@ H5O_attr_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p, H5O_shared_t UNUSED * H5O_free_real(H5O_SHARED, shared); } /* end if */ else { - if((attr->dt=(H5O_DTYPE->decode)(f,dxpl_id,p,NULL))==NULL) + if((attr->dt=(H5O_DTYPE->decode)(f,dxpl_id,p))==NULL) HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, NULL, "can't decode attribute datatype"); } /* end else */ if(version < H5O_ATTR_VERSION_NEW) @@ -178,7 +178,7 @@ H5O_attr_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p, H5O_shared_t UNUSED * if (NULL==(attr->ds = H5FL_CALLOC(H5S_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - if((extent=(H5O_SDSPACE->decode)(f,dxpl_id,p,NULL))==NULL) + if((extent=(H5O_SDSPACE->decode)(f,dxpl_id,p))==NULL) HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, NULL, "can't decode attribute dataspace"); /* Copy the extent information */ @@ -629,9 +629,10 @@ H5O_attr_copy_file(H5F_t UNUSED *file_src, void *native_src, /* Copy the top level of the attribute */ *attr_dst = *attr_src; - /* Don't have an opened group entry for copy */ - H5G_ent_reset(&(attr_dst->ent)); - attr_dst->ent_opened = 0; + /* Don't have an opened group location for copy */ + H5O_loc_reset(&(attr_dst->oloc)); + H5G_name_reset(&(attr_dst->path)); + attr_dst->obj_opened = 0; /* Copy attribute's name */ attr_dst->name = H5MM_strdup(attr_src->name); @@ -642,21 +643,21 @@ H5O_attr_copy_file(H5F_t UNUSED *file_src, void *native_src, /* Check for named datatype being copied */ if(H5T_committed(attr_src->dt)) { - H5G_entry_t *ent_src; /* Pointer to source datatype's group entry */ - H5G_entry_t *ent_dst; /* Pointer to dest. datatype's group entry */ + H5O_loc_t *src_oloc; /* Pointer to source datatype's object location */ + H5O_loc_t *dst_oloc; /* Pointer to dest. datatype's object location */ /* Get group entries for source & destination */ - ent_src = H5T_entof(attr_src->dt); - HDassert(ent_src); - ent_dst = H5T_entof(attr_dst->dt); - HDassert(ent_dst); + src_oloc = H5T_oloc(attr_src->dt); + HDassert(src_oloc); + dst_oloc = H5T_oloc(attr_dst->dt); + HDassert(dst_oloc); - /* Reset group entry for new object */ - H5G_ent_reset(ent_dst); - ent_dst->file = file_dst; + /* Reset object location for new object */ + H5O_loc_reset(dst_oloc); + dst_oloc->file = file_dst; /* Copy the shared object from source to destination */ - if(H5O_copy_header_map(ent_src, ent_dst, dxpl_id, map_list) < 0) + if(H5O_copy_header_map(src_oloc, dst_oloc, dxpl_id, map_list) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy object") } /* end if */ @@ -725,11 +726,11 @@ H5O_attr_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int in "Initialized:", (unsigned int)mesg->initialized); fprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, - "Opened:", - (unsigned int)mesg->ent_opened); - fprintf(stream, "%*sSymbol table entry...\n", indent, ""); - H5G_ent_debug(f, dxpl_id, &(mesg->ent), stream, indent+3, MAX(0, fwidth-3), - HADDR_UNDEF); + "Object opened:", + (unsigned int)mesg->obj_opened); + HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth, + "Object:", + mesg->oloc.addr); fprintf(stream, "%*sData type...\n", indent, ""); fprintf(stream, "%*s%-*s %lu\n", indent+3, "", MAX(0,fwidth-3), diff --git a/src/H5Obogus.c b/src/H5Obogus.c index 7296860..7596ae2 100644 --- a/src/H5Obogus.c +++ b/src/H5Obogus.c @@ -39,7 +39,7 @@ #ifdef H5O_ENABLE_BOGUS /* PRIVATE PROTOTYPES */ -static void *H5O_bogus_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p, H5O_shared_t *sh); +static void *H5O_bogus_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p); static herr_t H5O_bogus_encode(H5F_t *f, uint8_t *p, const void *_mesg); static size_t H5O_bogus_size(const H5F_t *f, const void *_mesg); static herr_t H5O_bogus_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, @@ -85,8 +85,7 @@ const H5O_class_t H5O_BOGUS[1] = {{ *------------------------------------------------------------------------- */ static void * -H5O_bogus_decode(H5F_t UNUSED *f, hid_t dxpl_id, const uint8_t *p, - H5O_shared_t UNUSED *sh) +H5O_bogus_decode(H5F_t UNUSED *f, hid_t dxpl_id, const uint8_t *p) { H5O_bogus_t *mesg=NULL; void *ret_value; /* Return value */ @@ -96,7 +95,6 @@ H5O_bogus_decode(H5F_t UNUSED *f, hid_t dxpl_id, const uint8_t *p, /* check args */ assert(f); assert(p); - assert(!sh); /* Allocate the bogus message */ if (NULL==(mesg = H5MM_calloc(sizeof(H5O_bogus_t)))) diff --git a/src/H5Ocache.c b/src/H5Ocache.c new file mode 100644 index 0000000..e5e20e4 --- /dev/null +++ b/src/H5Ocache.c @@ -0,0 +1,554 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5Ocache.c + * Sep 28 2005 + * Quincey Koziol <koziol@ncsa.uiuc.edu> + * + * Purpose: Object header metadata cache virtual functions. + * + *------------------------------------------------------------------------- + */ + +#define H5O_PACKAGE /*suppress error about including H5Opkg */ + +/* Interface initialization */ +#define H5_INTERFACE_INIT_FUNC H5O_cache_init_interface + + +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5FLprivate.h" /* Free lists */ +#include "H5Opkg.h" /* Object headers */ + +/* Private typedefs */ + +/* PRIVATE PROTOTYPES */ + +/* Metadata cache callbacks */ +static H5O_t *H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_udata1, + void *_udata2); +static herr_t H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5O_t *oh); +static herr_t H5O_clear(H5F_t *f, H5O_t *oh, hbool_t destroy); +static herr_t H5O_compute_size(const H5F_t *f, const H5O_t *oh, size_t *size_ptr); + +/* H5O inherits cache-like properties from H5AC */ +const H5AC_class_t H5AC_OHDR[1] = {{ + H5AC_OHDR_ID, + (H5AC_load_func_t)H5O_load, + (H5AC_flush_func_t)H5O_flush, + (H5AC_dest_func_t)H5O_dest, + (H5AC_clear_func_t)H5O_clear, + (H5AC_size_func_t)H5O_compute_size, +}}; + + +/*------------------------------------------------------------------------- + * Function: H5O_cache_init_interface + * + * Purpose: Initialize the H5O interface. (Just calls + * H5O_init_iterface currently). + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Wednesday, September 28, 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_cache_init_interface(void) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_cache_init_interface) + + FUNC_LEAVE_NOAPI(H5O_init()) +} /* end H5O_cache_init_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_load + * + * Purpose: Loads an object header from disk. + * + * Return: Success: Pointer to the new object header. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 5 1997 + * + *------------------------------------------------------------------------- + */ +static H5O_t * +H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1, + void UNUSED * _udata2) +{ + H5O_t *oh = NULL; + H5O_t *ret_value; + uint8_t buf[16], *p; + size_t mesg_size; + size_t hdr_size; + unsigned id; + int mesgno; + unsigned curmesg = 0, nmesgs; + unsigned chunkno; + unsigned skipped_msgs = 0; /* Number of unknown messages skipped */ + unsigned merged_null_msgs = 0; /* Number of null messages merged together */ + haddr_t chunk_addr; + size_t chunk_size; + uint8_t flags; + + FUNC_ENTER_NOAPI(H5O_load, NULL) + + /* check args */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(!_udata1); + HDassert(!_udata2); + + /* allocate ohdr and init chunk list */ + if (NULL==(oh = H5FL_CALLOC(H5O_t))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + + /* read fixed-lenth part of object header */ + hdr_size = H5O_SIZEOF_HDR(f); + assert(hdr_size<=sizeof(buf)); + if (H5F_block_read(f, H5FD_MEM_OHDR, addr, hdr_size, dxpl_id, buf) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header"); + p = buf; + + /* decode version */ + oh->version = *p++; + if (H5O_VERSION != oh->version) + HGOTO_ERROR(H5E_OHDR, H5E_VERSION, NULL, "bad object header version number"); + + /* reserved */ + p++; + + /* decode number of messages */ + UINT16DECODE(p, nmesgs); + + /* decode link count */ + UINT32DECODE(p, oh->nlink); + + /* decode first chunk info */ + chunk_addr = addr + (hsize_t)hdr_size; + UINT32DECODE(p, chunk_size); + + /* build the message array */ + oh->alloc_nmesgs = MAX(H5O_NMESGS, nmesgs); + if (NULL==(oh->mesg=H5FL_SEQ_CALLOC(H5O_mesg_t,(size_t)oh->alloc_nmesgs))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + + /* read each chunk from disk */ + while(H5F_addr_defined(chunk_addr)) { + /* increase chunk array size */ + if(oh->nchunks >= oh->alloc_nchunks) { + unsigned na = oh->alloc_nchunks + H5O_NCHUNKS; + H5O_chunk_t *x = H5FL_SEQ_REALLOC (H5O_chunk_t, oh->chunk, (size_t)na); + + if(!x) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + oh->alloc_nchunks = na; + oh->chunk = x; + } /* end if */ + + /* read the chunk raw data */ + chunkno = oh->nchunks++; + oh->chunk[chunkno].dirty = FALSE; + oh->chunk[chunkno].addr = chunk_addr; + oh->chunk[chunkno].size = chunk_size; + if(NULL==(oh->chunk[chunkno].image = H5FL_BLK_MALLOC(chunk_image, chunk_size))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + if(H5F_block_read(f, H5FD_MEM_OHDR, chunk_addr, chunk_size, dxpl_id, oh->chunk[chunkno].image) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read object header data"); + + /* load messages from this chunk */ + for(p = oh->chunk[chunkno].image; p < oh->chunk[chunkno].image + chunk_size; p += mesg_size) { + UINT16DECODE(p, id); + UINT16DECODE(p, mesg_size); + HDassert(mesg_size==H5O_ALIGN (mesg_size)); + flags = *p++; + p += 3; /*reserved*/ + + /* Try to detect invalidly formatted object header messages */ + if(p + mesg_size > oh->chunk[chunkno].image + chunk_size) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "corrupt object header") + + /* Skip header messages we don't know about */ + /* (Usually from future versions of the library */ + if(id >= NELMTS(message_type_g) || NULL == message_type_g[id]) { + skipped_msgs++; + continue; + } /* end if */ + + if(H5O_NULL_ID == id && oh->nmesgs > 0 && + H5O_NULL_ID == oh->mesg[oh->nmesgs - 1].type->id && + oh->mesg[oh->nmesgs - 1].chunkno == chunkno) { + /* combine adjacent null messages */ + mesgno = oh->nmesgs - 1; + oh->mesg[mesgno].raw_size += H5O_SIZEOF_MSGHDR(f) + mesg_size; + merged_null_msgs++; + } else { + /* new message */ + if (oh->nmesgs >= nmesgs) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "corrupt object header - too many messages"); + mesgno = oh->nmesgs++; + oh->mesg[mesgno].type = message_type_g[id]; + oh->mesg[mesgno].dirty = FALSE; + oh->mesg[mesgno].flags = flags; + oh->mesg[mesgno].native = NULL; + oh->mesg[mesgno].raw = p; + oh->mesg[mesgno].raw_size = mesg_size; + oh->mesg[mesgno].chunkno = chunkno; + } /* end else */ + } /* end for */ + + HDassert(p == oh->chunk[chunkno].image + chunk_size); + + /* decode next object header continuation message */ + for(chunk_addr = HADDR_UNDEF; !H5F_addr_defined(chunk_addr) && curmesg < oh->nmesgs; ++curmesg) { + if(H5O_CONT_ID == oh->mesg[curmesg].type->id) { + H5O_cont_t *cont; + + cont = (H5O_CONT->decode) (f, dxpl_id, oh->mesg[curmesg].raw); + oh->mesg[curmesg].native = cont; + chunk_addr = cont->addr; + chunk_size = cont->size; + cont->chunkno = oh->nchunks; /*the next chunk to allocate */ + } /* end if */ + } /* end for */ + } /* end while */ + + /* Sanity check for the correct # of messages in object header */ + if((oh->nmesgs + skipped_msgs + merged_null_msgs) != nmesgs) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "corrupt object header - too few messages") + + /* Set return value */ + ret_value = oh; + +done: + if(!ret_value && oh) { + if(H5O_dest(f,oh) < 0) + HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, NULL, "unable to destroy object header data") + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_load() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_flush + * + * Purpose: Flushes (and destroys) an object header. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 5 1997 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5O_t *oh) +{ + uint8_t buf[16], *p; + int id; + H5O_mesg_t *curr_msg; /* Pointer to current message being operated on */ + herr_t (*encode)(H5F_t*, uint8_t*, const void*) = NULL; + unsigned combine = 0; /* Whether to combine the object header prefix & the first chunk */ + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_flush, FAIL) + + /* check args */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(oh); + + /* flush */ + if(oh->cache_info.is_dirty) { + /* Encode any dirty messages */ + for(u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++) { + if(curr_msg->dirty) { + p = curr_msg->raw - H5O_SIZEOF_MSGHDR(f); + + id = curr_msg->type->id; + UINT16ENCODE(p, id); + HDassert(curr_msg->raw_size < H5O_MAX_SIZE); + UINT16ENCODE(p, curr_msg->raw_size); + *p++ = curr_msg->flags; + *p++ = 0; /*reserved*/ + *p++ = 0; /*reserved*/ + *p++ = 0; /*reserved*/ + + if(curr_msg->native) { + HDassert(curr_msg->type->encode); + + /* allocate file space for chunks that have none yet */ + if(H5O_CONT_ID == curr_msg->type->id && !H5F_addr_defined(((H5O_cont_t *)(curr_msg->native))->addr)) + /* We now allocate disk space on insertion, instead + * of on flush from the cache, so this case is now an + * error. -- JRM + */ + HGOTO_ERROR(H5E_OHDR, H5E_SYSTEM, FAIL, "File space for message not allocated!?!") + + /* + * Encode the message. If the message is shared then we + * encode a Shared Object message instead of the object + * which is being shared. + */ + HDassert(curr_msg->raw >= oh->chunk[curr_msg->chunkno].image); + HDassert(curr_msg->raw_size == H5O_ALIGN (curr_msg->raw_size)); + HDassert(curr_msg->raw + curr_msg->raw_size <= + oh->chunk[curr_msg->chunkno].image + oh->chunk[curr_msg->chunkno].size); + if(curr_msg->flags & H5O_FLAG_SHARED) + encode = H5O_SHARED->encode; + else + encode = curr_msg->type->encode; + if((encode)(f, curr_msg->raw, curr_msg->native) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "unable to encode object header message") + } /* end if */ + curr_msg->dirty = FALSE; + oh->chunk[curr_msg->chunkno].dirty = TRUE; + } /* end if */ + } /* end for */ + + /* Sanity check for the correct # of messages in object header */ + if(oh->nmesgs != u) + HGOTO_ERROR(H5E_OHDR, H5E_CANTFLUSH, FAIL, "corrupt object header - too few messages") + + /* Encode header prefix */ + p = buf; + + /* encode version */ + *p++ = oh->version; + + /* reserved */ + *p++ = 0; + + /* encode number of messages */ + UINT16ENCODE(p, oh->nmesgs); + + /* encode link count */ + UINT32ENCODE(p, oh->nlink); + + /* encode body size */ + UINT32ENCODE(p, oh->chunk[0].size); + + /* zero to alignment */ + HDmemset (p, 0, (size_t)(H5O_SIZEOF_HDR(f)-12)); + + /* write the object header prefix */ + + /* Check if we can combine the object header prefix & the first chunk into one I/O operation */ + if(oh->chunk[0].dirty && (addr + H5O_SIZEOF_HDR(f)) == oh->chunk[0].addr) { + combine = 1; + } /* end if */ + else { + if(H5F_block_write(f, H5FD_MEM_OHDR, addr, (size_t)H5O_SIZEOF_HDR(f), dxpl_id, buf) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header hdr to disk") + } /* end else */ + + /* write each chunk to disk */ + for(u = 0; u < oh->nchunks; u++) { + if(oh->chunk[u].dirty) { + HDassert(H5F_addr_defined(oh->chunk[u].addr)); + if(u == 0 && combine) { + /* Allocate space for the combined prefix and first chunk */ + if((p = H5FL_BLK_MALLOC(chunk_image,(H5O_SIZEOF_HDR(f)+oh->chunk[u].size))) == NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Copy in the prefix */ + HDmemcpy(p, buf, (size_t)H5O_SIZEOF_HDR(f)); + + /* Copy in the first chunk */ + HDmemcpy(p + H5O_SIZEOF_HDR(f), oh->chunk[u].image, oh->chunk[u].size); + + /* Write the combined prefix/chunk out */ + if(H5F_block_write(f, H5FD_MEM_OHDR, addr, + (H5O_SIZEOF_HDR(f) + oh->chunk[u].size), dxpl_id, p) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header data to disk") + + /* Release the memory for the combined prefix/chunk */ + p = H5FL_BLK_FREE(chunk_image,p); + } /* end if */ + else { + if(H5F_block_write(f, H5FD_MEM_OHDR, oh->chunk[u].addr, + (oh->chunk[u].size), dxpl_id, oh->chunk[u].image) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header data to disk") + } /* end else */ + oh->chunk[u].dirty = FALSE; + } /* end if */ + } /* end for */ + oh->cache_info.is_dirty = FALSE; + } /* end if */ + + if (destroy) { + if(H5O_dest(f,oh) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy object header data") + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_flush() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_dest + * + * Purpose: Destroys an object header. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Jan 15 2003 + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_dest(H5F_t UNUSED *f, H5O_t *oh) +{ + unsigned i; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_dest); + + /* check args */ + assert(oh); + + /* Verify that node is clean */ + assert (oh->cache_info.is_dirty==FALSE); + + /* destroy chunks */ + for (i = 0; i < oh->nchunks; i++) { + /* Verify that chunk is clean */ + assert (oh->chunk[i].dirty==0); + + oh->chunk[i].image = H5FL_BLK_FREE(chunk_image,oh->chunk[i].image); + } + if(oh->chunk) + oh->chunk = H5FL_SEQ_FREE(H5O_chunk_t,oh->chunk); + + /* destroy messages */ + for (i = 0; i < oh->nmesgs; i++) { + /* Verify that message is clean */ + assert (oh->mesg[i].dirty==0); + + H5O_free_mesg(&oh->mesg[i]); + } + if(oh->mesg) + oh->mesg = H5FL_SEQ_FREE(H5O_mesg_t,oh->mesg); + + /* destroy object header */ + H5FL_FREE(H5O_t,oh); + + FUNC_LEAVE_NOAPI(SUCCEED); +} /* end H5O_dest() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_clear + * + * Purpose: Mark a object header in memory as non-dirty. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 20 2003 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_clear(H5F_t *f, H5O_t *oh, hbool_t destroy) +{ + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT(H5O_clear); + + /* check args */ + assert(oh); + + /* Mark chunks as clean */ + for (u = 0; u < oh->nchunks; u++) + oh->chunk[u].dirty=FALSE; + + /* Mark messages as clean */ + for (u = 0; u < oh->nmesgs; u++) + oh->mesg[u].dirty=FALSE; + + /* Mark whole header as clean */ + oh->cache_info.is_dirty=FALSE; + + if (destroy) + if (H5O_dest(f, oh) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy object header data"); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5O_clear() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_compute_size + * + * Purpose: Compute the size in bytes of the specified instance of + * H5O_t on disk, and return it in *len_ptr. On failure, + * the value of *len_ptr is undefined. + * + * The value returned will probably be low unless the object + * has just been flushed, as we simply total up the size of + * the header with the sizes of the chunks. Thus any message + * that has been added since the last flush will not be + * reflected in the total. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: John Mainzer + * 5/13/04 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_compute_size(const H5F_t *f, const H5O_t *oh, size_t *size_ptr) +{ + unsigned u; + size_t size; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_compute_size); + + /* check args */ + HDassert(f); + HDassert(oh); + HDassert(size_ptr); + + size = H5O_SIZEOF_HDR(f); + + for (u = 0; u < oh->nchunks; u++) + size += oh->chunk[u].size; + + HDassert(size >= H5O_SIZEOF_HDR(f)); + + *size_ptr = size; + + FUNC_LEAVE_NOAPI(SUCCEED); +} /* H5O_compute_size() */ + diff --git a/src/H5Ocont.c b/src/H5Ocont.c index afa5ab7..f471c61 100644 --- a/src/H5Ocont.c +++ b/src/H5Ocont.c @@ -23,25 +23,24 @@ * the H5O package. Therefore, do not change * any definitions in this file! * - * Modifications: - * *------------------------------------------------------------------------- */ #define H5O_PACKAGE /*suppress error about including H5Opkg */ -#include "H5private.h" -#include "H5Eprivate.h" +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ #include "H5FLprivate.h" /* Free Lists */ -#include "H5MMprivate.h" -#include "H5Opkg.h" /* Object header functions */ +#include "H5MFprivate.h" /* File memory management */ +#include "H5Opkg.h" /* Object headers */ /* PRIVATE PROTOTYPES */ -static void *H5O_cont_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p, H5O_shared_t *sh); +static void *H5O_cont_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p); static herr_t H5O_cont_encode(H5F_t *f, uint8_t *p, const void *_mesg); static size_t H5O_cont_size(const H5F_t *f, const void *_mesg); static herr_t H5O_cont_free(void *mesg); +static herr_t H5O_cont_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link); static void *H5O_cont_copy_file(H5F_t *file_src, void *mesg_src, H5F_t *file_dst, hid_t dxpl_id, H5SL_t *map_list, void *udata); static herr_t H5O_cont_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, @@ -58,7 +57,7 @@ const H5O_class_t H5O_CONT[1] = {{ H5O_cont_size, /*size of header continuation */ NULL, /*reset method */ H5O_cont_free, /* free method */ - NULL, /* file delete method */ + H5O_cont_delete, /* file delete method */ NULL, /* link method */ NULL, /*get share method */ NULL, /*set share method */ @@ -89,7 +88,7 @@ H5FL_DEFINE(H5O_cont_t); *------------------------------------------------------------------------- */ static void * -H5O_cont_decode(H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *p, H5O_shared_t UNUSED *sh) +H5O_cont_decode(H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *p) { H5O_cont_t *cont = NULL; void *ret_value; @@ -99,7 +98,6 @@ H5O_cont_decode(H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *p, H5O_shared_t U /* check args */ assert(f); assert(p); - assert (!sh); /* decode */ if (NULL==(cont = H5FL_MALLOC(H5O_cont_t))) @@ -213,6 +211,39 @@ H5O_cont_free (void *mesg) /*------------------------------------------------------------------------- + * Function: H5O_cont_delete + * + * Purpose: Free file space referenced by message + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Monday, October 10, 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_cont_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t UNUSED adj_link) +{ + const H5O_cont_t *mesg = (const H5O_cont_t *) _mesg; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5O_cont_delete) + + /* check args */ + HDassert(f); + HDassert(mesg); + + /* Release space for chunk */ + if(H5MF_xfree(f, H5FD_MEM_OHDR, dxpl_id, mesg->addr, (hsize_t)mesg->size) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free object header chunk") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_cont_delete() */ + + +/*------------------------------------------------------------------------- * Function: H5O_cont_copy_file * * Purpose: Copies a continuation block message from _MESG to _DEST in file @@ -228,7 +259,7 @@ H5O_cont_free (void *mesg) */ static void * H5O_cont_copy_file(H5F_t UNUSED *file_src, void *mesg_src, - H5F_t *file_dst, hid_t UNUSED dxpl_id, H5SL_t UNUSED *map_list, void *udata) + H5F_t UNUSED *file_dst, hid_t UNUSED dxpl_id, H5SL_t UNUSED *map_list, void *udata) { H5O_cont_t *cont_src = (H5O_cont_t *) mesg_src; H5O_chunk_t *chunk = (H5O_chunk_t *)udata; diff --git a/src/H5Odtype.c b/src/H5Odtype.c index 05ca879..73d8909 100644 --- a/src/H5Odtype.c +++ b/src/H5Odtype.c @@ -26,7 +26,7 @@ /* PRIVATE PROTOTYPES */ static herr_t H5O_dtype_encode (H5F_t *f, uint8_t *p, const void *mesg); -static void *H5O_dtype_decode (H5F_t *f, hid_t dxpl_id, const uint8_t *p, H5O_shared_t *sh); +static void *H5O_dtype_decode (H5F_t *f, hid_t dxpl_id, const uint8_t *p); static void *H5O_dtype_copy (const void *_mesg, void *_dest, unsigned update_flags); static size_t H5O_dtype_size (const H5F_t *f, const void *_mesg); static herr_t H5O_dtype_reset (void *_mesg); @@ -67,10 +67,6 @@ const H5O_class_t H5O_DTYPE[1] = {{ * class objects (array definitely, potentially compound & vlen sequences also) */ #define H5O_DTYPE_VERSION_UPDATED 2 -/* Declare external the free list for H5T_t's */ -H5FL_EXTERN(H5T_t); -H5FL_EXTERN(H5T_shared_t); - /*------------------------------------------------------------------------- * Function: H5O_dtype_decode_helper @@ -823,8 +819,7 @@ done: function using malloc() and is returned to the caller. --------------------------------------------------------------------------*/ static void * -H5O_dtype_decode(H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *p, - H5O_shared_t UNUSED *sh) +H5O_dtype_decode(H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *p) { H5T_t *dt = NULL; void *ret_value; /* Return value */ @@ -1103,8 +1098,6 @@ H5O_dtype_free (void *mesg) * Programmer: Robb Matzke * Monday, June 1, 1998 * - * Modifications: - * *------------------------------------------------------------------------- */ static herr_t @@ -1112,25 +1105,26 @@ H5O_dtype_get_share(H5F_t UNUSED *f, const void *_mesg, H5O_shared_t *sh/*out*/) { const H5T_t *dt = (const H5T_t *)_mesg; - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5O_dtype_get_share) - FUNC_ENTER_NOAPI_NOINIT(H5O_dtype_get_share); + HDassert(dt); + HDassert(sh); - assert (dt); - assert (sh); + /* Check for object location address defined */ + if(!H5F_addr_defined(dt->oloc.addr)) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "datatype is not sharable") - if (H5F_addr_defined (dt->ent.header)) { - /* If the address is defined, this had better be a named datatype */ - HDassert (H5T_STATE_NAMED==dt->shared->state || H5T_STATE_OPEN==dt->shared->state); + /* If the address is defined, this had better be a named datatype */ + HDassert(H5T_STATE_NAMED == dt->shared->state || H5T_STATE_OPEN == dt->shared->state); - sh->in_gh = FALSE; - sh->u.ent = dt->ent; - } else - HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, "datatype is not sharable"); + /* Copy object location info */ + H5O_loc_copy(&(sh->oloc), &(dt->oloc), H5O_COPY_DEEP); done: - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_dtype_get_share() */ /*------------------------------------------------------------------------- @@ -1143,33 +1137,27 @@ done: * Programmer: Robb Matzke * Thursday, June 4, 1998 * - * Modifications: - * - * Pedro Vicente, <pvn@ncsa.uiuc.edu> 22 Aug 2002 - * Added `id to name' support. - * *------------------------------------------------------------------------- */ static herr_t -H5O_dtype_set_share (H5F_t UNUSED *f, void *_mesg/*in,out*/, +H5O_dtype_set_share(H5F_t UNUSED *f, void *_mesg/*in,out*/, const H5O_shared_t *sh) { H5T_t *dt = (H5T_t *)_mesg; - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_dtype_set_share); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_dtype_set_share) - assert (dt); - assert (sh); - assert (!sh->in_gh); + HDassert(dt); + HDassert(sh); - /* NULL copy here, names not appropriate */ - H5G_ent_copy(&(dt->ent),&(sh->u.ent),H5G_COPY_NULL); + /* Retrieve object location information */ + H5O_loc_copy(&(dt->oloc), &(sh->oloc), H5O_COPY_DEEP); /* Note that the datatype is a named datatype */ dt->shared->state = H5T_STATE_NAMED; - FUNC_LEAVE_NOAPI(SUCCEED); -} + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5O_dtype_set_share() */ /*-------------------------------------------------------------------------- diff --git a/src/H5Oefl.c b/src/H5Oefl.c index 8c78cae..24f8c3b 100644 --- a/src/H5Oefl.c +++ b/src/H5Oefl.c @@ -28,7 +28,7 @@ #include "H5Opkg.h" /* Object headers */ /* PRIVATE PROTOTYPES */ -static void *H5O_efl_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p, H5O_shared_t *sh); +static void *H5O_efl_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p); static herr_t H5O_efl_encode(H5F_t *f, uint8_t *p, const void *_mesg); static void *H5O_efl_copy(const void *_mesg, void *_dest, unsigned update_flags); static size_t H5O_efl_size(const H5F_t *f, const void *_mesg); @@ -81,7 +81,7 @@ const H5O_class_t H5O_EFL[1] = {{ *------------------------------------------------------------------------- */ static void * -H5O_efl_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p, H5O_shared_t UNUSED *sh) +H5O_efl_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p) { H5O_efl_t *mesg = NULL; int version; @@ -95,7 +95,6 @@ H5O_efl_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p, H5O_shared_t UNUSED *s /* Check args */ assert(f); assert(p); - assert (!sh); if (NULL==(mesg = H5MM_calloc(sizeof(H5O_efl_t)))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); diff --git a/src/H5Ofill.c b/src/H5Ofill.c index b68c106..f6e68a0 100644 --- a/src/H5Ofill.c +++ b/src/H5Ofill.c @@ -30,7 +30,7 @@ #include "H5Pprivate.h" /* Property lists */ -static void *H5O_fill_new_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p, H5O_shared_t *sh); +static void *H5O_fill_new_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p); static herr_t H5O_fill_new_encode(H5F_t *f, uint8_t *p, const void *_mesg); static void *H5O_fill_new_copy(const void *_mesg, void *_dest, unsigned update_flags); static size_t H5O_fill_new_size(const H5F_t *f, const void *_mesg); @@ -39,7 +39,7 @@ static herr_t H5O_fill_new_free(void *_mesg); static herr_t H5O_fill_new_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE *stream, int indent, int fwidth); -static void *H5O_fill_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p, H5O_shared_t *sh); +static void *H5O_fill_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p); static herr_t H5O_fill_encode(H5F_t *f, uint8_t *p, const void *_mesg); static void *H5O_fill_copy(const void *_mesg, void *_dest, unsigned update_flags); static size_t H5O_fill_size(const H5F_t *f, const void *_mesg); @@ -119,8 +119,7 @@ H5FL_DEFINE(H5O_fill_t); *------------------------------------------------------------------------- */ static void * -H5O_fill_new_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const uint8_t *p, - H5O_shared_t UNUSED *sh) +H5O_fill_new_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const uint8_t *p) { H5O_fill_new_t *mesg=NULL; int version; @@ -130,7 +129,6 @@ H5O_fill_new_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const uint8_t *p, assert(f); assert(p); - assert(!sh); if (NULL==(mesg=H5FL_CALLOC(H5O_fill_new_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill value message"); @@ -193,8 +191,7 @@ done: *------------------------------------------------------------------------- */ static void * -H5O_fill_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const uint8_t *p, - H5O_shared_t UNUSED *sh) +H5O_fill_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const uint8_t *p) { H5O_fill_t *mesg=NULL; void *ret_value; @@ -203,7 +200,6 @@ H5O_fill_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const uint8_t *p, assert(f); assert(p); - assert(!sh); if (NULL==(mesg=H5FL_CALLOC(H5O_fill_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill value message"); diff --git a/src/H5Oginfo.c b/src/H5Oginfo.c new file mode 100644 index 0000000..6aeda3d --- /dev/null +++ b/src/H5Oginfo.c @@ -0,0 +1,334 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5Oginfo.c + * Aug 23 2005 + * Quincey Koziol <koziol@ncsa.uiuc.edu> + * + * Purpose: Group Information messages. + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +#define H5O_PACKAGE /*suppress error about including H5Opkg */ + +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5FLprivate.h" /* Free lists */ +#include "H5Opkg.h" /* Object headers */ + + +/* PRIVATE PROTOTYPES */ +static void *H5O_ginfo_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p); +static herr_t H5O_ginfo_encode(H5F_t *f, uint8_t *p, const void *_mesg); +static void *H5O_ginfo_copy(const void *_mesg, void *_dest, unsigned update_flags); +static size_t H5O_ginfo_size(const H5F_t *f, const void *_mesg); +static herr_t H5O_ginfo_free(void *_mesg); +static herr_t H5O_ginfo_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, + FILE * stream, int indent, int fwidth); + +/* This message derives from H5O */ +const H5O_class_t H5O_GINFO[1] = {{ + H5O_GINFO_ID, /*message id number */ + "ginfo", /*message name for debugging */ + sizeof(H5O_ginfo_t), /*native message size */ + H5O_ginfo_decode, /*decode message */ + H5O_ginfo_encode, /*encode message */ + H5O_ginfo_copy, /*copy the native value */ + H5O_ginfo_size, /*size of symbol table entry */ + NULL, /*default reset method */ + H5O_ginfo_free, /* free method */ + NULL, /* file delete method */ + NULL, /* link method */ + NULL, /*get share method */ + NULL, /*set share method */ + NULL, /* copy native value to file */ + NULL, /* post copy native value to file */ + H5O_ginfo_debug /*debug the message */ +}}; + +/* Current version of group info information */ +#define H5O_GINFO_VERSION 1 + +/* Declare a free list to manage the H5O_ginfo_t struct */ +H5FL_DEFINE_STATIC(H5O_ginfo_t); + + +/*------------------------------------------------------------------------- + * Function: H5O_ginfo_decode + * + * Purpose: Decode a message and return a pointer to + * a newly allocated one. + * + * Return: Success: Ptr to new message in native order. + * + * Failure: NULL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Aug 30 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void * +H5O_ginfo_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const uint8_t *p) +{ + H5O_ginfo_t *ginfo = NULL; /* Pointer to group information message */ + void *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5O_ginfo_decode) + + /* check args */ + HDassert(f); + HDassert(p); + + /* decode */ + if(*p++ != H5O_GINFO_VERSION) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for message") + + /* Allocate space for message */ + if(NULL == (ginfo = H5FL_CALLOC(H5O_ginfo_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* Get the local heap size hint */ + UINT32DECODE(p, ginfo->lheap_size_hint) + + /* Get the max. # of links to store compactly & the min. # of links to store densely */ + UINT32DECODE(p, ginfo->max_compact) + UINT32DECODE(p, ginfo->min_dense) + + /* Get the estimated # of entries & name lengths */ + UINT32DECODE(p, ginfo->est_num_entries) + UINT32DECODE(p, ginfo->est_name_len) + + /* Set return value */ + ret_value=ginfo; + +done: + if(ret_value == NULL) + if(ginfo != NULL) + H5FL_FREE(H5O_ginfo_t, ginfo); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_ginfo_decode() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_ginfo_encode + * + * Purpose: Encodes a message. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Aug 30 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_ginfo_encode(H5F_t UNUSED *f, uint8_t *p, const void *_mesg) +{ + const H5O_ginfo_t *ginfo = (const H5O_ginfo_t *) _mesg; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_ginfo_encode) + + /* check args */ + HDassert(f); + HDassert(p); + HDassert(ginfo); + + /* encode */ + *p++ = H5O_GINFO_VERSION; + + /* Store the local heap size hint for the group */ + UINT32ENCODE(p, ginfo->lheap_size_hint) + + /* Store the max. # of links to store compactly & the min. # of links to store densely */ + UINT32ENCODE(p, ginfo->max_compact) + UINT32ENCODE(p, ginfo->min_dense) + + /* Store the estimated # of entries & name lengths */ + UINT32ENCODE(p, ginfo->est_num_entries) + UINT32ENCODE(p, ginfo->est_name_len) + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5O_ginfo_encode() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_ginfo_copy + * + * Purpose: Copies a message from _MESG to _DEST, allocating _DEST if + * necessary. + * + * Return: Success: Ptr to _DEST + * + * Failure: NULL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Aug 30 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void * +H5O_ginfo_copy(const void *_mesg, void *_dest, unsigned UNUSED update_flags) +{ + const H5O_ginfo_t *ginfo = (const H5O_ginfo_t *) _mesg; + H5O_ginfo_t *dest = (H5O_ginfo_t *) _dest; + void *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5O_ginfo_copy) + + /* check args */ + HDassert(ginfo); + if(!dest && NULL == (dest = H5FL_MALLOC(H5O_ginfo_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* copy */ + *dest = *ginfo; + + /* Set return value */ + ret_value=dest; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_ginfo_copy() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_ginfo_size + * + * Purpose: Returns the size of the raw message in bytes not counting + * the message type or size fields, but only the data fields. + * This function doesn't take into account alignment. + * + * Return: Success: Message data size in bytes without alignment. + * + * Failure: zero + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Aug 30 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static size_t +H5O_ginfo_size(const H5F_t UNUSED *f, const void UNUSED *_mesg) +{ + size_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_ginfo_size) + + /* Set return value */ + ret_value = 1 + /* Version */ + 4 + /* Local heap size hint */ + 4 + /* "Max compact" links */ + 4 + /* "Min dense" links */ + 4 + /* Estimated # of entries in group */ + 4; /* Estimated length of name of entry in group */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_ginfo_size() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_ginfo_free + * + * Purpose: Free's the message + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, August 30, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_ginfo_free(void *mesg) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_ginfo_free) + + HDassert(mesg); + + H5FL_FREE(H5O_ginfo_t, mesg); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5O_ginfo_free() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_ginfo_debug + * + * Purpose: Prints debugging info for a message. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Aug 30 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_ginfo_debug(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const void *_mesg, FILE * stream, + int indent, int fwidth) +{ + const H5O_ginfo_t *ginfo = (const H5O_ginfo_t *) _mesg; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_ginfo_debug) + + /* check args */ + HDassert(f); + HDassert(ginfo); + HDassert(stream); + HDassert(indent >= 0); + HDassert(fwidth >= 0); + + HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, + "Local heap size hint:", ginfo->lheap_size_hint); + + HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, + "Max. compact links:", ginfo->max_compact); + + HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, + "Min. dense links:", ginfo->min_dense); + + HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, + "Estimated # of objects in group:", ginfo->est_num_entries); + + HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, + "Estimated length of object in group's name:", ginfo->est_name_len); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5O_ginfo_debug() */ + + diff --git a/src/H5Olayout.c b/src/H5Olayout.c index 3103053..0844010 100644 --- a/src/H5Olayout.c +++ b/src/H5Olayout.c @@ -32,7 +32,7 @@ #include "H5Pprivate.h" /* Property lists */ /* PRIVATE PROTOTYPES */ -static void *H5O_layout_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p, H5O_shared_t *sh); +static void *H5O_layout_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p); static herr_t H5O_layout_encode(H5F_t *f, uint8_t *p, const void *_mesg); static void *H5O_layout_copy(const void *_mesg, void *_dest, unsigned update_flags); static size_t H5O_layout_size(const H5F_t *f, const void *_mesg); @@ -105,7 +105,7 @@ H5FL_DEFINE(H5O_layout_t); *------------------------------------------------------------------------- */ static void * -H5O_layout_decode(H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *p, H5O_shared_t UNUSED *sh) +H5O_layout_decode(H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *p) { H5O_layout_t *mesg = NULL; unsigned u; @@ -116,7 +116,6 @@ H5O_layout_decode(H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *p, H5O_shared_t /* check args */ assert(f); assert(p); - assert (!sh); /* decode */ if (NULL==(mesg = H5FL_CALLOC(H5O_layout_t))) @@ -768,3 +767,4 @@ H5O_layout_debug(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const void *_mesg, FILE FUNC_LEAVE_NOAPI(SUCCEED); } + diff --git a/src/H5Olinfo.c b/src/H5Olinfo.c new file mode 100644 index 0000000..cc0ce2d --- /dev/null +++ b/src/H5Olinfo.c @@ -0,0 +1,301 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5Olinfo.c + * Aug 23 2005 + * Quincey Koziol <koziol@ncsa.uiuc.edu> + * + * Purpose: Link Information messages. + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +#define H5O_PACKAGE /*suppress error about including H5Opkg */ + +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5FLprivate.h" /* Free lists */ +#include "H5Opkg.h" /* Object headers */ + + +/* PRIVATE PROTOTYPES */ +static void *H5O_linfo_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p); +static herr_t H5O_linfo_encode(H5F_t *f, uint8_t *p, const void *_mesg); +static void *H5O_linfo_copy(const void *_mesg, void *_dest, unsigned update_flags); +static size_t H5O_linfo_size(const H5F_t *f, const void *_mesg); +static herr_t H5O_linfo_free(void *_mesg); +static herr_t H5O_linfo_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, + FILE * stream, int indent, int fwidth); + +/* This message derives from H5O */ +const H5O_class_t H5O_LINFO[1] = {{ + H5O_LINFO_ID, /*message id number */ + "linfo", /*message name for debugging */ + sizeof(H5O_linfo_t), /*native message size */ + H5O_linfo_decode, /*decode message */ + H5O_linfo_encode, /*encode message */ + H5O_linfo_copy, /*copy the native value */ + H5O_linfo_size, /*size of symbol table entry */ + NULL, /*default reset method */ + H5O_linfo_free, /* free method */ + NULL, /* file delete method */ + NULL, /* link method */ + NULL, /*get share method */ + NULL, /*set share method */ + NULL, /* copy native value to file */ + NULL, /* post copy native value to file */ + H5O_linfo_debug /*debug the message */ +}}; + +/* Current version of link info information */ +#define H5O_LINFO_VERSION 1 + +/* Declare a free list to manage the hsize_t struct */ +H5FL_DEFINE_STATIC(H5O_linfo_t); + + +/*------------------------------------------------------------------------- + * Function: H5O_linfo_decode + * + * Purpose: Decode a message and return a pointer to + * a newly allocated one. + * + * Return: Success: Ptr to new message in native order. + * + * Failure: NULL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Aug 23 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void * +H5O_linfo_decode(H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *p) +{ + H5O_linfo_t *linfo = NULL; /* Link info */ + void *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5O_linfo_decode) + + /* check args */ + HDassert(f); + HDassert(p); + + /* decode */ + if(*p++ != H5O_LINFO_VERSION) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for message") + + /* Allocate space for message */ + if (NULL == (linfo = H5FL_MALLOC(H5O_linfo_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* Get the number of links in the group */ + H5F_DECODE_LENGTH(f, p, linfo->nlinks) + + /* Set return value */ + ret_value = linfo; + +done: + if(ret_value == NULL) + if(linfo != NULL) + H5FL_FREE(H5O_linfo_t, linfo); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_linfo_decode() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_linfo_encode + * + * Purpose: Encodes a message. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Aug 23 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_linfo_encode(H5F_t *f, uint8_t *p, const void *_mesg) +{ + const H5O_linfo_t *linfo = (const H5O_linfo_t *) _mesg; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_linfo_encode) + + /* check args */ + HDassert(f); + HDassert(p); + HDassert(linfo); + + /* encode */ + *p++ = H5O_LINFO_VERSION; + + /* Store the number of links in the group */ + H5F_ENCODE_LENGTH(f, p, linfo->nlinks) + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5O_linfo_encode() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_linfo_copy + * + * Purpose: Copies a message from _MESG to _DEST, allocating _DEST if + * necessary. + * + * Return: Success: Ptr to _DEST + * + * Failure: NULL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Aug 23 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void * +H5O_linfo_copy(const void *_mesg, void *_dest, unsigned UNUSED update_flags) +{ + const H5O_linfo_t *linfo = (const H5O_linfo_t *) _mesg; + H5O_linfo_t *dest = (H5O_linfo_t *) _dest; + void *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5O_linfo_copy) + + /* check args */ + HDassert(linfo); + if(!dest && NULL == (dest = H5FL_MALLOC(H5O_linfo_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* copy */ + *dest = *linfo; + + /* Set return value */ + ret_value=dest; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_linfo_copy() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_linfo_size + * + * Purpose: Returns the size of the raw message in bytes not counting + * the message type or size fields, but only the data fields. + * This function doesn't take into account alignment. + * + * Return: Success: Message data size in bytes without alignment. + * + * Failure: zero + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Aug 23 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static size_t +H5O_linfo_size(const H5F_t *f, const void UNUSED *_mesg) +{ + size_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_linfo_size) + + /* Set return value */ + ret_value = 1 + /* Version */ + H5F_SIZEOF_SIZE(f); /* Number of links */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_linfo_size() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_linfo_free + * + * Purpose: Free's the message + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, August 23, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_linfo_free(void *mesg) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_linfo_free) + + HDassert(mesg); + + H5FL_FREE(H5O_linfo_t, mesg); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5O_linfo_free() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_linfo_debug + * + * Purpose: Prints debugging info for a message. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Aug 23 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_linfo_debug(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const void *_mesg, FILE * stream, + int indent, int fwidth) +{ + const H5O_linfo_t *linfo = (const H5O_linfo_t *) _mesg; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_linfo_debug) + + /* check args */ + HDassert(f); + HDassert(linfo); + HDassert(stream); + HDassert(indent >= 0); + HDassert(fwidth >= 0); + + HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth, + "Number of links:", linfo->nlinks); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5O_linfo_debug() */ + diff --git a/src/H5Olink.c b/src/H5Olink.c new file mode 100644 index 0000000..2284ecb --- /dev/null +++ b/src/H5Olink.c @@ -0,0 +1,672 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5Olink.c + * Aug 29 2005 + * Quincey Koziol <koziol@ncsa.uiuc.edu> + * + * Purpose: Link messages. + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +#define H5O_PACKAGE /*suppress error about including H5Opkg */ + +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5FLprivate.h" /* Free lists */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5Opkg.h" /* Object headers */ + + +/* PRIVATE PROTOTYPES */ +static void *H5O_link_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p); +static herr_t H5O_link_encode(H5F_t *f, uint8_t *p, const void *_mesg); +static void *H5O_link_copy(const void *_mesg, void *_dest, unsigned update_flags); +static size_t H5O_link_size(const H5F_t *f, const void *_mesg); +static herr_t H5O_link_reset(void *_mesg); +static herr_t H5O_link_free(void *_mesg); +static herr_t H5O_link_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link); +static void *H5O_link_copy_file(H5F_t *file_src, void *native_src, + H5F_t *file_dst, hid_t dxpl_id, H5SL_t *map_list, void *udata); +static herr_t H5O_link_post_copy_file(H5F_t *file_src, const void *mesg_src, + H5O_loc_t *dst_oloc, void *mesg_dst, hbool_t *modified, hid_t dxpl_id, H5SL_t *map_list); +static herr_t H5O_link_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, + FILE * stream, int indent, int fwidth); + +/* This message derives from H5O */ +const H5O_class_t H5O_LINK[1] = {{ + H5O_LINK_ID, /*message id number */ + "link", /*message name for debugging */ + sizeof(H5O_link_t), /*native message size */ + H5O_link_decode, /*decode message */ + H5O_link_encode, /*encode message */ + H5O_link_copy, /*copy the native value */ + H5O_link_size, /*size of symbol table entry */ + H5O_link_reset, /* reset method */ + H5O_link_free, /* free method */ + H5O_link_delete, /* file delete method */ + NULL, /* link method */ + NULL, /*get share method */ + NULL, /*set share method */ + H5O_link_copy_file, /* copy native value to file */ + H5O_link_post_copy_file, /* post copy native value to file */ + H5O_link_debug /*debug the message */ +}}; + +/* Current version of link information */ +#define H5O_LINK_VERSION 1 + +/* Declare a free list to manage the H5O_link_t struct */ +H5FL_DEFINE_STATIC(H5O_link_t); + + +/*------------------------------------------------------------------------- + * Function: H5O_link_decode + * + * Purpose: Decode a message and return a pointer to + * a newly allocated one. + * + * Return: Success: Ptr to new message in native order. + * + * Failure: NULL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Aug 29 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void * +H5O_link_decode(H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *p) +{ + H5O_link_t *lnk = NULL; /* Pointer to link message */ + uint16_t len; /* Length of a string in the message */ + uint32_t tmp_time; /* Temporary copy of the time */ + void *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5O_link_decode) + + /* check args */ + HDassert(f); + HDassert(p); + + /* decode */ + if(*p++ != H5O_LINK_VERSION) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for message") + + /* Allocate space for message */ + if(NULL == (lnk = H5FL_CALLOC(H5O_link_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* Get the type of the link */ + lnk->type = *p++; + if(lnk->type < H5G_LINK_HARD || lnk->type > H5G_LINK_SOFT) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad link type") + + /* Get the link creation time from the file */ + UINT32DECODE(p, tmp_time) + lnk->ctime = (time_t)tmp_time; + + /* Get the link name's character set */ + lnk->cset = (H5T_cset_t)*p++; + if(lnk->cset < H5T_CSET_ASCII || lnk->cset > H5T_CSET_UTF8) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad cset type") + + /* Get the link's name */ + UINT16DECODE(p, len) + if(len == 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "invalid name length") + if(NULL == (lnk->name = H5MM_malloc((size_t)len + 1))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + HDmemcpy(lnk->name, p, len); + lnk->name[len] = '\0'; + p += len; + + /* Get the appropriate information for each type of link */ + switch(lnk->type) { + case H5G_LINK_HARD: + /* Get the address of the object the link points to */ + H5F_addr_decode(f, &p, &(lnk->u.hard.addr)); + break; + + case H5G_LINK_SOFT: + /* Get the link value */ + UINT16DECODE(p, len) + if(len == 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "invalid link length") + if(NULL == (lnk->u.soft.name = H5MM_malloc((size_t)len + 1))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + HDmemcpy(lnk->u.soft.name, p, len); + lnk->u.soft.name[len] = '\0'; + p += len; + break; + + default: + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "unknown link type") + break; + } /* end switch */ + + /* Set return value */ + ret_value=lnk; + +done: + if(ret_value == NULL) + if(lnk != NULL) { + if(lnk->name != NULL) + H5MM_xfree(lnk->name); + if(lnk->type == H5G_LINK_SOFT && lnk->u.soft.name != NULL) + H5MM_xfree(lnk->u.soft.name); + H5FL_FREE(H5O_link_t, lnk); + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_link_decode() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_link_encode + * + * Purpose: Encodes a link message. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Aug 29 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_link_encode(H5F_t *f, uint8_t *p, const void *_mesg) +{ + const H5O_link_t *lnk = (const H5O_link_t *) _mesg; + uint16_t len; /* Length of a string in the message */ + uint32_t tmp_time; /* Temporary copy of the time */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_link_encode) + + /* check args */ + HDassert(f); + HDassert(p); + HDassert(lnk); + + /* encode */ + *p++ = H5O_LINK_VERSION; + + /* Store the type of the link */ + *p++ = lnk->type; + + /* Store the link creation time from the file */ + tmp_time = lnk->ctime; + UINT32ENCODE(p, tmp_time) + + /* Store the link name's character set */ + *p++ = (uint8_t)lnk->cset; + + /* Store the link's name */ + len = (uint16_t)HDstrlen(lnk->name); + HDassert(len > 0); + UINT16ENCODE(p, len) + HDmemcpy(p, lnk->name, len); + p += len; + + /* Store the appropriate information for each type of link */ + switch(lnk->type) { + case H5G_LINK_HARD: + /* Store the address of the object the link points to */ + H5F_addr_encode(f, &p, lnk->u.hard.addr); + break; + + case H5G_LINK_SOFT: + /* Store the link value */ + len = (uint16_t)HDstrlen(lnk->u.soft.name); + HDassert(len > 0); + UINT16ENCODE(p, len) + HDmemcpy(p, lnk->u.soft.name, len); + p += len; + break; + + default: + HDassert((lnk->type == H5G_LINK_HARD) || (lnk->type == H5G_LINK_SOFT)); + break; + } /* end switch */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5O_link_encode() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_link_copy + * + * Purpose: Copies a message from _MESG to _DEST, allocating _DEST if + * necessary. + * + * Return: Success: Ptr to _DEST + * + * Failure: NULL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Aug 29 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void * +H5O_link_copy(const void *_mesg, void *_dest, unsigned UNUSED update_flags) +{ + const H5O_link_t *lnk = (const H5O_link_t *) _mesg; + H5O_link_t *dest = (H5O_link_t *) _dest; + void *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5O_link_copy) + + /* check args */ + HDassert(lnk); + if(!dest && NULL == (dest = H5FL_MALLOC(H5O_link_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* copy */ + *dest = *lnk; + HDassert(lnk->name); + dest->name = H5MM_xstrdup(lnk->name); + if(lnk->type == H5G_LINK_SOFT) + dest->u.soft.name = H5MM_xstrdup(lnk->u.soft.name); + + /* Set return value */ + ret_value=dest; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_link_copy() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_link_size + * + * Purpose: Returns the size of the raw message in bytes not counting + * the message type or size fields, but only the data fields. + * This function doesn't take into account alignment. + * + * Return: Success: Message data size in bytes without alignment. + * + * Failure: zero + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Aug 29 2005 + * + *------------------------------------------------------------------------- + */ +static size_t +H5O_link_size(const H5F_t *f, const void *_mesg) +{ + const H5O_link_t *lnk = (const H5O_link_t *)_mesg; + size_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_link_size) + + /* Set return value */ + ret_value = 1 + /* Version */ + 1 + /* Link type */ + 4 + /* Creation time */ + 1 + /* Character set */ + 2 + /* Name length */ + HDstrlen(lnk->name); /* Name */ + + /* Add the appropriate length for each type of link */ + switch(lnk->type) { + case H5G_LINK_HARD: + ret_value += H5F_SIZEOF_ADDR(f); + break; + + case H5G_LINK_SOFT: + ret_value += 2 + /* Link value length */ + HDstrlen(lnk->u.soft.name); /* Link value */ + break; + + default: + HDassert((lnk->type == H5G_LINK_HARD) || (lnk->type == H5G_LINK_SOFT)); + break; + } /* end switch */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_link_size() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_link_reset + * + * Purpose: Frees resources within a message, but doesn't free + * the message itself. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Monday, August 29, 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_link_reset(void *_mesg) +{ + H5O_link_t *lnk = (H5O_link_t *)_mesg; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_link_reset) + + if(lnk) { + /* Free information for link (but don't free link pointer) */ + if(lnk->type == H5G_LINK_SOFT) + lnk->u.soft.name = H5MM_xfree(lnk->u.soft.name); + lnk->name = H5MM_xfree(lnk->name); + } /* end if */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5O_link_reset() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_link_free + * + * Purpose: Free's the message contents and the message itself + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Monday, August 29, 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_link_free(void *_mesg) +{ + H5O_link_t *lnk = (H5O_link_t *)_mesg; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_link_free) + + HDassert(lnk); + + /* Free information for link */ + if(lnk->type == H5G_LINK_SOFT) + lnk->u.soft.name = H5MM_xfree(lnk->u.soft.name); + lnk->name = H5MM_xfree(lnk->name); + H5FL_FREE(H5O_link_t, lnk); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5O_link_free() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_link_delete + * + * Purpose: Free file space referenced by message + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Monday, August 29, 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_link_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link) +{ + const H5O_link_t *lnk = (const H5O_link_t *)_mesg; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5O_link_delete) + + /* check args */ + HDassert(f); + HDassert(lnk); + + /* Decrement reference count to the object, for hard links */ + if(lnk->type == H5G_LINK_HARD) { + H5O_loc_t oloc; + + /* Construct object location for object, in order to decrement it's ref count */ + H5O_loc_reset(&oloc); + oloc.file = f; + HDassert(H5F_addr_defined(lnk->u.hard.addr)); + oloc.addr = lnk->u.hard.addr; + + /* Decrement the ref count for the object, if requested */ + if(adj_link) + if(H5O_link(&oloc, -1, dxpl_id)<0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to decrement object link count") + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_link_delete() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_link_copy_file + * + * Purpose: Copies a message from _MESG to _DEST in file + * + * Return: Success: Ptr to _DEST + * + * Failure: NULL + * + * Programmer: Quincey Koziol + * November 7, 2005 + * + *------------------------------------------------------------------------- + */ +static void * +H5O_link_copy_file(H5F_t UNUSED *file_src, void *native_src, + H5F_t UNUSED *file_dst, hid_t UNUSED dxpl_id, H5SL_t UNUSED *map_list, void UNUSED *udata) +{ + H5O_link_t *link_src = (H5O_link_t *) native_src; + H5O_link_t *link_dst = NULL; + void *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5O_link_copy_file) + + /* check args */ + HDassert(link_src); + HDassert(file_dst); + + /* Allocate space for the destination stab */ + if(NULL == (link_dst = H5FL_MALLOC(H5O_link_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* Copy top-level information */ + *link_dst = *link_src; + + /* Deep copy the link's name */ + if(NULL == (link_dst->name = H5MM_xstrdup(link_src->name))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* "Deep copy" other information for each kind of link */ + switch(link_src->type) { + case H5G_LINK_HARD: + /* Set link's address undefined here, will be fixed up in "post copy" callback */ + link_dst->u.hard.addr = HADDR_UNDEF; + break; + + case H5G_LINK_SOFT: + /* Copy the soft link's value */ + if(NULL == (link_dst->u.soft.name = H5MM_xstrdup(link_src->u.soft.name))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + break; + + default: + HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, NULL, "unrecognized link type") + } /* end switch */ + + /* Set return value */ + ret_value = link_dst; + +done: + if(!ret_value) + if(link_dst) + H5FL_FREE(H5O_link_t, link_dst); + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5O_link_copy_file() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_link_post_copy_file + * + * Purpose: Finish copying a message from between files + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * November 7, 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_link_post_copy_file(H5F_t *file_src, const void *mesg_src, + H5O_loc_t *dst_oloc, void *mesg_dst, hbool_t *modified, hid_t dxpl_id, H5SL_t *map_list) +{ + const H5O_link_t *link_src = (const H5O_link_t *)mesg_src; + H5O_link_t *link_dst = (H5O_link_t *)mesg_dst; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5O_link_post_copy_file) + + /* check args */ + HDassert(link_src); + HDassert(dst_oloc); + HDassert(H5F_addr_defined(dst_oloc->addr)); + HDassert(dst_oloc->file); + HDassert(link_dst); + HDassert(modified && *modified == FALSE); + HDassert(map_list); + + /* Additional "deep copy" for each kind of link */ + switch(link_src->type) { + case H5G_LINK_HARD: + /* Copy the object pointed to */ + { + H5O_loc_t src_oloc; /* Temporary object location for source object */ + H5O_loc_t new_oloc; /* Temporary object location for source object */ + + /* Build temporary object location for source */ + H5O_loc_reset(&src_oloc); + src_oloc.file = file_src; + HDassert(H5F_addr_defined(link_src->u.hard.addr)); + src_oloc.addr = link_src->u.hard.addr; + + /* Build temporary object location for destination */ + H5O_loc_reset(&new_oloc); + new_oloc.file = dst_oloc->file; + + /* Copy the shared object from source to destination */ + /* (Increments link count on destination) */ + if(H5O_copy_header_map(&src_oloc, &new_oloc, dxpl_id, map_list) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object") + + /* Update link information with new destination object's address */ + link_dst->u.hard.addr = new_oloc.addr; + + /* Indicate that the destination message was modified */ + *modified = TRUE; + } /* end case */ + break; + + case H5G_LINK_SOFT: + HGOTO_DONE(SUCCEED) + break; + + default: + HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "unrecognized link type") + } /* end switch */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5O_link_post_copy_file() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_link_debug + * + * Purpose: Prints debugging info for a message. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Aug 29 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_link_debug(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const void *_mesg, FILE * stream, + int indent, int fwidth) +{ + const H5O_link_t *lnk = (const H5O_link_t *) _mesg; + struct tm *tm; + char buf[128]; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_link_debug) + + /* check args */ + HDassert(f); + HDassert(lnk); + HDassert(stream); + HDassert(indent >= 0); + HDassert(fwidth >= 0); + + HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, + "Link Type:", (lnk->type == H5G_LINK_HARD ? "Hard" : + (lnk->type == H5G_LINK_SOFT ? "Soft" : "Unknown"))); + + tm = HDlocaltime(&(lnk->ctime)); + HDstrftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %Z", tm); + HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, + "Creation Time:", buf); + + HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, + "Link Name Character Set:", (lnk->cset == H5T_CSET_ASCII ? + "ASCII" : (lnk->cset == H5T_CSET_UTF8 ? "UTF-8" : "Unknown"))); + HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, + "Link Name:", lnk->name); + + switch(lnk->type) { + case H5G_LINK_HARD: + HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth, + "Object address:", lnk->u.hard.addr); + break; + + case H5G_LINK_SOFT: + HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, + "Link Value:", lnk->u.soft.name); + break; + + default: + break; + } /* end switch */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5O_link_debug() */ + diff --git a/src/H5Omtime.c b/src/H5Omtime.c index 4244733..d452ea2 100644 --- a/src/H5Omtime.c +++ b/src/H5Omtime.c @@ -32,11 +32,11 @@ #endif -static void *H5O_mtime_new_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p, H5O_shared_t *sh); +static void *H5O_mtime_new_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p); static herr_t H5O_mtime_new_encode(H5F_t *f, uint8_t *p, const void *_mesg); static size_t H5O_mtime_new_size(const H5F_t *f, const void *_mesg); -static void *H5O_mtime_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p, H5O_shared_t *sh); +static void *H5O_mtime_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p); static herr_t H5O_mtime_encode(H5F_t *f, uint8_t *p, const void *_mesg); static void *H5O_mtime_copy(const void *_mesg, void *_dest, unsigned update_flags); static size_t H5O_mtime_size(const H5F_t *f, const void *_mesg); @@ -115,8 +115,7 @@ H5FL_DEFINE(time_t); *------------------------------------------------------------------------- */ static void * -H5O_mtime_new_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const uint8_t *p, - H5O_shared_t UNUSED *sh) +H5O_mtime_new_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const uint8_t *p) { time_t *mesg; uint32_t tmp_time; /* Temporary copy of the time */ @@ -127,7 +126,6 @@ H5O_mtime_new_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const uint8_t *p, /* check args */ assert(f); assert(p); - assert (!sh); /* decode */ if(*p++ != H5O_MTIME_VERSION) @@ -171,8 +169,7 @@ done: *------------------------------------------------------------------------- */ static void * -H5O_mtime_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const uint8_t *p, - H5O_shared_t UNUSED *sh) +H5O_mtime_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const uint8_t *p) { time_t *mesg, the_time; int i; @@ -184,7 +181,6 @@ H5O_mtime_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const uint8_t *p, /* check args */ assert(f); assert(p); - assert (!sh); /* Initialize time zone information */ if (!ntzset) { diff --git a/src/H5Oname.c b/src/H5Oname.c index ba4433a..d6f7e3e 100644 --- a/src/H5Oname.c +++ b/src/H5Oname.c @@ -34,7 +34,7 @@ /* PRIVATE PROTOTYPES */ -static void *H5O_name_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p, H5O_shared_t *sh); +static void *H5O_name_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p); static herr_t H5O_name_encode(H5F_t *f, uint8_t *p, const void *_mesg); static void *H5O_name_copy(const void *_mesg, void *_dest, unsigned update_flags); static size_t H5O_name_size(const H5F_t *f, const void *_mesg); @@ -82,8 +82,7 @@ const H5O_class_t H5O_NAME[1] = {{ *------------------------------------------------------------------------- */ static void * -H5O_name_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const uint8_t *p, - H5O_shared_t UNUSED *sh) +H5O_name_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const uint8_t *p) { H5O_name_t *mesg; void *ret_value; /* Return value */ @@ -93,7 +92,6 @@ H5O_name_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const uint8_t *p, /* check args */ assert(f); assert(p); - assert (!sh); /* decode */ if (NULL==(mesg = H5MM_calloc(sizeof(H5O_name_t))) || diff --git a/src/H5Opkg.h b/src/H5Opkg.h index fdca31a..874ea91 100644 --- a/src/H5Opkg.h +++ b/src/H5Opkg.h @@ -23,6 +23,7 @@ #include "H5Oprivate.h" /* Object headers */ /* Other private headers needed by this file */ +#include "H5ACprivate.h" /* Metadata cache */ #include "H5SLprivate.h" /* Skip lists */ /* @@ -62,7 +63,7 @@ typedef struct H5O_class_t { int id; /*message type ID on disk */ const char *name; /*for debugging */ size_t native_size; /*size of native message */ - void *(*decode)(H5F_t*, hid_t, const uint8_t*, struct H5O_shared_t*); + void *(*decode)(H5F_t*, hid_t, const uint8_t*); herr_t (*encode)(H5F_t*, uint8_t*, const void*); void *(*copy)(const void*, void*, unsigned); /*copy native value */ size_t (*raw_size)(const H5F_t*, const void*);/*sizeof raw val */ @@ -73,7 +74,7 @@ typedef struct H5O_class_t { herr_t (*get_share)(H5F_t*, const void*, struct H5O_shared_t*); /* Get shared information */ herr_t (*set_share)(H5F_t*, void*, const struct H5O_shared_t*); /* Set shared information */ void *(*copy_file)(H5F_t *, void *, H5F_t *, hid_t, H5SL_t *, void *); /*copy native value to file */ - herr_t (*post_copy_file)(H5F_t *, const void *, H5G_entry_t *, hid_t, H5SL_t *); /*"post copy" action when copying native value to file */ + herr_t (*post_copy_file)(H5F_t *, const void *, H5O_loc_t *, void *, hbool_t *, hid_t, H5SL_t *); /*"post copy" action when copying native value to file */ herr_t (*debug)(H5F_t*, hid_t, const void*, FILE*, int, int); } H5O_class_t; @@ -107,6 +108,24 @@ typedef struct H5O_t { H5O_chunk_t *chunk; /*array of chunks */ } H5O_t; +/* H5O inherits cache-like properties from H5AC */ +H5_DLLVAR const H5AC_class_t H5AC_OHDR[1]; + +/* ID to type mapping */ +H5_DLLVAR const H5O_class_t *const message_type_g[19]; + +/* Declare external the free list for H5O_t's */ +H5FL_EXTERN(H5O_t); + +/* Declare external the free list for H5O_mesg_t sequences */ +H5FL_SEQ_EXTERN(H5O_mesg_t); + +/* Declare external the free list for H5O_chunk_t sequences */ +H5FL_SEQ_EXTERN(H5O_chunk_t); + +/* Declare external the free list for chunk_image blocks */ +H5FL_BLK_EXTERN(chunk_image); + /* * Null Message. (0x0000) */ @@ -118,6 +137,11 @@ H5_DLLVAR const H5O_class_t H5O_NULL[1]; H5_DLLVAR const H5O_class_t H5O_SDSPACE[1]; /* + * Link Information Message. (0x0002) + */ +H5_DLLVAR const H5O_class_t H5O_LINFO[1]; + +/* * Datatype Message. (0x0003) */ H5_DLLVAR const H5O_class_t H5O_DTYPE[1]; @@ -137,6 +161,12 @@ H5_DLLVAR const H5O_class_t H5O_FILL[1]; H5_DLLVAR const H5O_class_t H5O_FILL_NEW[1]; /* + * Link Message. (0x0006) + * + */ +H5_DLLVAR const H5O_class_t H5O_LINK[1]; + +/* * External File List Message. (0x0007) */ H5_DLLVAR const H5O_class_t H5O_EFL[1]; @@ -154,6 +184,11 @@ H5_DLLVAR const H5O_class_t H5O_BOGUS[1]; #endif /* H5O_ENABLE_BOGUS */ /* + * Group Information Message. (0x000a) + */ +H5_DLLVAR const H5O_class_t H5O_GINFO[1]; + +/* * Filter pipeline message. (0x000b) */ H5_DLLVAR const H5O_class_t H5O_PLINE[1]; @@ -203,16 +238,18 @@ H5_DLLVAR const H5O_class_t H5O_STAB[1]; H5_DLLVAR const H5O_class_t H5O_MTIME_NEW[1]; /* Package-local function prototypes */ -H5_DLL void * H5O_read_real(const H5G_entry_t *ent, const H5O_class_t *type, - int sequence, void *mesg, hid_t dxpl_id); +H5_DLL void * H5O_read_real(const H5O_loc_t *loc, const H5O_class_t *type, + int sequence, void *mesg, hid_t dxpl_id); +H5_DLL herr_t H5O_free_mesg(H5O_mesg_t *mesg); H5_DLL void * H5O_free_real(const H5O_class_t *type, void *mesg); +H5_DLL herr_t H5O_debug_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, haddr_t addr, FILE *stream, int indent, int fwidth); /* Shared object operators */ H5_DLL void * H5O_shared_read(H5F_t *f, hid_t dxpl_id, H5O_shared_t *shared, const H5O_class_t *type, void *mesg); -/* Symbol table operators */ -H5_DLL void *H5O_stab_fast(const H5G_cache_t *cache, const struct H5O_class_t *type, - void *_mesg); +/* Useful metadata cache callbacks */ +H5_DLL herr_t H5O_dest(H5F_t *f, H5O_t *oh); #endif /* _H5Opkg_H */ + diff --git a/src/H5Opline.c b/src/H5Opline.c index 391c758..d7fec7e 100644 --- a/src/H5Opline.c +++ b/src/H5Opline.c @@ -31,7 +31,7 @@ #define H5O_PLINE_VERSION 1 static herr_t H5O_pline_encode (H5F_t *f, uint8_t *p, const void *mesg); -static void *H5O_pline_decode (H5F_t *f, hid_t dxpl_id, const uint8_t *p, H5O_shared_t *sh); +static void *H5O_pline_decode (H5F_t *f, hid_t dxpl_id, const uint8_t *p); static void *H5O_pline_copy (const void *_mesg, void *_dest, unsigned update_flags); static size_t H5O_pline_size (const H5F_t *f, const void *_mesg); static herr_t H5O_pline_reset (void *_mesg); @@ -81,8 +81,7 @@ H5FL_DEFINE(H5O_pline_t); *------------------------------------------------------------------------- */ static void * -H5O_pline_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const uint8_t *p, - H5O_shared_t UNUSED *sh) +H5O_pline_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const uint8_t *p) { H5O_pline_t *pline = NULL; void *ret_value; diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h index d619806..b9c7511 100644 --- a/src/H5Oprivate.h +++ b/src/H5Oprivate.h @@ -35,8 +35,7 @@ #include "H5Spublic.h" /* Dataspace functions */ /* Private headers needed by this file */ -#include "H5FLprivate.h" /* Free Lists */ -#include "H5HGprivate.h" /* Global heap functions */ +#include "H5Fprivate.h" /* File access */ #include "H5Tprivate.h" /* Datatype functions */ #include "H5Zprivate.h" /* I/O pipeline filters */ @@ -45,6 +44,7 @@ #define H5O_MAX_SIZE 65536 /*max obj header data size */ #define H5O_NEW_MESG (-1) /*new message */ #define H5O_ALL (-1) /* Operate on all messages of type */ +#define H5O_FIRST (-2) /* Operate on first message of type */ /* Flags which are part of a message */ #define H5O_FLAG_CONSTANT 0x01u @@ -55,18 +55,24 @@ #define H5O_UPDATE_TIME 0x01u #define H5O_UPDATE_DATA_ONLY 0x02u +/* The object location information for an object */ +typedef struct H5O_loc_t { + H5F_t *file; /* File that object header is located within */ + haddr_t addr; /* File address of object header */ +} H5O_loc_t; + /* Header message IDs */ #define H5O_NULL_ID 0x0000 /* Null Message. */ #define H5O_SDSPACE_ID 0x0001 /* Simple Dataspace Message. */ -/* Complex dataspace is/was planned for message 0x0002 */ +#define H5O_LINFO_ID 0x0002 /* Link Info Message. */ #define H5O_DTYPE_ID 0x0003 /* Datatype Message. */ #define H5O_FILL_ID 0x0004 /* Fill Value Message. (Old) */ #define H5O_FILL_NEW_ID 0x0005 /* Fill Value Message. (New) */ -/* Compact data storage is/was planned for message 0x0006 */ +#define H5O_LINK_ID 0x0006 /* Link Message. */ #define H5O_EFL_ID 0x0007 /* External File List Message */ #define H5O_LAYOUT_ID 0x0008 /* Data Storage Layout Message. */ #define H5O_BOGUS_ID 0x0009 /* "Bogus" Message. */ -/* message 0x000a appears unused... */ +#define H5O_GINFO_ID 0x000a /* Group Info Message. */ #define H5O_PLINE_ID 0x000b /* Filter pipeline message. */ #define H5O_ATTR_ID 0x000c /* Attribute Message. */ #define H5O_NAME_ID 0x000d /* Object name message. */ @@ -77,6 +83,14 @@ #define H5O_MTIME_NEW_ID 0x0012 /* Modification time message. (New) */ /* + * Link Info Message. + * (Data structure in memory) + */ +typedef struct H5O_linfo_t { + hsize_t nlinks; /* Number of links in the group */ +} H5O_linfo_t; + +/* * Fill Value Message. (Old) * (Data structure in memory) */ @@ -102,6 +116,29 @@ typedef struct H5O_fill_new_t { } H5O_fill_new_t; /* + * Link message. + * (Data structure in memory) + */ +typedef struct H5O_link_hard_t { + haddr_t addr; /* Object header address */ +} H5O_link_hard_t; + +typedef struct H5O_link_soft_t { + char *name; /* Destination name */ +} H5O_link_soft_t; + +typedef struct H5O_link_t { + H5G_link_t type; /* Type of link */ + time_t ctime; /* Time link was createed */ + H5T_cset_t cset; /* Character set of link name */ + char *name; /* Link name */ + union { + H5O_link_hard_t hard; /* Information for hard links */ + H5O_link_soft_t soft; /* Information for soft links */ + } u; +} H5O_link_t; + +/* * External File List Message * (Data structure in memory) */ @@ -209,11 +246,7 @@ typedef struct H5O_name_t { */ typedef struct H5O_shared_t { - hbool_t in_gh; /*shared by global heap? */ - union { - H5HG_t gh; /*global heap info */ - H5G_entry_t ent; /*symbol table entry info */ - } u; + H5O_loc_t oloc; /*object location info */ } H5O_shared_t; /* @@ -250,38 +283,45 @@ typedef struct H5O_stab_t { typedef herr_t (*H5O_operator_t)(const void *mesg/*in*/, unsigned idx, void *operator_data/*in,out*/); +/* Depth of object location copy */ +typedef enum { + H5O_COPY_SHALLOW, /* Copy from source to destination, just copy field pointers */ + H5O_COPY_DEEP /* Deep copy from source to destination, including duplicating fields pointed to */ +} H5O_copy_depth_t; + /* Forward declarations for prototype arguments */ struct H5SL_t; /* General message operators */ +H5_DLL herr_t H5O_init(void); H5_DLL herr_t H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, - H5G_entry_t *ent/*out*/); -H5_DLL herr_t H5O_open(const H5G_entry_t *ent); -H5_DLL herr_t H5O_close(H5G_entry_t *ent); -H5_DLL int H5O_link(const H5G_entry_t *ent, int adjust, hid_t dxpl_id); -H5_DLL int H5O_count(H5G_entry_t *ent, unsigned type_id, hid_t dxpl_id); -H5_DLL htri_t H5O_exists(H5G_entry_t *ent, unsigned type_id, int sequence, + H5O_loc_t *loc/*out*/); +H5_DLL herr_t H5O_open(const H5O_loc_t *loc); +H5_DLL herr_t H5O_close(H5O_loc_t *loc); +H5_DLL int H5O_link(const H5O_loc_t *loc, int adjust, hid_t dxpl_id); +H5_DLL int H5O_count(H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id); +H5_DLL htri_t H5O_exists(H5O_loc_t *loc, unsigned type_id, int sequence, hid_t dxpl_id); -H5_DLL void *H5O_read(const H5G_entry_t *ent, unsigned type_id, int sequence, +H5_DLL void *H5O_read(const H5O_loc_t *loc, unsigned type_id, int sequence, void *mesg, hid_t dxpl_id); -H5_DLL int H5O_modify(H5G_entry_t *ent, unsigned type_id, +H5_DLL int H5O_modify(H5O_loc_t *loc, unsigned type_id, int overwrite, unsigned flags, unsigned update_flags, const void *mesg, hid_t dxpl_id); -H5_DLL struct H5O_t * H5O_protect(H5G_entry_t *ent, hid_t dxpl_id); -H5_DLL herr_t H5O_unprotect(H5G_entry_t *ent, struct H5O_t *oh, hid_t dxpl_id, - unsigned oh_flags); +H5_DLL struct H5O_t *H5O_protect(H5O_loc_t *loc, hid_t dxpl_id); +H5_DLL herr_t H5O_unprotect(H5O_loc_t *loc, struct H5O_t *oh, hid_t dxpl_id, + unsigned oh_flags); H5_DLL int H5O_append(H5F_t *f, hid_t dxpl_id, struct H5O_t *oh, unsigned type_id, unsigned flags, const void *mesg, unsigned * oh_flags_ptr); -H5_DLL herr_t H5O_touch(H5G_entry_t *ent, hbool_t force, hid_t dxpl_id); -H5_DLL herr_t H5O_touch_oh(H5F_t *f, hid_t dxpl_id, struct H5O_t *oh, - hbool_t force, unsigned * oh_flags_ptr); +H5_DLL herr_t H5O_touch(H5O_loc_t *loc, hbool_t force, hid_t dxpl_id); +H5_DLL herr_t H5O_touch_oh(H5F_t *f, hid_t dxpl_id, struct H5O_t *oh, + hbool_t force, unsigned *oh_flags_ptr); #ifdef H5O_ENABLE_BOGUS -H5_DLL herr_t H5O_bogus(H5G_entry_t *ent, hid_t dxpl_id); +H5_DLL herr_t H5O_bogus(H5O_loc_t *loc, hid_t dxpl_id); H5_DLL herr_t H5O_bogus_oh(H5F_t *f, hid_t dxpl_id, struct H5O_t *oh, - unsigned * oh_flags_ptr); + unsigned * oh_flags_ptr); #endif /* H5O_ENABLE_BOGUS */ -H5_DLL herr_t H5O_remove(H5G_entry_t *ent, unsigned type_id, int sequence, +H5_DLL herr_t H5O_remove(H5O_loc_t *loc, unsigned type_id, int sequence, hbool_t adj_link, hid_t dxpl_id); -H5_DLL herr_t H5O_remove_op(H5G_entry_t *ent, unsigned type_id, +H5_DLL herr_t H5O_remove_op(const H5O_loc_t *loc, unsigned type_id, int sequence, H5O_operator_t op, void *op_data, hbool_t adj_link, hid_t dxpl_id); H5_DLL herr_t H5O_reset(unsigned type_id, void *native); H5_DLL void *H5O_free(unsigned type_id, void *mesg); @@ -292,17 +332,24 @@ H5_DLL size_t H5O_raw_size(unsigned type_id, const H5F_t *f, const void *mesg); H5_DLL size_t H5O_mesg_size(unsigned type_id, const H5F_t *f, const void *mesg); H5_DLL herr_t H5O_get_share(unsigned type_id, H5F_t *f, const void *mesg, H5O_shared_t *share); H5_DLL herr_t H5O_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr); -H5_DLL herr_t H5O_get_info(H5G_entry_t *ent, H5O_stat_t *ostat, hid_t dxpl_id); -H5_DLL herr_t H5O_iterate(const H5G_entry_t *ent, unsigned type_id, H5O_operator_t op, +H5_DLL herr_t H5O_get_info(H5O_loc_t *loc, H5O_stat_t *ostat, hid_t dxpl_id); +H5_DLL herr_t H5O_iterate(const H5O_loc_t *loc, unsigned type_id, H5O_operator_t op, void *op_data, hid_t dxpl_id); -H5_DLL herr_t H5O_copy_header(const H5G_entry_t *ent_src, - H5G_entry_t *ent_dst /*out */, hid_t dxpl_id); -H5_DLL herr_t H5O_copy_header_map(const H5G_entry_t *ent_src, - H5G_entry_t *ent_dst /*out */, hid_t dxpl_id, struct H5SL_t *obj_list); +H5_DLL H5G_obj_t H5O_obj_type(H5O_loc_t *loc, hid_t dxpl_id); +H5_DLL herr_t H5O_copy_header(const H5O_loc_t *oloc_src, + H5O_loc_t *oloc_dst /*out */, hid_t dxpl_id); +H5_DLL herr_t H5O_copy_header_map(const H5O_loc_t *oloc_src, + H5O_loc_t *oloc_dst /*out */, hid_t dxpl_id, struct H5SL_t *map_list); H5_DLL herr_t H5O_debug_id(hid_t type_id, H5F_t *f, hid_t dxpl_id, const void *mesg, FILE *stream, int indent, int fwidth); H5_DLL herr_t H5O_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent, int fwidth); +/* + * These functions operate on object locations + */ +H5_DLL herr_t H5O_loc_reset(H5O_loc_t *loc); +H5_DLL herr_t H5O_loc_copy(H5O_loc_t *dst, const H5O_loc_t *src, H5O_copy_depth_t depth); + /* Layout operators */ H5_DLL size_t H5O_layout_meta_size(const H5F_t *f, const void *_mesg); diff --git a/src/H5Osdspace.c b/src/H5Osdspace.c index f4c5500..e09f029 100644 --- a/src/H5Osdspace.c +++ b/src/H5Osdspace.c @@ -25,7 +25,7 @@ /* PRIVATE PROTOTYPES */ -static void *H5O_sdspace_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p, H5O_shared_t *sh); +static void *H5O_sdspace_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p); static herr_t H5O_sdspace_encode(H5F_t *f, uint8_t *p, const void *_mesg); static void *H5O_sdspace_copy(const void *_mesg, void *_dest, unsigned update_flags); static size_t H5O_sdspace_size(const H5F_t *f, const void *_mesg); @@ -99,7 +99,7 @@ H5FL_ARR_EXTERN(hsize_t); --------------------------------------------------------------------------*/ static void * -H5O_sdspace_decode(H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *p, H5O_shared_t UNUSED *sh) +H5O_sdspace_decode(H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *p) { H5S_extent_t *sdim = NULL;/* New extent dimensionality structure */ void *ret_value; @@ -111,7 +111,6 @@ H5O_sdspace_decode(H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *p, H5O_shared_ /* check args */ assert(f); assert(p); - assert (!sh); /* decode */ if ((sdim = H5FL_CALLOC(H5S_extent_t)) != NULL) { @@ -147,8 +146,15 @@ H5O_sdspace_decode(H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *p, H5O_shared_ if (sdim->rank > 0) { if (NULL==(sdim->size=H5FL_ARR_MALLOC(hsize_t,sdim->rank))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - for (i = 0; i < sdim->rank; i++) + for (i = 0; i < sdim->rank; i++) { H5F_DECODE_LENGTH (f, p, sdim->size[i]); +#ifndef H5_HAVE_LARGE_HSIZET + /* Rudimentary check for overflow of the dimension size */ + if(sdim->size[i] == 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADSIZE, NULL, "invalid size detected"); +#endif /* H5_HAVE_LARGE_HSIZET */ + } /* end for */ + if (flags & H5S_VALID_MAX) { if (NULL==(sdim->max=H5FL_ARR_MALLOC(hsize_t,sdim->rank))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); @@ -463,3 +469,4 @@ H5O_sdspace_debug(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const void *mesg, FUNC_LEAVE_NOAPI(SUCCEED); } + diff --git a/src/H5Oshared.c b/src/H5Oshared.c index 09f273d..de58460 100644 --- a/src/H5Oshared.c +++ b/src/H5Oshared.c @@ -36,7 +36,7 @@ #include "H5MMprivate.h" /* Memory management */ #include "H5Opkg.h" /* Object headers */ -static void *H5O_shared_decode (H5F_t*, hid_t dxpl_id, const uint8_t*, H5O_shared_t *sh); +static void *H5O_shared_decode (H5F_t*, hid_t dxpl_id, const uint8_t*); static herr_t H5O_shared_encode (H5F_t*, uint8_t*, const void*); static void *H5O_shared_copy(const void *_mesg, void *_dest, unsigned update_flags); static size_t H5O_shared_size (const H5F_t*, const void *_mesg); @@ -99,39 +99,19 @@ H5O_shared_read(H5F_t *f, hid_t dxpl_id, H5O_shared_t *shared, const H5O_class_t { void *ret_value = NULL; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5O_shared_read); + FUNC_ENTER_NOAPI_NOINIT(H5O_shared_read) /* check args */ - assert(f); - assert(shared); - assert(type); - - /* Get the shared message */ - if (shared->in_gh) { - void *tmp_buf, *tmp_mesg; - - if (NULL==(tmp_buf = H5HG_read (f, dxpl_id, &(shared->u.gh), NULL))) - HGOTO_ERROR (H5E_OHDR, H5E_CANTLOAD, NULL, "unable to read shared message from global heap"); - tmp_mesg = (type->decode)(f, dxpl_id, tmp_buf, shared); - tmp_buf = H5MM_xfree (tmp_buf); - if (!tmp_mesg) - HGOTO_ERROR (H5E_OHDR, H5E_CANTLOAD, NULL, "unable to decode object header shared message"); - if (mesg) { - HDmemcpy (mesg, tmp_mesg, type->native_size); - H5MM_xfree (tmp_mesg); - } /* end if */ - else - ret_value = tmp_mesg; - } /* end if */ - else { - ret_value = H5O_read_real(&(shared->u.ent), type, 0, mesg, dxpl_id); - if (type->set_share && - (type->set_share)(f, ret_value, shared)<0) - HGOTO_ERROR (H5E_OHDR, H5E_CANTINIT, NULL, "unable to set sharing information"); - } /* end else */ + HDassert(f); + HDassert(shared); + HDassert(type); + + ret_value = H5O_read_real(&(shared->oloc), type, 0, mesg, dxpl_id); + if(type->set_share && (type->set_share)(f, ret_value, shared) < 0) + HGOTO_ERROR (H5E_OHDR, H5E_CANTINIT, NULL, "unable to set sharing information") done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_shared_read() */ @@ -158,35 +138,25 @@ H5O_shared_link_adj(H5F_t *f, hid_t dxpl_id, const H5O_shared_t *shared, int adj { int ret_value; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5O_shared_link_adj); + FUNC_ENTER_NOAPI_NOINIT(H5O_shared_link_adj) /* check args */ - assert(f); - assert(shared); - - if (shared->in_gh) { - /* - * The shared message is stored in the global heap. - * Adjust the reference count on the global heap message. - */ - if ((ret_value = H5HG_link (f, dxpl_id, &(shared->u.gh), adjust))<0) - HGOTO_ERROR (H5E_OHDR, H5E_LINK, FAIL, "unable to adjust shared object link count"); - } /* end if */ - else { - /* - * The shared message is stored in some other object header. - * The other object header must be in the same file as the - * new object header. Adjust the reference count on that - * object header. - */ - if (shared->u.ent.file->shared != f->shared) - HGOTO_ERROR(H5E_OHDR, H5E_LINK, FAIL, "interfile hard links are not allowed"); - if ((ret_value = H5O_link (&(shared->u.ent), adjust, dxpl_id))<0) - HGOTO_ERROR (H5E_OHDR, H5E_LINK, FAIL, "unable to adjust shared object link count"); - } /* end else */ + HDassert(f); + HDassert(shared); + + /* + * The shared message is stored in some other object header. + * The other object header must be in the same file as the + * new object header. Adjust the reference count on that + * object header. + */ + if(shared->oloc.file->shared != f->shared) + HGOTO_ERROR(H5E_OHDR, H5E_LINK, FAIL, "interfile hard links are not allowed") + if((ret_value = H5O_link(&(shared->oloc), adjust, dxpl_id)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_LINK, FAIL, "unable to adjust shared object link count") done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_shared_link_adj() */ @@ -208,53 +178,45 @@ done: *------------------------------------------------------------------------- */ static void * -H5O_shared_decode (H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *buf, H5O_shared_t UNUSED *sh) +H5O_shared_decode(H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *buf) { - H5O_shared_t *mesg=NULL; + H5O_shared_t *mesg = NULL; unsigned flags, version; void *ret_value; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5O_shared_decode); + FUNC_ENTER_NOAPI_NOINIT(H5O_shared_decode) /* Check args */ - assert (f); - assert (buf); - assert (!sh); + HDassert(f); + HDassert(buf); /* Decode */ - if (NULL==(mesg = H5MM_calloc (sizeof(H5O_shared_t)))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + if(NULL == (mesg = H5MM_calloc (sizeof(H5O_shared_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Version */ version = *buf++; - if (version!=H5O_SHARED_VERSION_1 && version!=H5O_SHARED_VERSION) - HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for shared object message"); + if(version != H5O_SHARED_VERSION_1 && version != H5O_SHARED_VERSION) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for shared object message") /* Get the shared information flags */ - flags = *buf++; - mesg->in_gh = (flags & 0x01); + flags = *buf++; /* Unused currently */ /* Skip reserved bytes (for version 1) */ - if(version==H5O_SHARED_VERSION_1) + if(version == H5O_SHARED_VERSION_1) buf += 6; /* Body */ - if (mesg->in_gh) { - H5F_addr_decode (f, &buf, &(mesg->u.gh.addr)); - INT32DECODE (buf, mesg->u.gh.idx); - } /* end if */ + if(version == H5O_SHARED_VERSION_1) + H5G_obj_ent_decode(f, &buf, &(mesg->oloc)); else { - if(version==H5O_SHARED_VERSION_1) - H5G_ent_decode (f, &buf, &(mesg->u.ent)); - else { - assert(version==H5O_SHARED_VERSION); - H5F_addr_decode (f, &buf, &(mesg->u.ent.header)); - mesg->u.ent.file=f; - } /* end else */ + HDassert(version == H5O_SHARED_VERSION); + H5F_addr_decode(f, &buf, &(mesg->oloc.addr)); + mesg->oloc.file = f; } /* end else */ /* Set return value */ - ret_value=mesg; + ret_value = mesg; done: if(ret_value==NULL) { @@ -262,8 +224,8 @@ done: H5MM_xfree(mesg); } /* end if */ - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_shared_decode() */ /*------------------------------------------------------------------------- @@ -286,44 +248,21 @@ static herr_t H5O_shared_encode (H5F_t *f, uint8_t *buf/*out*/, const void *_mesg) { const H5O_shared_t *mesg = (const H5O_shared_t *)_mesg; - unsigned flags; - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_shared_encode); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_shared_encode) /* Check args */ - assert (f); - assert (buf); - assert (mesg); + HDassert(f); + HDassert(buf); + HDassert(mesg); /* Encode */ *buf++ = H5O_SHARED_VERSION; - flags = mesg->in_gh ? 0x01 : 0x00; - *buf++ = flags; -#ifdef OLD_WAY - *buf++ = 0; /*reserved 1*/ - *buf++ = 0; /*reserved 2*/ - *buf++ = 0; /*reserved 3*/ - *buf++ = 0; /*reserved 4*/ - *buf++ = 0; /*reserved 5*/ - *buf++ = 0; /*reserved 6*/ - - if (mesg->in_gh) { - H5F_addr_encode (f, &buf, mesg->u.gh.addr); - INT32ENCODE (buf, mesg->u.gh.idx); - } /* end if */ - else - H5G_ent_encode (f, &buf, &(mesg->u.ent)); -#else /* OLD_WAY */ - if (mesg->in_gh) { - H5F_addr_encode (f, &buf, mesg->u.gh.addr); - INT32ENCODE (buf, mesg->u.gh.idx); - } /* end if */ - else - H5F_addr_encode (f, &buf, mesg->u.ent.header); -#endif /* OLD_WAY */ + *buf++ = 0; /* No flags currently */ + H5F_addr_encode(f, &buf, mesg->oloc.addr); - FUNC_LEAVE_NOAPI(SUCCEED); -} + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5O_shared_encode() */ /*------------------------------------------------------------------------- @@ -395,9 +334,7 @@ H5O_shared_size (const H5F_t *f, const void *_mesg) ret_value = 1 + /*version */ 1 + /*the flags field */ - (shared->in_gh ? - (H5F_SIZEOF_ADDR(f)+4) : /*sharing via global heap */ - H5F_SIZEOF_ADDR(f)); /*sharing by another obj hdr */ + H5F_SIZEOF_ADDR(f); /*sharing by another obj hdr */ FUNC_LEAVE_NOAPI(ret_value); } @@ -508,16 +445,12 @@ H5O_shared_copy_file(H5F_t UNUSED *file_src, void *native_src, if(NULL == (shared_dst = H5MM_malloc(sizeof(H5O_shared_t)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - /* Can't handle copying message in global heap currently */ - HDassert(!shared_src->in_gh); - shared_dst->in_gh = FALSE; - /* Reset group entry for new object */ - H5G_ent_reset(&(shared_dst->u.ent)); - shared_dst->u.ent.file = file_dst; + H5O_loc_reset(&(shared_dst->oloc)); + shared_dst->oloc.file = file_dst; /* Copy the shared object from source to destination */ - if(H5O_copy_header_map(&(shared_src->u.ent), &(shared_dst->u.ent), dxpl_id, map_list) < 0) + if(H5O_copy_header_map(&(shared_src->oloc), &(shared_dst->oloc), dxpl_id, map_list) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy object") /* Set return value */ @@ -547,37 +480,27 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5O_shared_debug (H5F_t UNUSED *f, hid_t dxpl_id, const void *_mesg, +H5O_shared_debug (H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const void *_mesg, FILE *stream, int indent, int fwidth) { const H5O_shared_t *mesg = (const H5O_shared_t *)_mesg; - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_shared_debug); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_shared_debug) /* Check args */ - assert (f); - assert (mesg); - assert (stream); - assert (indent>=0); - assert (fwidth>=0); - - if (mesg->in_gh) { - HDfprintf (stream, "%*s%-*s %s\n", indent, "", fwidth, - "Sharing method", - "Global heap"); - HDfprintf (stream, "%*s%-*s %a\n", indent, "", fwidth, - "Collection address:", - mesg->u.gh.addr); - HDfprintf (stream, "%*s%-*s %d\n", indent, "", fwidth, - "Object ID within collection:", - mesg->u.gh.idx); - } else { - HDfprintf (stream, "%*s%-*s %s\n", indent, "", fwidth, - "Sharing method", - "Obj Hdr"); - H5G_ent_debug (f, dxpl_id, &(mesg->u.ent), stream, indent, fwidth, - HADDR_UNDEF); - } - - FUNC_LEAVE_NOAPI(SUCCEED); -} + HDassert(f); + HDassert(mesg); + HDassert(stream); + HDassert(indent >= 0); + HDassert(fwidth >= 0); + + HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, + "Sharing method", + "Obj Hdr"); + HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth, + "Object address:", + mesg->oloc.addr); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5O_shared_debug() */ + diff --git a/src/H5Ostab.c b/src/H5Ostab.c index e03d6b1..b74fd8c 100644 --- a/src/H5Ostab.c +++ b/src/H5Ostab.c @@ -32,11 +32,12 @@ #include "H5Eprivate.h" /* Error handling */ #include "H5FLprivate.h" /* Free lists */ #include "H5Gpkg.h" /* Groups */ +#include "H5HLprivate.h" /* Local Heaps */ #include "H5Opkg.h" /* Object headers */ /* PRIVATE PROTOTYPES */ -static void *H5O_stab_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p, H5O_shared_t *sh); +static void *H5O_stab_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p); static herr_t H5O_stab_encode(H5F_t *f, uint8_t *p, const void *_mesg); static void *H5O_stab_copy(const void *_mesg, void *_dest, unsigned update_flags); static size_t H5O_stab_size(const H5F_t *f, const void *_mesg); @@ -45,7 +46,7 @@ static herr_t H5O_stab_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_ static void *H5O_stab_copy_file(H5F_t *file_src, void *native_src, H5F_t *file_dst, hid_t dxpl_id, H5SL_t *map_list, void *udata); static herr_t H5O_stab_post_copy_file(H5F_t *file_src, const void *mesg_src, - H5G_entry_t *loc_dst, hid_t dxpl_id, H5SL_t *map_list); + H5O_loc_t *dst_oloc, void *mesg_dst, hbool_t *modified, hid_t dxpl_id, H5SL_t *map_list); static herr_t H5O_stab_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); @@ -92,7 +93,7 @@ H5FL_DEFINE_STATIC(H5O_stab_t); *------------------------------------------------------------------------- */ static void * -H5O_stab_decode(H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *p, H5O_shared_t UNUSED *sh) +H5O_stab_decode(H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *p) { H5O_stab_t *stab=NULL; void *ret_value; /* Return value */ @@ -102,7 +103,6 @@ H5O_stab_decode(H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *p, H5O_shared_t U /* check args */ assert(f); assert(p); - assert(!sh); /* decode */ if (NULL==(stab = H5FL_CALLOC(H5O_stab_t))) @@ -159,53 +159,6 @@ H5O_stab_encode(H5F_t *f, uint8_t *p, const void *_mesg) /*------------------------------------------------------------------------- - * Function: H5O_stab_fast - * - * Purpose: Initializes a new message struct with info from the cache of - * a symbol table entry. - * - * Return: Success: Ptr to message struct, allocated if none - * supplied. - * - * Failure: NULL - * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Aug 6 1997 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -void * -H5O_stab_fast(const H5G_cache_t *cache, const H5O_class_t *type, void *_mesg) -{ - H5O_stab_t *ret_value; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5O_stab_fast); - - /* check args */ - assert(cache); - assert(type); - - if (H5O_STAB == type) { - if (_mesg) { - ret_value = (H5O_stab_t *) _mesg; - } else if (NULL==(ret_value = H5FL_MALLOC(H5O_stab_t))) { - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - } - ret_value->btree_addr = cache->stab.btree_addr; - ret_value->heap_addr = cache->stab.heap_addr; - } - else - ret_value=NULL; - -done: - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- * Function: H5O_stab_copy * * Purpose: Copies a message from _MESG to _DEST, allocating _DEST if @@ -357,12 +310,13 @@ done: *------------------------------------------------------------------------- */ static void * -H5O_stab_copy_file(H5F_t UNUSED *file_src, void *native_src, +H5O_stab_copy_file(H5F_t *file_src, void *native_src, H5F_t *file_dst, hid_t dxpl_id, H5SL_t UNUSED *map_list, void UNUSED *udata) { - H5O_stab_t *stab_src = (H5O_stab_t *) native_src; - H5O_stab_t *stab_dst = NULL; - void *ret_value; /* Return value */ + H5O_stab_t *stab_src = (H5O_stab_t *) native_src; + H5O_stab_t *stab_dst = NULL; + size_t size_hint; /* Local heap initial size */ + void *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_stab_copy_file) @@ -374,8 +328,13 @@ H5O_stab_copy_file(H5F_t UNUSED *file_src, void *native_src, if(NULL == (stab_dst = H5FL_MALLOC(H5O_stab_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - if(H5G_stab_copy_tmp(file_dst, stab_dst, dxpl_id) < 0) - HGOTO_ERROR(H5E_IO, H5E_CANTINIT, NULL, "unable to copy group symbol table") + /* Get the old local heap's size and use that as the hint for the new heap */ + if(H5HL_get_size(file_src, dxpl_id, stab_src->heap_addr, &size_hint) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTGETSIZE, NULL, "can't query local heap size") + + /* Create components of symbol table message */ + if(H5G_stab_create_components(file_dst, stab_dst, size_hint, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "can't create symbol table components") /* Set return value */ ret_value = stab_dst; @@ -392,7 +351,7 @@ done: /*------------------------------------------------------------------------- * Function: H5O_stab_post_copy_file * - * Purpose: Copies entries of a symbol table message from _MESG to _DEST in file + * Purpose: Finish copying a message from between files * * Return: Non-negative on success/Negative on failure * @@ -403,10 +362,11 @@ done: */ static herr_t H5O_stab_post_copy_file(H5F_t *file_src, const void *mesg_src, - H5G_entry_t *loc_dst, hid_t dxpl_id, H5SL_t *map_list) + H5O_loc_t *dst_oloc, void *mesg_dst, hbool_t UNUSED *modified, hid_t dxpl_id, H5SL_t *map_list) { - H5G_bt_it_ud5_t udata; /* B-tree user data */ - const H5O_stab_t *stab_src = (const H5O_stab_t *) mesg_src; + H5G_bt_it_ud5_t udata; /* B-tree user data */ + const H5O_stab_t *stab_src = (const H5O_stab_t *)mesg_src; + H5O_stab_t *stab_dst = (H5O_stab_t *)mesg_dst; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_stab_post_copy_file) @@ -414,13 +374,16 @@ H5O_stab_post_copy_file(H5F_t *file_src, const void *mesg_src, /* check args */ HDassert(file_src); HDassert(stab_src); - HDassert(loc_dst->file); + HDassert(H5F_addr_defined(dst_oloc->addr)); + HDassert(dst_oloc->file); + HDassert(stab_dst); HDassert(map_list); /* Set up B-tree iteration user data */ udata.map_list = map_list; - udata.heap_addr = stab_src->heap_addr; - udata.loc_dst = loc_dst; + udata.src_heap_addr = stab_src->heap_addr; + udata.dst_file = dst_oloc->file; + udata.dst_stab = stab_dst; /* Iterate over objects in group, copying them */ if((H5B_iterate(file_src, dxpl_id, H5B_SNODE, H5G_node_copy, stab_src->btree_addr, &udata)) < 0) @@ -225,8 +225,18 @@ static herr_t H5P_init_interface(void) { H5P_genclass_t *root_class; /* Pointer to root property list class created */ - H5P_genclass_t *ocrt_class; /* Pointer to object (dataset, group, or datatype) creation property list class created */ H5P_genclass_t *pclass; /* Pointer to property list class to create */ + /* Group creation property class variables. In sequence, they are, + * - Creation property list class to modify + * - Default value for "group info" + */ + H5P_genclass_t *gcrt_class; /* Pointer to group creation property list class created */ + H5O_ginfo_t ginfo = H5G_CRT_GROUP_INFO_DEF; + /* Object creation property class variables. In sequence, they are, + * - Creation property list class to modify + * - Default value for "intermediate group creation" + */ + H5P_genclass_t *ocrt_class; /* Pointer to object (dataset, group, or datatype) creation property list class created */ unsigned intmd_group = H5G_CRT_INTERMEDIATE_GROUP_DEF; size_t nprops; /* Number of properties */ herr_t ret_value = SUCCEED; @@ -276,11 +286,48 @@ H5P_init_interface(void) HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") } /* end if */ + /* Register the group creation and group access property classes */ + /* (Register the group property classes before file property classes, so + * file creation property class can inherit from group creation property + * class, which is used to allow application to control the group creation + * properties of the root group of a file. -QAK) + */ + + /* Allocate the group creation class */ + HDassert(H5P_CLS_GROUP_CREATE_g == (-1)); + if(NULL == (gcrt_class = H5P_create_class(ocrt_class, "group create", 1, NULL, NULL, NULL, NULL, NULL, NULL))) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "class initialization failed"); + + /* Register the group creation class */ + if((H5P_CLS_GROUP_CREATE_g = H5I_register(H5I_GENPROP_CLS, gcrt_class)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "can't register property list class"); + + /* Get the number of properties in the class */ + if(H5P_get_nprops_pclass(gcrt_class, &nprops, FALSE) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "can't query number of properties") + + /* Assume that if there are properties in the class, they are the default ones */ + if(nprops == 0) { + /* Register group info */ + if(H5P_register(gcrt_class, H5G_CRT_GROUP_INFO_NAME, H5G_CRT_GROUP_INFO_SIZE, + &ginfo, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + } /* end if */ + + /* Allocate the group access class */ + HDassert(H5P_CLS_GROUP_ACCESS_g == (-1)); + if(NULL == (pclass = H5P_create_class(root_class, "group access", 1, NULL, NULL, NULL, NULL, NULL, NULL))) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "class initialization failed"); + + /* Register the group access class */ + if((H5P_CLS_GROUP_ACCESS_g = H5I_register(H5I_GENPROP_CLS, pclass)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "can't register property list class"); + /* Register the file creation and file access property classes */ /* Allocate the file creation class */ assert(H5P_CLS_FILE_CREATE_g==(-1)); - if (NULL==(pclass = H5P_create_class (root_class,"file create",1,NULL,NULL,NULL,NULL,NULL,NULL))) + if (NULL==(pclass = H5P_create_class (gcrt_class,"file create",1,NULL,NULL,NULL,NULL,NULL,NULL))) HGOTO_ERROR (H5E_PLIST, H5E_CANTINIT, FAIL, "class initialization failed"); /* Register the file creation class */ @@ -325,6 +372,8 @@ H5P_init_interface(void) if ((H5P_CLS_DATASET_XFER_g = H5I_register (H5I_GENPROP_CLS, pclass))<0) HGOTO_ERROR (H5E_PLIST, H5E_CANTREGISTER, FAIL, "can't register property list class"); + /* Register the mount property classes */ + /* Allocate the mount class */ assert(H5P_CLS_MOUNT_g==(-1)); if (NULL==(pclass = H5P_create_class (root_class,"file mount",1,NULL,NULL,NULL,NULL,NULL,NULL))) @@ -334,24 +383,7 @@ H5P_init_interface(void) if ((H5P_CLS_MOUNT_g = H5I_register (H5I_GENPROP_CLS, pclass))<0) HGOTO_ERROR (H5E_PLIST, H5E_CANTREGISTER, FAIL, "can't register property list class"); - - /* Allocate the group creation class */ - assert(H5P_CLS_GROUP_CREATE_g==(-1)); - if (NULL==(pclass = H5P_create_class (ocrt_class,"group create",1,NULL,NULL,NULL,NULL,NULL,NULL))) - HGOTO_ERROR (H5E_PLIST, H5E_CANTINIT, FAIL, "class initialization failed"); - - /* Register the group creation class */ - if ((H5P_CLS_GROUP_CREATE_g = H5I_register (H5I_GENPROP_CLS, pclass))<0) - HGOTO_ERROR (H5E_PLIST, H5E_CANTREGISTER, FAIL, "can't register property list class"); - - /* Allocate the group access class */ - assert(H5P_CLS_GROUP_ACCESS_g==(-1)); - if (NULL==(pclass = H5P_create_class (root_class,"group access",1,NULL,NULL,NULL,NULL,NULL,NULL))) - HGOTO_ERROR (H5E_PLIST, H5E_CANTINIT, FAIL, "class initialization failed"); - - /* Register the group access class */ - if ((H5P_CLS_GROUP_ACCESS_g = H5I_register (H5I_GENPROP_CLS, pclass))<0) - HGOTO_ERROR (H5E_PLIST, H5E_CANTREGISTER, FAIL, "can't register property list class"); + /* Register the named datatype creation and named datatype access property classes */ /* Allocate the datatype creation class */ assert(H5P_CLS_DATATYPE_CREATE_g==(-1)); diff --git a/src/H5Pgcpl.c b/src/H5Pgcpl.c index 8b22015..388d453 100644 --- a/src/H5Pgcpl.c +++ b/src/H5Pgcpl.c @@ -30,6 +30,8 @@ * * Purpose: Set the "size hint" for creating local heaps for a group. * + * Note: XXX: Add [meaningful] tests for this routine! -QAK + * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol @@ -71,6 +73,8 @@ done: * Purpose: Returns the local heap size hint, which is used for creating * groups * + * Note: XXX: Add [meaningful] tests for this routine! -QAK + * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol @@ -104,3 +108,193 @@ done: FUNC_LEAVE_API(ret_value) } /* end H5Pget_local_heap_size_hint() */ + +/*------------------------------------------------------------------------- + * Function: H5Pset_link_phase_change + * + * Purpose: Set the maximum # of links to store "compactly" and the + * minimum # of links to store "densely". (These should + * overlap). + * + * Note: Currently both of these must be updated at the same time. + * + * Note: XXX: Add [meaningful] tests for this routine! -QAK + * + * Note: Come up with better name & description! -QAK + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * August 29, 2005 + *------------------------------------------------------------------------- + */ +herr_t +H5Pset_link_phase_change(hid_t plist_id, unsigned max_compact, unsigned min_dense) +{ + H5P_genplist_t *plist; /* Property list pointer */ + H5O_ginfo_t ginfo; /* Group information structure */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Pset_link_phase_change, FAIL) + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(plist_id, H5P_GROUP_CREATE))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Get group info */ + if(H5P_get(plist, H5G_CRT_GROUP_INFO_NAME, &ginfo) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get group info") + + /* Update fields */ + ginfo.max_compact = max_compact; + ginfo.min_dense = min_dense; + + /* Set group info */ + if(H5P_set(plist, H5G_CRT_GROUP_INFO_NAME, &ginfo) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set group info") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pset_link_phase_change() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pget_link_phase_change + * + * Purpose: Returns the max. # of compact links & the min. # of dense + * links, which are used for storing groups + * + * Note: XXX: Add [meaningful] tests for this routine! -QAK + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * August 29, 2005 + *------------------------------------------------------------------------- + */ +herr_t +H5Pget_link_phase_change(hid_t plist_id, unsigned *max_compact /*out*/, unsigned *min_dense /*out*/) +{ + herr_t ret_value = SUCCEED; /* return value */ + + FUNC_ENTER_API(H5Pget_link_phase_change, FAIL) + + /* Get values */ + if(max_compact || min_dense) { + H5P_genplist_t *plist; /* Property list pointer */ + H5O_ginfo_t ginfo; /* Group information structure */ + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(plist_id, H5P_GROUP_CREATE))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Get group info */ + if(H5P_get(plist, H5G_CRT_GROUP_INFO_NAME, &ginfo) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get group info") + + if(max_compact) + *max_compact = ginfo.max_compact; + if(min_dense) + *min_dense = ginfo.min_dense; + } /* end if */ + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pget_link_phase_change() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pset_est_link_info + * + * Purpose: Set the estimates for the number of entries and length of each + * entry name in a group. + * + * Note: Currently both of these must be updated at the same time. + * + * Note: EST_NUM_ENTRIES applies only when the number of entries than + * the MAX_COMPACT # of entries (from H5Pset_link_phase_change). + * + * Note: XXX: Add [meaningful] tests for this routine! -QAK + * + * Note: Come up with better name & description? -QAK + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * September 6, 2005 + *------------------------------------------------------------------------- + */ +herr_t +H5Pset_est_link_info(hid_t plist_id, unsigned est_num_entries, unsigned est_name_len) +{ + H5P_genplist_t *plist; /* Property list pointer */ + H5O_ginfo_t ginfo; /* Group information structure */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Pset_est_link_info, FAIL) + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(plist_id, H5P_GROUP_CREATE))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Get group info */ + if(H5P_get(plist, H5G_CRT_GROUP_INFO_NAME, &ginfo) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get group info") + + /* Update fields */ + ginfo.est_num_entries = est_num_entries; + ginfo.est_name_len = est_name_len; + + /* Set group info */ + if(H5P_set(plist, H5G_CRT_GROUP_INFO_NAME, &ginfo) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set group info") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pset_est_link_info() */ + + +/*------------------------------------------------------------------------- + * Function: H5Pget_est_link_info + * + * Purpose: Returns the est. # of links in a group & the est. length of + * the name of each link. + * + * Note: XXX: Add [meaningful] tests for this routine! -QAK + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * September 6, 2005 + *------------------------------------------------------------------------- + */ +herr_t +H5Pget_est_link_info(hid_t plist_id, unsigned *est_num_entries /*out*/, unsigned *est_name_len /*out*/) +{ + herr_t ret_value = SUCCEED; /* return value */ + + FUNC_ENTER_API(H5Pget_est_link_info, FAIL) + + /* Get values */ + if(est_num_entries || est_name_len) { + H5P_genplist_t *plist; /* Property list pointer */ + H5O_ginfo_t ginfo; /* Group information structure */ + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(plist_id, H5P_GROUP_CREATE))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID") + + /* Get group info */ + if(H5P_get(plist, H5G_CRT_GROUP_INFO_NAME, &ginfo) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get group info") + + if(est_num_entries) + *est_num_entries = ginfo.est_num_entries; + if(est_name_len) + *est_name_len = ginfo.est_name_len; + } /* end if */ + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Pget_est_link_info() */ + diff --git a/src/H5Pocpl.c b/src/H5Pocpl.c index 7132a93..8277ddc 100755 --- a/src/H5Pocpl.c +++ b/src/H5Pocpl.c @@ -31,6 +31,8 @@ * Purpose: set crt_intmd_group so that H5Gcreate(), H5Dcreate, etc. * will create missing groups along the given path "name" * + * Note: XXX: This property should really be an access property. -QAK + * * Return: Non-negative on success/Negative on failure * * Programmer: Peter Cao diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h index 8d5e015..a470dfd 100644 --- a/src/H5Ppublic.h +++ b/src/H5Ppublic.h @@ -334,6 +334,10 @@ H5_DLL herr_t H5Pget_create_intermediate_group(hid_t plist_id, unsigned *crt_int H5_DLL herr_t H5Pset_local_heap_size_hint(hid_t plist_id, size_t size_hint); H5_DLL herr_t H5Pget_local_heap_size_hint(hid_t plist_id, size_t *size_hint /*out*/); +H5_DLL herr_t H5Pset_link_phase_change(hid_t plist_id, unsigned max_compact, unsigned min_dense); +H5_DLL herr_t H5Pget_link_phase_change(hid_t plist_id, unsigned *max_compact /*out*/, unsigned *min_dense /*out*/); +H5_DLL herr_t H5Pset_est_link_info(hid_t plist_id, unsigned est_num_entries, unsigned est_name_len); +H5_DLL herr_t H5Pget_est_link_info(hid_t plist_id, unsigned *est_num_entries /* out */, unsigned *est_name_len /* out */); #ifdef __cplusplus } @@ -12,29 +12,30 @@ * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -#define H5F_PACKAGE /*suppress error about including H5Fpkg */ - /* Interface initialization */ #define H5_INTERFACE_INIT_FUNC H5R_init_interface -#include "H5private.h" /* Generic Functions */ -#include "H5Iprivate.h" /* ID Functions */ -#include "H5Dprivate.h" /* Datasets */ -#include "H5Eprivate.h" /* Error handling */ -#include "H5Fpkg.h" /* Files */ -#include "H5Gprivate.h" /* Groups */ -#include "H5HGprivate.h" /* Global Heaps */ -#include "H5MMprivate.h" /* Memory Management */ -#include "H5Rprivate.h" /* References */ -#include "H5Sprivate.h" /* Dataspace functions */ -#include "H5Tprivate.h" /* Datatypes */ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Fprivate.h" /* File access */ +#include "H5Gprivate.h" /* Groups */ +#include "H5HGprivate.h" /* Global Heaps */ +#include "H5Iprivate.h" /* IDs */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5Rprivate.h" /* References */ +#include "H5Sprivate.h" /* Dataspaces */ + +/* Local macro definitions */ + +/* Number of reserved IDs in ID group */ +#define H5R_RESERVED_ATOMS 0 /* Static functions */ -static herr_t H5R_create(void *ref, H5G_entry_t *loc, const char *name, +static herr_t H5R_create(void *ref, H5G_loc_t *loc, const char *name, H5R_type_t ref_type, H5S_t *space, hid_t dxpl_id); static hid_t H5R_dereference(H5F_t *file, hid_t dxpl_id, H5R_type_t ref_type, void *_ref); -static H5S_t * H5R_get_region(H5F_t *file, hid_t dxpl_id, H5R_type_t ref_type, void *_ref); +static H5S_t * H5R_get_region(H5F_t *file, hid_t dxpl_id, void *_ref); static H5G_obj_t H5R_get_obj_type(H5F_t *file, hid_t dxpl_id, H5R_type_t ref_type, void *_ref); @@ -60,7 +61,7 @@ H5R_init_interface(void) /* Initialize the atom group for the file IDs */ if (H5I_register_type(H5I_REFERENCE, H5I_REFID_HASHSIZE, H5R_RESERVED_ATOMS, (H5I_free_t)NULL)<0) - HGOTO_ERROR (H5E_REFERENCE, H5E_CANTINIT, FAIL, "unable to initialize interface"); + HGOTO_ERROR(H5E_REFERENCE, H5E_CANTINIT, FAIL, "unable to initialize interface"); done: FUNC_LEAVE_NOAPI(ret_value); @@ -113,7 +114,7 @@ H5R_term_interface(void) USAGE herr_t H5R_create(ref, loc, name, ref_type, space) void *ref; OUT: Reference created - H5G_entry_t *loc; IN: File location used to locate object pointed to + H5G_loc_t *loc; IN: File location used to locate object pointed to const char *name; IN: Name of object at location LOC_ID of object pointed to H5R_type_t ref_type; IN: Type of reference to create @@ -133,25 +134,25 @@ H5R_term_interface(void) REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5R_create(void *_ref, H5G_entry_t *loc, const char *name, H5R_type_t ref_type, H5S_t *space, hid_t dxpl_id) +H5R_create(void *_ref, H5G_loc_t *loc, const char *name, H5R_type_t ref_type, H5S_t *space, hid_t dxpl_id) { - H5G_stat_t sb; /* Stat buffer for retrieving OID */ - herr_t ret_value=SUCCEED; /* Return value */ + H5G_stat_t sb; /* Stat buffer for retrieving OID */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5R_create); + FUNC_ENTER_NOAPI_NOINIT(H5R_create) - assert(_ref); - assert(loc); - assert(name); - assert(ref_type>H5R_BADTYPE || ref_type<H5R_MAXTYPE); + HDassert(_ref); + HDassert(loc); + HDassert(name); + HDassert(ref_type > H5R_BADTYPE || ref_type < H5R_MAXTYPE); - if (H5G_get_objinfo (loc, name, 0, &sb, dxpl_id)<0) - HGOTO_ERROR (H5E_REFERENCE, H5E_NOTFOUND, FAIL, "unable to stat object"); + if(H5G_get_objinfo(loc, name, 0, &sb, dxpl_id) < 0) + HGOTO_ERROR(H5E_REFERENCE, H5E_NOTFOUND, FAIL, "unable to stat object") switch(ref_type) { case H5R_OBJECT: { - hobj_ref_t *ref=(hobj_ref_t *)_ref; /* Get pointer to correct type of reference struct */ + hobj_ref_t *ref = (hobj_ref_t *)_ref; /* Get pointer to correct type of reference struct */ *ref=sb.u.obj.objno; break; @@ -160,7 +161,7 @@ H5R_create(void *_ref, H5G_entry_t *loc, const char *name, H5R_type_t ref_type, case H5R_DATASET_REGION: { H5HG_t hobjid; /* Heap object ID */ - hdset_reg_ref_t *ref=(hdset_reg_ref_t *)_ref; /* Get pointer to correct type of reference struct */ + hdset_reg_ref_t *ref = (hdset_reg_ref_t *)_ref; /* Get pointer to correct type of reference struct */ hssize_t buf_size; /* Size of buffer needed to serialize selection */ uint8_t *p; /* Pointer to OID to store */ uint8_t *buf; /* Buffer to store serialized selection in */ @@ -170,51 +171,51 @@ H5R_create(void *_ref, H5G_entry_t *loc, const char *name, H5R_type_t ref_type, /* Set up information for dataset region */ /* Return any previous heap block to the free list if we are garbage collecting */ - if(loc->file->shared->gc_ref) { + if(H5F_GC_REF(loc->oloc->file)) { /* Check for an existing heap ID in the reference */ - for(u=0, heapid_found=0, p=(uint8_t *)ref; u<H5R_DSET_REG_REF_BUF_SIZE; u++) - if(p[u]!=0) { - heapid_found=1; + for(u = 0, heapid_found = 0, p = (uint8_t *)ref; u < H5R_DSET_REG_REF_BUF_SIZE; u++) + if(p[u] != 0) { + heapid_found = 1; break; } /* end if */ - if(heapid_found!=0) { + if(heapid_found != 0) { /* Return heap block to free list */ } /* end if */ } /* end if */ /* Zero the heap ID out, may leak heap space if user is re-using reference and doesn't have garbage collection on */ - HDmemset(ref,H5R_DSET_REG_REF_BUF_SIZE,0); + HDmemset(ref, H5R_DSET_REG_REF_BUF_SIZE, 0); /* Get the amount of space required to serialize the selection */ - if ((buf_size = H5S_SELECT_SERIAL_SIZE(space)) < 0) - HGOTO_ERROR(H5E_REFERENCE, H5E_CANTINIT, FAIL, "Invalid amount of space for serializing selection"); + if((buf_size = H5S_SELECT_SERIAL_SIZE(space)) < 0) + HGOTO_ERROR(H5E_REFERENCE, H5E_CANTINIT, FAIL, "Invalid amount of space for serializing selection") /* Increase buffer size to allow for the dataset OID */ - buf_size+=sizeof(haddr_t); + buf_size += sizeof(haddr_t); /* Allocate the space to store the serialized information */ - H5_CHECK_OVERFLOW(buf_size,hssize_t,size_t); - if (NULL==(buf = H5MM_malloc((size_t)buf_size))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + H5_CHECK_OVERFLOW(buf_size, hssize_t, size_t); + if(NULL == (buf = H5MM_malloc((size_t)buf_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") /* Serialize information for dataset OID */ - p=(uint8_t *)buf; - H5F_addr_encode(loc->file,&p,sb.u.obj.objno); + p = (uint8_t *)buf; + H5F_addr_encode(loc->oloc->file, &p, sb.u.obj.objno); /* Serialize the selection */ - if (H5S_SELECT_SERIALIZE(space,p) < 0) - HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOPY, FAIL, "Unable to serialize selection"); + if(H5S_SELECT_SERIALIZE(space, p) < 0) + HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOPY, FAIL, "Unable to serialize selection") /* Save the serialized buffer for later */ - H5_CHECK_OVERFLOW(buf_size,hssize_t,size_t); - if(H5HG_insert(loc->file,dxpl_id,(size_t)buf_size,buf,&hobjid)<0) - HGOTO_ERROR(H5E_REFERENCE, H5E_WRITEERROR, FAIL, "Unable to serialize selection"); + H5_CHECK_OVERFLOW(buf_size, hssize_t, size_t); + if(H5HG_insert(loc->oloc->file, dxpl_id, (size_t)buf_size, buf, &hobjid) < 0) + HGOTO_ERROR(H5E_REFERENCE, H5E_WRITEERROR, FAIL, "Unable to serialize selection") /* Serialize the heap ID and index for storage in the file */ - p=(uint8_t *)ref; - H5F_addr_encode(loc->file,&p,hobjid.addr); - INT32ENCODE(p,hobjid.idx); + p = (uint8_t *)ref; + H5F_addr_encode(loc->oloc->file, &p, hobjid.addr); + INT32ENCODE(p, hobjid.idx); /* Free the buffer we serialized data in */ H5MM_xfree(buf); @@ -222,17 +223,17 @@ H5R_create(void *_ref, H5G_entry_t *loc, const char *name, H5R_type_t ref_type, } case H5R_INTERNAL: - HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "Internal references are not yet supported"); + HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "Internal references are not yet supported") case H5R_BADTYPE: case H5R_MAXTYPE: default: assert("unknown reference type" && 0); - HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (unknown reference type)"); + HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (unknown reference type)") } /* end switch */ done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5R_create() */ @@ -266,33 +267,33 @@ done: herr_t H5Rcreate(void *ref, hid_t loc_id, const char *name, H5R_type_t ref_type, hid_t space_id) { - H5G_entry_t *loc = NULL; /* File location */ + H5G_loc_t loc; /* File location */ H5S_t *space = NULL; /* Pointer to dataspace containing region */ - herr_t ret_value; /* Return value */ + herr_t ret_value; /* Return value */ - FUNC_ENTER_API(H5Rcreate, FAIL); + FUNC_ENTER_API(H5Rcreate, FAIL) H5TRACE5("e","xisRti",ref,loc_id,name,ref_type,space_id); /* Check args */ - if(ref==NULL) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference pointer"); - if (NULL==(loc=H5G_loc (loc_id))) - HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a location"); - if (!name || !*name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name given"); - if(ref_type<=H5R_BADTYPE || ref_type>=H5R_MAXTYPE) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference type"); - if(ref_type!=H5R_OBJECT && ref_type!=H5R_DATASET_REGION) - HGOTO_ERROR (H5E_ARGS, H5E_UNSUPPORTED, FAIL, "reference type not supported"); - if (space_id!=(-1) && (NULL==(space=H5I_object_verify(space_id,H5I_DATASPACE)))) - HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace"); + if(ref == NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference pointer") + if(H5G_loc(loc_id, &loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + if(!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name given") + if(ref_type <= H5R_BADTYPE || ref_type >= H5R_MAXTYPE) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference type") + if(ref_type != H5R_OBJECT && ref_type != H5R_DATASET_REGION) + HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "reference type not supported") + if(space_id != (-1) && (NULL == (space = H5I_object_verify(space_id, H5I_DATASPACE)))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") /* Create reference */ - if ((ret_value=H5R_create(ref,loc,name,ref_type,space, H5AC_dxpl_id))<0) - HGOTO_ERROR (H5E_REFERENCE, H5E_CANTINIT, FAIL, "unable to create reference"); + if((ret_value = H5R_create(ref, &loc, name, ref_type, space, H5AC_dxpl_id)) < 0) + HGOTO_ERROR(H5E_REFERENCE, H5E_CANTINIT, FAIL, "unable to create reference") done: - FUNC_LEAVE_API(ret_value); + FUNC_LEAVE_API(ret_value) } /* end H5Rcreate() */ @@ -321,52 +322,50 @@ done: static hid_t H5R_dereference(H5F_t *file, hid_t dxpl_id, H5R_type_t ref_type, void *_ref) { - H5D_t *dset; /* Pointer to dataset to open */ - H5T_t *type; /* Pointer to datatype to open */ - H5G_t *group; /* Pointer to group to open */ - H5G_entry_t ent; /* Symbol table entry */ + H5O_loc_t oloc; /* Object location */ + H5G_name_t path; /* Path of object */ + H5G_loc_t loc; /* Group location */ uint8_t *p; /* Pointer to OID to store */ int oid_type; /* type of object being dereferenced */ hid_t ret_value; - FUNC_ENTER_NOAPI_NOINIT(H5R_dereference); + FUNC_ENTER_NOAPI_NOINIT(H5R_dereference) - assert(_ref); - assert(ref_type>H5R_BADTYPE || ref_type<H5R_MAXTYPE); - assert(file); + HDassert(_ref); + HDassert(ref_type > H5R_BADTYPE || ref_type < H5R_MAXTYPE); + HDassert(file); - /* Initialize the symbol table entry */ - H5G_ent_reset(&ent); - ent.type=H5G_NOTHING_CACHED; - ent.file=file; + /* Initialize the object location */ + H5O_loc_reset(&oloc); + oloc.file = file; switch(ref_type) { case H5R_OBJECT: { - hobj_ref_t *ref=(hobj_ref_t *)_ref; /* Only object references currently supported */ + hobj_ref_t *ref = (hobj_ref_t *)_ref; /* Only object references currently supported */ - ent.header=*ref; + oloc.addr = *ref; } /* end case */ break; case H5R_DATASET_REGION: { - hdset_reg_ref_t *ref=(hdset_reg_ref_t *)_ref; /* Get pointer to correct type of reference struct */ + hdset_reg_ref_t *ref = (hdset_reg_ref_t *)_ref; /* Get pointer to correct type of reference struct */ H5HG_t hobjid; /* Heap object ID */ uint8_t *buf; /* Buffer to store serialized selection in */ /* Get the heap ID for the dataset region */ - p=(uint8_t *)ref; - H5F_addr_decode(ent.file,(const uint8_t **)&p,&(hobjid.addr)); - INT32DECODE(p,hobjid.idx); + p = (uint8_t *)ref; + H5F_addr_decode(oloc.file, (const uint8_t **)&p, &(hobjid.addr)); + INT32DECODE(p, hobjid.idx); /* Get the dataset region from the heap (allocate inside routine) */ - if((buf=H5HG_read(ent.file,dxpl_id,&hobjid,NULL))==NULL) - HGOTO_ERROR(H5E_REFERENCE, H5E_READERROR, FAIL, "Unable to read dataset region information"); + if((buf = H5HG_read(oloc.file, dxpl_id, &hobjid, NULL)) == NULL) + HGOTO_ERROR(H5E_REFERENCE, H5E_READERROR, FAIL, "Unable to read dataset region information") /* Get the object oid for the dataset */ - p=(uint8_t *)buf; - H5F_addr_decode(ent.file,(const uint8_t **)&p,&(ent.header)); + p = (uint8_t *)buf; + H5F_addr_decode(oloc.file, (const uint8_t **)&p, &(oloc.addr)); /* Free the buffer allocated in H5HG_read() */ H5MM_xfree(buf); @@ -374,62 +373,79 @@ H5R_dereference(H5F_t *file, hid_t dxpl_id, H5R_type_t ref_type, void *_ref) break; case H5R_INTERNAL: - HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "Internal references are not yet supported"); + HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "Internal references are not yet supported") case H5R_BADTYPE: case H5R_MAXTYPE: default: - assert("unknown reference type" && 0); - HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (unknown reference type)"); + HDassert("unknown reference type" && 0); + HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (unknown reference type)") } /* end switch */ /* Check to make certain that this object hasn't been deleted since the reference was created */ - if(H5O_link(&ent,0,dxpl_id)<=0) - HGOTO_ERROR(H5E_REFERENCE, H5E_LINKCOUNT, FAIL, "dereferencing deleted object"); + if(H5O_link(&oloc, 0, dxpl_id) <= 0) + HGOTO_ERROR(H5E_REFERENCE, H5E_LINKCOUNT, FAIL, "dereferencing deleted object") + + /* Construct a group location for opening the object */ + H5G_name_reset(&path); + loc.oloc = &oloc; + loc.path = &path; /* Open the object */ - oid_type=H5G_get_type(&ent,dxpl_id); + oid_type = H5O_obj_type(&oloc, dxpl_id); switch(oid_type) { case H5G_GROUP: - if ((group=H5G_open(&ent,dxpl_id)) == NULL) - HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "not found"); - - /* Create an atom for the group */ - if ((ret_value = H5I_register(H5I_GROUP, group)) < 0) { - H5G_close(group); - HGOTO_ERROR(H5E_SYM, H5E_CANTREGISTER, FAIL, "can't register group"); - } + { + H5G_t *group; /* Pointer to group to open */ + + if((group = H5G_open(&loc, dxpl_id)) == NULL) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "not found") + + /* Create an atom for the group */ + if((ret_value = H5I_register(H5I_GROUP, group)) < 0) { + H5G_close(group); + HGOTO_ERROR(H5E_SYM, H5E_CANTREGISTER, FAIL, "can't register group") + } /* end if */ + } /* end case */ break; case H5G_TYPE: - if ((type=H5T_open(&ent, dxpl_id)) == NULL) - HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, FAIL, "not found"); - - /* Create an atom for the datatype */ - if ((ret_value = H5I_register(H5I_DATATYPE, type)) < 0) { - H5T_close(type); - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "can't register datatype"); - } + { + H5T_t *type; /* Pointer to datatype to open */ + + if((type = H5T_open(&loc, dxpl_id)) == NULL) + HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, FAIL, "not found") + + /* Create an atom for the datatype */ + if((ret_value = H5I_register(H5I_DATATYPE, type)) < 0) { + H5T_close(type); + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "can't register datatype") + } /* end if */ + } /* end case */ break; case H5G_DATASET: - /* Open the dataset */ - if ((dset=H5D_open(&ent,dxpl_id))==NULL) - HGOTO_ERROR(H5E_DATASET, H5E_NOTFOUND, FAIL, "not found"); - - /* Create an atom for the dataset */ - if ((ret_value = H5I_register(H5I_DATASET, dset)) < 0) { - H5D_close(dset); - HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "can't register dataset"); - } + { + H5D_t *dset; /* Pointer to dataset to open */ + + /* Open the dataset */ + if((dset = H5D_open(&loc, dxpl_id)) == NULL) + HGOTO_ERROR(H5E_DATASET, H5E_NOTFOUND, FAIL, "not found") + + /* Create an atom for the dataset */ + if((ret_value = H5I_register(H5I_DATASET, dset)) < 0) { + H5D_close(dset); + HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "can't register dataset") + } /* end if */ + } /* end case */ break; default: - HGOTO_ERROR(H5E_REFERENCE, H5E_BADTYPE, FAIL, "can't identify type of object referenced"); + HGOTO_ERROR(H5E_REFERENCE, H5E_BADTYPE, FAIL, "can't identify type of object referenced") } /* end switch */ done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5R_dereference() */ @@ -458,30 +474,30 @@ done: hid_t H5Rdereference(hid_t id, H5R_type_t ref_type, void *_ref) { - H5G_entry_t *loc = NULL; /* Symbol table entry */ - H5F_t *file=NULL; /* File object */ + H5G_loc_t loc; /* Group location */ + H5F_t *file = NULL; /* File object */ hid_t ret_value; - FUNC_ENTER_API(H5Rdereference, FAIL); + FUNC_ENTER_API(H5Rdereference, FAIL) H5TRACE3("i","iRtx",id,ref_type,_ref); /* Check args */ - if (NULL == (loc = H5G_loc(id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location"); - if(ref_type<=H5R_BADTYPE || ref_type>=H5R_MAXTYPE) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference type"); - if(_ref==NULL) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference pointer"); + if(H5G_loc(id, &loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + if(ref_type <= H5R_BADTYPE || ref_type >= H5R_MAXTYPE) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference type") + if(_ref == NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference pointer") /* Get the file pointer from the entry */ - file=loc->file; + file = loc.oloc->file; /* Create reference */ - if ((ret_value=H5R_dereference(file, H5AC_dxpl_id, ref_type, _ref))<0) - HGOTO_ERROR (H5E_REFERENCE, H5E_CANTINIT, FAIL, "unable dereference object"); + if((ret_value = H5R_dereference(file, H5AC_dxpl_id, ref_type, _ref)) < 0) + HGOTO_ERROR(H5E_REFERENCE, H5E_CANTINIT, FAIL, "unable dereference object") done: - FUNC_LEAVE_API(ret_value); + FUNC_LEAVE_API(ret_value) } /* end H5Rdereference() */ @@ -493,7 +509,6 @@ done: USAGE H5S_t *H5R_get_region(file, ref_type, ref) H5F_t *file; IN: File the object being dereferenced is within - H5R_type_t ref_type; UNUSED void *ref; IN: Reference to open. RETURNS @@ -508,52 +523,50 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static H5S_t * -H5R_get_region(H5F_t *file, hid_t dxpl_id, H5R_type_t UNUSED ref_type, void *_ref) +H5R_get_region(H5F_t *file, hid_t dxpl_id, void *_ref) { - H5G_entry_t ent; /* Symbol table entry */ + H5O_loc_t oloc; /* Object location */ uint8_t *p; /* Pointer to OID to store */ - hdset_reg_ref_t *ref=(hdset_reg_ref_t *)_ref; /* Get pointer to correct type of reference struct */ + hdset_reg_ref_t *ref = (hdset_reg_ref_t *)_ref; /* Get pointer to correct type of reference struct */ H5HG_t hobjid; /* Heap object ID */ uint8_t *buf; /* Buffer to store serialized selection in */ H5S_t *ret_value; - FUNC_ENTER_NOAPI_NOINIT(H5R_get_region); + FUNC_ENTER_NOAPI_NOINIT(H5R_get_region) - assert(_ref); - assert(ref_type==H5R_DATASET_REGION); - assert(file); + HDassert(_ref); + HDassert(file); - /* Initialize the symbol table entry */ - H5G_ent_reset(&ent); - ent.type=H5G_NOTHING_CACHED; - ent.file=file; + /* Initialize the object location */ + H5O_loc_reset(&oloc); + oloc.file = file; /* Get the heap ID for the dataset region */ - p=(uint8_t *)ref; - H5F_addr_decode(ent.file,(const uint8_t **)&p,&(hobjid.addr)); + p = (uint8_t *)ref; + H5F_addr_decode(oloc.file, (const uint8_t **)&p, &(hobjid.addr)); INT32DECODE(p,hobjid.idx); /* Get the dataset region from the heap (allocate inside routine) */ - if((buf=H5HG_read(ent.file,dxpl_id,&hobjid,NULL))==NULL) - HGOTO_ERROR(H5E_REFERENCE, H5E_READERROR, NULL, "Unable to read dataset region information"); + if((buf = H5HG_read(oloc.file, dxpl_id, &hobjid, NULL)) == NULL) + HGOTO_ERROR(H5E_REFERENCE, H5E_READERROR, NULL, "Unable to read dataset region information") /* Get the object oid for the dataset */ - p=(uint8_t *)buf; - H5F_addr_decode(ent.file,(const uint8_t **)&p,&(ent.header)); + p = (uint8_t *)buf; + H5F_addr_decode(oloc.file, (const uint8_t **)&p, &(oloc.addr)); /* Open and copy the dataset's dataspace */ - if ((ret_value=H5S_read(&ent, dxpl_id)) == NULL) - HGOTO_ERROR(H5E_DATASPACE, H5E_NOTFOUND, NULL, "not found"); + if((ret_value = H5S_read(&oloc, dxpl_id)) == NULL) + HGOTO_ERROR(H5E_DATASPACE, H5E_NOTFOUND, NULL, "not found") /* Unserialize the selection */ - if (H5S_select_deserialize(ret_value,p) < 0) - HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, NULL, "can't deserialize selection"); + if(H5S_select_deserialize(ret_value, p) < 0) + HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, NULL, "can't deserialize selection") /* Free the buffer allocated in H5HG_read() */ H5MM_xfree(buf); done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5R_get_region() */ @@ -581,37 +594,33 @@ done: REVISION LOG --------------------------------------------------------------------------*/ hid_t -H5Rget_region(hid_t id, H5R_type_t ref_type, void *_ref) +H5Rget_region(hid_t id, H5R_type_t ref_type, void *ref) { - H5G_entry_t *loc = NULL; /* Symbol table entry */ - H5S_t *space = NULL; /* dataspace object */ - H5F_t *file=NULL; /* File object */ + H5G_loc_t loc; /* Object's group location */ + H5S_t *space = NULL; /* Dataspace object */ hid_t ret_value; - FUNC_ENTER_API(H5Rget_region, FAIL); - H5TRACE3("i","iRtx",id,ref_type,_ref); + FUNC_ENTER_API(H5Rget_region, FAIL) + H5TRACE3("i","iRtx",id,ref_type,ref); /* Check args */ - if (NULL == (loc = H5G_loc(id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location"); - if(ref_type!=H5R_DATASET_REGION) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference type"); - if(_ref==NULL) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference pointer"); - - /* Get the file pointer from the entry */ - file=loc->file; + if(H5G_loc(id, &loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + if(ref_type != H5R_DATASET_REGION) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference type") + if(ref == NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference pointer") /* Get the dataspace with the correct region selected */ - if ((space=H5R_get_region(file,H5AC_ind_dxpl_id,ref_type,_ref))==NULL) - HGOTO_ERROR (H5E_REFERENCE, H5E_CANTCREATE, FAIL, "unable to create dataspace"); + if((space = H5R_get_region(loc.oloc->file, H5AC_ind_dxpl_id, ref)) == NULL) + HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCREATE, FAIL, "unable to create dataspace") /* Atomize */ - if ((ret_value=H5I_register (H5I_DATASPACE, space))<0) - HGOTO_ERROR (H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace atom"); + if((ret_value = H5I_register (H5I_DATASPACE, space)) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace atom") done: - FUNC_LEAVE_API(ret_value); + FUNC_LEAVE_API(ret_value) } /* end H5Rget_region() */ @@ -640,48 +649,47 @@ done: static H5G_obj_t H5R_get_obj_type(H5F_t *file, hid_t dxpl_id, H5R_type_t ref_type, void *_ref) { - H5G_entry_t ent; /* Symbol table entry */ + H5O_loc_t oloc; /* Object location */ uint8_t *p; /* Pointer to OID to store */ H5G_obj_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5R_get_obj_type); + FUNC_ENTER_NOAPI_NOINIT(H5R_get_obj_type) - assert(file); - assert(_ref); + HDassert(file); + HDassert(_ref); /* Initialize the symbol table entry */ - H5G_ent_reset(&ent); - ent.type=H5G_NOTHING_CACHED; - ent.file=file; + H5O_loc_reset(&oloc); + oloc.file = file; switch(ref_type) { case H5R_OBJECT: { - hobj_ref_t *ref=(hobj_ref_t *)_ref; /* Only object references currently supported */ + hobj_ref_t *ref = (hobj_ref_t *)_ref; /* Only object references currently supported */ /* Get the object oid */ - ent.header=*ref; + oloc.addr = *ref; } /* end case */ break; case H5R_DATASET_REGION: { - hdset_reg_ref_t *ref=(hdset_reg_ref_t *)_ref; /* Get pointer to correct type of reference struct */ + hdset_reg_ref_t *ref = (hdset_reg_ref_t *)_ref; /* Get pointer to correct type of reference struct */ H5HG_t hobjid; /* Heap object ID */ uint8_t *buf; /* Buffer to store serialized selection in */ /* Get the heap ID for the dataset region */ - p=(uint8_t *)ref; - H5F_addr_decode(ent.file,(const uint8_t **)&p,&(hobjid.addr)); - INT32DECODE(p,hobjid.idx); + p = (uint8_t *)ref; + H5F_addr_decode(oloc.file, (const uint8_t **)&p, &(hobjid.addr)); + INT32DECODE(p, hobjid.idx); /* Get the dataset region from the heap (allocate inside routine) */ - if((buf=H5HG_read(ent.file,dxpl_id,&hobjid,NULL))==NULL) - HGOTO_ERROR(H5E_REFERENCE, H5E_READERROR, H5G_UNKNOWN, "Unable to read dataset region information"); + if((buf = H5HG_read(oloc.file, dxpl_id, &hobjid, NULL)) == NULL) + HGOTO_ERROR(H5E_REFERENCE, H5E_READERROR, H5G_UNKNOWN, "Unable to read dataset region information") /* Get the object oid for the dataset */ - p=(uint8_t *)buf; - H5F_addr_decode(ent.file,(const uint8_t **)&p,&(ent.header)); + p = (uint8_t *)buf; + H5F_addr_decode(oloc.file, (const uint8_t **)&p, &(oloc.addr)); /* Free the buffer allocated in H5HG_read() */ H5MM_xfree(buf); @@ -689,24 +697,24 @@ H5R_get_obj_type(H5F_t *file, hid_t dxpl_id, H5R_type_t ref_type, void *_ref) break; case H5R_INTERNAL: - HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, H5G_UNKNOWN, "Internal references are not yet supported"); + HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, H5G_UNKNOWN, "Internal references are not yet supported") case H5R_BADTYPE: case H5R_MAXTYPE: default: - assert("unknown reference type" && 0); - HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, H5G_UNKNOWN, "internal error (unknown reference type)"); + HDassert("unknown reference type" && 0); + HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, H5G_UNKNOWN, "internal error (unknown reference type)") } /* end switch */ /* Check to make certain that this object hasn't been deleted since the reference was created */ - if(H5O_link(&ent,0,dxpl_id)<=0) - HGOTO_ERROR(H5E_REFERENCE, H5E_LINKCOUNT, H5G_UNKNOWN, "dereferencing deleted object"); + if(H5O_link(&oloc, 0, dxpl_id) <= 0) + HGOTO_ERROR(H5E_REFERENCE, H5E_LINKCOUNT, H5G_UNKNOWN, "dereferencing deleted object") /* Get the OID type */ - ret_value=H5G_get_type(&ent,dxpl_id); + ret_value = H5O_obj_type(&oloc,dxpl_id); done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5R_get_obj_type() */ @@ -734,31 +742,27 @@ done: REVISION LOG --------------------------------------------------------------------------*/ H5G_obj_t -H5Rget_obj_type(hid_t id, H5R_type_t ref_type, void *_ref) +H5Rget_obj_type(hid_t id, H5R_type_t ref_type, void *ref) { - H5G_entry_t *loc = NULL; /* Symbol table entry */ - H5F_t *file=NULL; /* File object */ + H5G_loc_t loc; /* Object location */ H5G_obj_t ret_value; - FUNC_ENTER_API(H5Rget_obj_type, H5G_UNKNOWN); - H5TRACE3("Go","iRtx",id,ref_type,_ref); + FUNC_ENTER_API(H5Rget_obj_type, H5G_UNKNOWN) + H5TRACE3("Go","iRtx",id,ref_type,ref); /* Check args */ - if (NULL == (loc = H5G_loc(id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "not a location"); - if(ref_type<=H5R_BADTYPE || ref_type>=H5R_MAXTYPE) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, H5G_UNKNOWN, "invalid reference type"); - if(_ref==NULL) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, H5G_UNKNOWN, "invalid reference pointer"); - - /* Get the file pointer from the entry */ - file=loc->file; + if(H5G_loc(id, &loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "not a location") + if(ref_type <= H5R_BADTYPE || ref_type >= H5R_MAXTYPE) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5G_UNKNOWN, "invalid reference type") + if(ref == NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5G_UNKNOWN, "invalid reference pointer") /* Get the object information */ - if ((ret_value=H5R_get_obj_type(file,H5AC_ind_dxpl_id,ref_type,_ref))<0) - HGOTO_ERROR(H5E_REFERENCE, H5E_CANTINIT, H5G_UNKNOWN, "unable to determine object type"); + if((ret_value = H5R_get_obj_type(loc.oloc->file, H5AC_ind_dxpl_id, ref_type, ref)) < 0) + HGOTO_ERROR(H5E_REFERENCE, H5E_CANTINIT, H5G_UNKNOWN, "unable to determine object type") done: - FUNC_LEAVE_API(ret_value); + FUNC_LEAVE_API(ret_value) } /* end H5Rget_obj_type() */ @@ -62,17 +62,17 @@ H5RS_xstrdup(const char *s) { char *ret_value; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5RS_xstrdup); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5RS_xstrdup) - if (s) { - ret_value = H5FL_BLK_MALLOC(str_buf,HDstrlen(s) + 1); - assert (ret_value); + if(s) { + ret_value = H5FL_BLK_MALLOC(str_buf, HDstrlen(s) + 1); + HDassert(ret_value); HDstrcpy(ret_value, s); } /* end if */ else - ret_value=NULL; + ret_value = NULL; - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5RS_xstrdup() */ @@ -160,7 +160,7 @@ done: NAME H5RS_own PURPOSE - Transfer ownership of a regular string to a reference counted string + Transfer ownership of a regular string to a reference counted string USAGE H5RS_str_t *H5RS_own(s) const char *s; IN: String to transfer ownership of @@ -286,7 +286,7 @@ H5RS_incr(H5RS_str_t *rs) PURPOSE "Duplicate" a ref-counted string USAGE - H5RS_str_t H5RS_incr(rs) + H5RS_str_t H5RS_dup(rs) H5RS_str_t *rs; IN/OUT: Ref-counted string to "duplicate" RETURNS @@ -315,6 +315,54 @@ H5RS_dup(H5RS_str_t *ret_value) /*-------------------------------------------------------------------------- NAME + H5RS_dup + PURPOSE + "Duplicate" a regular string into a ref-counted string + USAGE + H5RS_str_t H5RS_dup_str(s) + const char *s; IN: Regular string to duplicate + + RETURNS + Returns a pointer to ref-counted string on success, NULL on failure. + DESCRIPTION + Duplicate a regular string into a ref-counted string. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +H5RS_str_t * +H5RS_dup_str(const char *s) +{ + char *new_str = NULL; /* Duplicate of string */ + size_t path_len; /* Length of the path */ + H5RS_str_t *ret_value; + + FUNC_ENTER_NOAPI(H5RS_dup_str, FAIL) + + /* Sanity check */ + HDassert(s); + + /* Get the length of the string */ + path_len = HDstrlen(s); + + /* Allocate space for the string */ + if(NULL == (new_str = H5FL_BLK_MALLOC(str_buf, path_len + 1))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* Copy name for full path */ + HDstrcpy(new_str, s); + + /* Create reference counted string for path */ + ret_value = H5RS_own(new_str); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5RS_dup_str() */ + + +/*-------------------------------------------------------------------------- + NAME H5RS_cmp PURPOSE Compare two ref-counted strings diff --git a/src/H5RSprivate.h b/src/H5RSprivate.h index a154d01..1ddbac7 100644 --- a/src/H5RSprivate.h +++ b/src/H5RSprivate.h @@ -50,6 +50,7 @@ H5_DLL H5RS_str_t *H5RS_own(char *s); H5_DLL herr_t H5RS_decr(H5RS_str_t *rs); H5_DLL herr_t H5RS_incr(H5RS_str_t *rs); H5_DLL H5RS_str_t *H5RS_dup(H5RS_str_t *s); +H5_DLL H5RS_str_t *H5RS_dup_str(const char *s); H5_DLL int H5RS_cmp(const H5RS_str_t *rs1, const H5RS_str_t *rs2); H5_DLL ssize_t H5RS_len(const H5RS_str_t *rs); H5_DLL char *H5RS_get_str(const H5RS_str_t *rs); diff --git a/src/H5Rprivate.h b/src/H5Rprivate.h index 0e1fdb2..0f23992 100644 --- a/src/H5Rprivate.h +++ b/src/H5Rprivate.h @@ -13,7 +13,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * This file contains private information about the H5S module + * This file contains private information about the H5R module */ #ifndef _H5Rprivate_H #define _H5Rprivate_H @@ -21,13 +21,10 @@ #include "H5Rpublic.h" /* Private headers needed by this file */ -#include "H5private.h" - -#define H5R_RESERVED_ATOMS 0 /* Internal data structures */ - /* Private functions */ #endif /* _H5Rprivate_H */ + @@ -30,6 +30,11 @@ #include "H5Spkg.h" /* Dataspaces */ /* Local macro definitions */ + +/* Number of reserved IDs in ID group */ +#define H5S_RESERVED_ATOMS 2 + +/* Version of datatype encoding */ #define H5S_ENCODE_VERSION 0 /* Local static function prototypes */ @@ -1042,39 +1047,37 @@ done: * Programmer: Robb Matzke * Tuesday, December 9, 1997 * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t -H5S_modify(H5G_entry_t *ent, const H5S_t *ds, hbool_t update_time, hid_t dxpl_id) +H5S_modify(H5O_loc_t *loc, const H5S_t *ds, hbool_t update_time, hid_t dxpl_id) { - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5S_modify, FAIL); + FUNC_ENTER_NOAPI(H5S_modify, FAIL) - assert(ent); - assert(ds); + HDassert(loc); + HDassert(ds); - switch (H5S_GET_EXTENT_TYPE(ds)) { + switch(H5S_GET_EXTENT_TYPE(ds)) { case H5S_NULL: case H5S_SCALAR: case H5S_SIMPLE: - if (H5O_modify(ent, H5O_SDSPACE_ID, 0, 0, update_time, &(ds->extent), dxpl_id)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't update simple data space message"); + if(H5O_modify(loc, H5O_SDSPACE_ID, 0, 0, update_time, &(ds->extent), dxpl_id) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't update simple dataspace message") break; case H5S_COMPLEX: - HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "complex data spaces are not implemented yet"); + HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "complex dataspaces are not implemented yet") default: - assert("unknown data space class" && 0); + HDassert("unknown dataspace class" && 0); break; - } + } /* end switch */ done: - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S_modify() */ /*------------------------------------------------------------------------- @@ -1143,44 +1146,40 @@ done: * Programmer: Robb Matzke * Tuesday, December 9, 1997 * - * Modifications: - * Robb Matzke, 9 Jun 1998 - * Removed the unused file argument since the file is now part of the - * ENT argument. *------------------------------------------------------------------------- */ H5S_t * -H5S_read(const H5G_entry_t *ent, hid_t dxpl_id) +H5S_read(const H5O_loc_t *loc, hid_t dxpl_id) { - H5S_t *ds = NULL; /* Dataspace to return */ - H5S_t *ret_value; /* Return value */ + H5S_t *ds = NULL; /* Dataspace to return */ + H5S_t *ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5S_read, NULL); + FUNC_ENTER_NOAPI(H5S_read, NULL) /* check args */ - assert(ent); + HDassert(loc); - if (NULL==(ds = H5FL_CALLOC(H5S_t))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + if(NULL == (ds = H5FL_CALLOC(H5S_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - if (H5O_read(ent, H5O_SDSPACE_ID, 0, &(ds->extent), dxpl_id) == NULL) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, NULL, "unable to load dataspace info from dataset header"); + if(H5O_read(loc, H5O_SDSPACE_ID, 0, &(ds->extent), dxpl_id) == NULL) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, NULL, "unable to load dataspace info from dataset header") /* Default to entire dataspace being selected */ - if(H5S_select_all(ds,0)<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTSET, NULL, "unable to set all selection"); + if(H5S_select_all(ds, 0) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, NULL, "unable to set all selection") /* Set the value for successful return */ - ret_value=ds; + ret_value = ds; done: - if(ret_value==NULL) { - if(ds!=NULL) - H5FL_FREE(H5S_t,ds); + if(ret_value == NULL) { + if(ds != NULL) + H5FL_FREE(H5S_t, ds); } /* end if */ - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S_read() */ /*-------------------------------------------------------------------------- @@ -466,6 +466,7 @@ H5SL_release_common(H5SL_t *slist, H5SL_operator_t op, void *op_data) /* Call callback, if one is given */ if(op!=NULL) + /* Casting away const OK -QAK */ (void)(op)(node->item,(void *)node->key,op_data); H5FL_ARR_FREE(H5SL_node_ptr_t,node); diff --git a/src/H5Spkg.h b/src/H5Spkg.h index 2cb8499..69330c5 100644 --- a/src/H5Spkg.h +++ b/src/H5Spkg.h @@ -29,9 +29,6 @@ #include "H5Sprivate.h" -/* Number of reserved IDs in ID group */ -#define H5S_RESERVED_ATOMS 2 - /* Flags to indicate special dataspace features are active */ #define H5S_VALID_MAX 0x01 #define H5S_VALID_PERM 0x02 diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h index a902918..bf9ff84 100644 --- a/src/H5Sprivate.h +++ b/src/H5Sprivate.h @@ -198,12 +198,12 @@ H5_DLL hbool_t H5S_has_extent(const H5S_t *ds); H5_DLL int H5S_get_simple_extent_ndims(const H5S_t *ds); H5_DLL int H5S_get_simple_extent_dims(const H5S_t *ds, hsize_t dims[]/*out*/, hsize_t max_dims[]/*out*/); -H5_DLL herr_t H5S_modify(struct H5G_entry_t *ent, const H5S_t *space, - hbool_t update_time, hid_t dxpl_id); +H5_DLL herr_t H5S_modify(struct H5O_loc_t *loc, const H5S_t *space, + hbool_t update_time, hid_t dxpl_id); H5_DLL herr_t H5S_append(H5F_t *f, hid_t dxpl_id, struct H5O_t *oh, const H5S_t *ds, unsigned * oh_flags_ptr); H5_DLL size_t H5S_raw_size(const H5F_t *f, const H5S_t *space); -H5_DLL H5S_t *H5S_read(const struct H5G_entry_t *ent, hid_t dxpl_id); +H5_DLL H5S_t *H5S_read(const struct H5O_loc_t *loc, hid_t dxpl_id); H5_DLL int H5S_extend(H5S_t *space, const hsize_t *size); H5_DLL int H5S_set_extent(H5S_t *space, const hsize_t *size); H5_DLL herr_t H5S_set_extent_real(H5S_t *space, const hsize_t *size); diff --git a/src/H5Stest.c b/src/H5Stest.c index 83fbd96..6df626c 100644 --- a/src/H5Stest.c +++ b/src/H5Stest.c @@ -22,10 +22,10 @@ #define H5S_TESTING /*suppress warning about H5S testing funcs*/ -#include "H5private.h" /* Generic Functions */ -#include "H5Eprivate.h" /* Error handling */ -#include "H5Iprivate.h" /* ID Functions */ -#include "H5Spkg.h" /* Dataspace functions */ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Iprivate.h" /* IDs */ +#include "H5Spkg.h" /* Dataspaces */ /*-------------------------------------------------------------------------- @@ -71,6 +71,7 @@ done: FUNC_LEAVE_NOAPI(ret_value); } /* H5S_select_shape_same_test() */ + /*-------------------------------------------------------------------------- NAME H5S_inquiry_rebuild_status @@ -257,7 +257,6 @@ H5FL_DEFINE(H5T_shared_t); H5FL_DEFINE(H5T_path_t); /* Static local functions */ -static H5T_t *H5T_open_oid(H5G_entry_t *ent, hid_t dxpl_id); static herr_t H5T_print_stats(H5T_path_t *path, int *nprint/*in,out*/); static herr_t H5T_unregister(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst, H5T_conv_t func, hid_t dxpl_id); @@ -378,7 +377,7 @@ static H5T_t *H5T_decode(const unsigned char *buf); /* Define a macro for common code for all newly allocate datatypes */ #define H5T_INIT_TYPE_ALLOC_COMMON(TYPE) { \ - dt->ent.header = HADDR_UNDEF; \ + dt->oloc.addr = HADDR_UNDEF; \ dt->shared->type = TYPE; \ } @@ -1568,75 +1567,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5Topen - * - * Purpose: Opens a named data type. - * - * Return: Success: Object ID of the named data type. - * - * Failure: Negative - * - * Programmer: Robb Matzke - * Monday, June 1, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -hid_t -H5Topen(hid_t loc_id, const char *name) -{ - H5T_t *type = NULL; - H5G_entry_t *loc = NULL; - H5G_entry_t ent; - hbool_t ent_found = FALSE; /* Entry at 'name' found */ - hid_t dxpl_id = H5AC_dxpl_id; /* dxpl to use to open datatype */ - hid_t ret_value =FAIL; - - FUNC_ENTER_API(H5Topen, FAIL); - H5TRACE2("i","is",loc_id,name); - - /* Check args */ - if (NULL==(loc=H5G_loc (loc_id))) - HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a location"); - if (!name || !*name) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "no name"); - - /* - * Find the named data type object header and read the data type message - * from it. - */ - if (H5G_find (loc, name, &ent/*out*/, dxpl_id)<0) - HGOTO_ERROR (H5E_DATATYPE, H5E_NOTFOUND, FAIL, "not found"); - ent_found = TRUE; - - /* Check that the object found is the correct type */ - if (H5G_get_type(&ent, dxpl_id) != H5G_TYPE) - HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, FAIL, "not a named datatype") - - /* Open it */ - if ((type=H5T_open (&ent, dxpl_id)) ==NULL) - HGOTO_ERROR (H5E_DATATYPE, H5E_CANTOPENOBJ, FAIL, "unable to open named data type"); - - /* Register the type and return the ID */ - if ((ret_value=H5I_register (H5I_DATATYPE, type))<0) - HGOTO_ERROR (H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register named data type"); - -done: - if(ret_value<0) { - if(type!=NULL) - H5T_close(type); - else { - if(ent_found && ent.header) - H5G_free_ent_name(&ent); - } /* end else */ - } /* end if */ - - FUNC_LEAVE_API(ret_value); -} - - -/*------------------------------------------------------------------------- * Function: H5Tcopy * * Purpose: Copies a data type. The resulting data type is not locked. @@ -3037,7 +2967,7 @@ done: * Function: H5T_isa * * Purpose: Determines if an object has the requisite messages for being - * a data type. + * a datatype. * * Return: Success: TRUE if the required data type messages are * present; FALSE otherwise. @@ -3048,166 +2978,23 @@ done: * Programmer: Robb Matzke * Monday, November 2, 1998 * - * Modifications: - * *------------------------------------------------------------------------- */ htri_t -H5T_isa(H5G_entry_t *ent, hid_t dxpl_id) +H5T_isa(H5O_loc_t *loc, hid_t dxpl_id) { htri_t ret_value; - FUNC_ENTER_NOAPI(H5T_isa, FAIL); - assert(ent); - - if ((ret_value=H5O_exists(ent, H5O_DTYPE_ID, 0, dxpl_id))<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to read object header"); - -done: - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5T_open - * - * Purpose: Open a named data type. - * - * Return: Success: Ptr to a new data type. - * - * Failure: NULL - * - * Programmer: Robb Matzke - * Monday, June 1, 1998 - * - * Modifications: - * Changed to use H5T_open_oid - QAK - 3/17/99 - * - *------------------------------------------------------------------------- - */ -H5T_t* -H5T_open (H5G_entry_t *ent, hid_t dxpl_id) -{ - H5T_shared_t *shared_fo=NULL; - H5T_t *dt=NULL; - H5T_t *ret_value; - - FUNC_ENTER_NOAPI(H5T_open, NULL); - - assert (ent); - - /* Check if datatype was already open */ - if((shared_fo=H5FO_opened(ent->file,ent->header))==NULL) { - /* Clear any errors from H5FO_opened() */ - H5E_clear_stack(NULL); - - /* Open the datatype object */ - if ((dt=H5T_open_oid(ent, dxpl_id)) ==NULL) - HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, NULL, "not found"); - - /* Add the datatype to the list of opened objects in the file */ - if(H5FO_insert(dt->ent.file, dt->ent.header, dt->shared)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, NULL, "can't insert datatype into list of open objects") - - /* Increment object count for the object in the top file */ - if(H5FO_top_incr(dt->ent.file, dt->ent.header) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count") - - /* Mark any datatypes as being in memory now */ - if (H5T_set_loc(dt, NULL, H5T_LOC_MEMORY)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "invalid datatype location") - - dt->shared->fo_count=1; - } - else - { - if(NULL == (dt = H5FL_MALLOC(H5T_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate space for datatype") - - /* Shallow copy (take ownership) of the group entry object */ - if(H5G_ent_copy(&(dt->ent),ent,H5G_COPY_SHALLOW)<0) - HGOTO_ERROR (H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy group entry") - - dt->shared=shared_fo; - - shared_fo->fo_count++; - - /* Check if the object has been opened through the top file yet */ - if(H5FO_top_count(dt->ent.file, dt->ent.header) == 0) { - /* Open the object through this top file */ - if(H5O_open(&(dt->ent)) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to open object header") - } /* end if */ - - /* Increment object count for the object in the top file */ - if(H5FO_top_incr(dt->ent.file, dt->ent.header) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count") - } - - ret_value = dt; - -done: - if(ret_value==NULL) { - if(dt) { - if(shared_fo==NULL) /* Need to free shared fo */ - H5FL_FREE(H5T_shared_t, dt->shared); - H5FL_FREE(H5T_t, dt); - } - if(shared_fo) - shared_fo->fo_count--; - } - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5T_open_oid - * - * Purpose: Open a named data type. - * - * Return: Success: Ptr to a new data type. - * - * Failure: NULL - * - * Programmer: Quincey Koziol - * Wednesday, March 17, 1999 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -H5T_t * -H5T_open_oid (H5G_entry_t *ent, hid_t dxpl_id) -{ - H5T_t *dt=NULL; - H5T_t *ret_value; - - FUNC_ENTER_NOAPI(H5T_open_oid, NULL); - - assert (ent); + FUNC_ENTER_NOAPI(H5T_isa, FAIL) - if (H5O_open (ent)<0) - HGOTO_ERROR (H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to open named data type"); - if (NULL==(dt=H5O_read (ent, H5O_DTYPE_ID, 0, NULL, dxpl_id))) - HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to load type message from object header"); + HDassert(loc); - /* Mark the type as named and open */ - dt->shared->state = H5T_STATE_OPEN; - - /* Shallow copy (take ownership) of the group entry object */ - H5G_ent_copy(&(dt->ent),ent,H5G_COPY_SHALLOW); - - /* Set return value */ - ret_value=dt; + if((ret_value = H5O_exists(loc, H5O_DTYPE_ID, 0, dxpl_id)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to read object header") done: - if(ret_value==NULL) { - if(dt==NULL) - H5O_close(ent); - } /* end if */ - - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T_isa() */ /*------------------------------------------------------------------------- @@ -3299,22 +3086,22 @@ H5T_copy(const H5T_t *old_dt, H5T_copy_t method) * Return a transient type (locked or unlocked) or an opened named * type. Immutable transient types are degraded to read-only. */ - if (H5F_addr_defined(old_dt->ent.header)) { + if(H5F_addr_defined(old_dt->oloc.addr)) { /* Check if the object is already open */ - if((reopened_fo=H5FO_opened(old_dt->ent.file, old_dt->ent.header))==NULL) { + if((reopened_fo=H5FO_opened(old_dt->oloc.file, old_dt->oloc.addr))==NULL) { /* Clear any errors from H5FO_opened() */ H5E_clear_stack(NULL); /* Open named datatype again */ - if (H5O_open (&(old_dt->ent))<0) + if(H5O_open(&(old_dt->oloc)) < 0) HGOTO_ERROR (H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to reopen named data type"); /* Insert opened named datatype into opened object list for the file */ - if(H5FO_insert(old_dt->ent.file, old_dt->ent.header, new_dt->shared)<0) + if(H5FO_insert(old_dt->oloc.file, old_dt->oloc.addr, new_dt->shared)<0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, NULL, "can't insert datatype into list of open objects") /* Increment object count for the object in the top file */ - if(H5FO_top_incr(old_dt->ent.file, old_dt->ent.header) < 0) + if(H5FO_top_incr(old_dt->oloc.file, old_dt->oloc.addr) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count") new_dt->shared->fo_count=1; @@ -3328,14 +3115,14 @@ H5T_copy(const H5T_t *old_dt, H5T_copy_t method) reopened_fo->fo_count++; /* Check if the object has been opened through the top file yet */ - if(H5FO_top_count(old_dt->ent.file, old_dt->ent.header) == 0) { + if(H5FO_top_count(old_dt->oloc.file, old_dt->oloc.addr) == 0) { /* Open the object through this top file */ - if(H5O_open(&(old_dt->ent)) < 0) + if(H5O_open(&(old_dt->oloc)) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to open object header") } /* end if */ /* Increment object count for the object in the top file */ - if(H5FO_top_incr(old_dt->ent.file, old_dt->ent.header) < 0) + if(H5FO_top_incr(old_dt->oloc.file, old_dt->oloc.addr) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count") } new_dt->shared->state = H5T_STATE_OPEN; @@ -3452,14 +3239,17 @@ H5T_copy(const H5T_t *old_dt, H5T_copy_t method) } /* end switch */ /* Deep copy of the symbol table entry, if there was one */ - if ( new_dt->shared->state == H5T_STATE_NAMED || new_dt->shared->state == H5T_STATE_OPEN) { - if (!H5F_addr_defined(old_dt->ent.header)) - HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, NULL, "named dataype with invalid address"); - if (H5G_ent_copy(&(new_dt->ent), &(old_dt->ent),H5G_COPY_DEEP)<0) - HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, NULL, "unable to copy entry"); + if(new_dt->shared->state == H5T_STATE_NAMED || new_dt->shared->state == H5T_STATE_OPEN) { + if(!H5F_addr_defined(old_dt->oloc.addr)) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, NULL, "named dataype with invalid address") + if(H5O_loc_copy(&(new_dt->oloc), &(old_dt->oloc), H5O_COPY_DEEP) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, NULL, "unable to copy entry") + if(H5G_name_copy(&(new_dt->path), &(old_dt->path), H5G_COPY_DEEP) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, NULL, "unable to copy path") } /* end if */ else { - H5G_ent_reset(&(new_dt->ent)); + H5O_loc_reset(&(new_dt->oloc)); + H5G_name_reset(&(new_dt->path)); } /* end else */ /* Set return value */ @@ -3540,7 +3330,7 @@ done: H5T_t * H5T_alloc(void) { - H5T_t *dt; /* Pointer to datatype allocated */ + H5T_t *dt = NULL; /* Pointer to datatype allocated */ H5T_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5T_alloc, NULL) @@ -3548,7 +3338,8 @@ H5T_alloc(void) /* Allocate & initialize new datatype info */ if(NULL == (dt = H5FL_CALLOC(H5T_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - H5G_ent_reset(&(dt->ent)); + H5O_loc_reset(&(dt->oloc)); + H5G_name_reset(&(dt->path)); if(NULL == (dt->shared = H5FL_CALLOC(H5T_shared_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") @@ -3580,54 +3371,56 @@ done: * Programmer: Quincey Koziol * Monday, January 6, 2003 * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t H5T_free(H5T_t *dt) { unsigned i; - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5T_free, FAIL); + FUNC_ENTER_NOAPI(H5T_free, FAIL) - assert(dt && dt->shared); + HDassert(dt && dt->shared); /* * If a named type is being closed then close the object header and * remove from the list of open objects in the file. */ - if (H5T_STATE_OPEN==dt->shared->state) { - assert (H5F_addr_defined(dt->ent.header)); + if(H5T_STATE_OPEN == dt->shared->state) { + HDassert(H5F_addr_defined(dt->oloc.addr)); + /* Remove the datatype from the list of opened objects in the file */ - if(H5FO_top_decr(dt->ent.file, dt->ent.header) < 0) + if(H5FO_top_decr(dt->oloc.file, dt->oloc.addr) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "can't decrement count for object") - if(H5FO_delete(dt->ent.file, H5AC_dxpl_id, dt->ent.header)<0) + if(H5FO_delete(dt->oloc.file, H5AC_dxpl_id, dt->oloc.addr) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "can't remove datatype from list of open objects") - if (H5O_close(&(dt->ent))<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to close data type object header"); + if(H5O_close(&(dt->oloc)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to close data type object header") dt->shared->state = H5T_STATE_NAMED; - } + } /* end if */ + + /* Free the ID to name info */ + H5G_name_free(&(dt->path)); /* * Don't free locked datatypes. */ - if (H5T_STATE_IMMUTABLE==dt->shared->state) - HGOTO_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, FAIL, "unable to close immutable datatype"); + if(H5T_STATE_IMMUTABLE==dt->shared->state) + HGOTO_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, FAIL, "unable to close immutable datatype") /* Close the datatype */ - switch (dt->shared->type) { + switch(dt->shared->type) { case H5T_COMPOUND: - for (i=0; i<dt->shared->u.compnd.nmembs; i++) { + for(i = 0; i < dt->shared->u.compnd.nmembs; i++) { H5MM_xfree(dt->shared->u.compnd.memb[i].name); H5T_close(dt->shared->u.compnd.memb[i].type); - } + } /* end for */ H5MM_xfree(dt->shared->u.compnd.memb); break; case H5T_ENUM: - for (i=0; i<dt->shared->u.enumer.nmembs; i++) + for(i = 0; i < dt->shared->u.enumer.nmembs; i++) H5MM_xfree(dt->shared->u.enumer.name[i]); H5MM_xfree(dt->shared->u.enumer.name); H5MM_xfree(dt->shared->u.enumer.value); @@ -3639,17 +3432,14 @@ H5T_free(H5T_t *dt) default: break; - } - - /* Free the ID to name info */ - H5G_free_ent_name(&(dt->ent)); + } /* end switch */ /* Close the parent */ - if (dt->shared->parent && H5T_close(dt->shared->parent)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "unable to close parent data type"); + if(dt->shared->parent && H5T_close(dt->shared->parent) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "unable to close parent data type") done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(ret_value) } /* end H5T_free() */ @@ -3682,17 +3472,16 @@ done: herr_t H5T_close(H5T_t *dt) { - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5T_close, FAIL); + FUNC_ENTER_NOAPI(H5T_close, FAIL) - assert(dt && dt->shared); + HDassert(dt && dt->shared); dt->shared->fo_count--; - if(dt->shared->state != H5T_STATE_OPEN || dt->shared->fo_count == 0) - { - if(H5T_free(dt)<0) + if(dt->shared->state != H5T_STATE_OPEN || dt->shared->fo_count == 0) { + if(H5T_free(dt) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "unable to free datatype"); H5FL_FREE(H5T_shared_t, dt->shared); @@ -3701,27 +3490,27 @@ H5T_close(H5T_t *dt) * If a named type is being closed then close the object header and * remove from the list of open objects in the file. */ - if(H5T_STATE_OPEN==dt->shared->state) { + if(H5T_STATE_OPEN == dt->shared->state) { /* Decrement the ref. count for this object in the top file */ - if(H5FO_top_decr(dt->ent.file, dt->ent.header) < 0) + if(H5FO_top_decr(dt->oloc.file, dt->oloc.addr) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "can't decrement count for object") /* Check reference count for this object in the top file */ - if(H5FO_top_count(dt->ent.file, dt->ent.header) == 0) - if(H5O_close(&(dt->ent)) < 0) + if(H5FO_top_count(dt->oloc.file, dt->oloc.addr) == 0) + if(H5O_close(&(dt->oloc)) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to close") } /* end if */ - /* Free the ID to name info since we're not calling H5T_free*/ - H5G_free_ent_name(&(dt->ent)); - } + /* Free the group hier. path since we're not calling H5T_free*/ + H5G_name_free(&(dt->path)); + } /* end else */ /* Free the datatype struct */ H5FL_FREE(H5T_t,dt); done: - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T_close() */ /*------------------------------------------------------------------------- @@ -4807,44 +4596,79 @@ done: /*------------------------------------------------------------------------- - * Function: H5T_entof + * Function: H5T_oloc * - * Purpose: Returns a pointer to the entry for a named data type. - * - * Return: Success: Ptr directly into named data type + * Purpose: Returns a pointer to the object location for a named datatype. * + * Return: Success: Ptr directly into named datatype * Failure: NULL * * Programmer: Robb Matzke * Friday, June 5, 1998 * - * Modifications: + *------------------------------------------------------------------------- + */ +H5O_loc_t * +H5T_oloc(H5T_t *dt) +{ + H5O_loc_t *ret_value = NULL; + + FUNC_ENTER_NOAPI(H5T_oloc, NULL) + + HDassert(dt); + + switch(dt->shared->state) { + case H5T_STATE_TRANSIENT: + case H5T_STATE_RDONLY: + case H5T_STATE_IMMUTABLE: + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "not a named datatype") + case H5T_STATE_NAMED: + case H5T_STATE_OPEN: + ret_value = &(dt->oloc); + break; + } /* end switch */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T_oloc() */ + + +/*------------------------------------------------------------------------- + * Function: H5T_nameof + * + * Purpose: Returns a pointer to the path for a named datatype. + * + * Return: Success: Ptr directly into named datatype + * Failure: NULL + * + * Programmer: Quincey Koziol + * Monday, September 12, 2005 * *------------------------------------------------------------------------- */ -H5G_entry_t * -H5T_entof (H5T_t *dt) +H5G_name_t * +H5T_nameof(H5T_t *dt) { - H5G_entry_t *ret_value = NULL; + H5G_name_t *ret_value = NULL; - FUNC_ENTER_NOAPI(H5T_entof, NULL); + FUNC_ENTER_NOAPI(H5T_nameof, NULL) - assert (dt); + HDassert(dt); - switch (dt->shared->state) { + switch(dt->shared->state) { case H5T_STATE_TRANSIENT: case H5T_STATE_RDONLY: case H5T_STATE_IMMUTABLE: - HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, NULL, "not a named data type"); + HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, NULL, "not a named datatype") case H5T_STATE_NAMED: case H5T_STATE_OPEN: - ret_value = &(dt->ent); + ret_value = &(dt->path); break; - } + } /* end switch */ done: - FUNC_LEAVE_NOAPI(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T_nameof() */ /*------------------------------------------------------------------------- @@ -5430,16 +5254,6 @@ H5T_debug(const H5T_t *dt, FILE *stream) fprintf(stream, "\n\"%s\" @%lu", dt->shared->u.compnd.memb[i].name, (unsigned long) (dt->shared->u.compnd.memb[i].offset)); -#ifdef OLD_WAY - if (dt->shared->u.compnd.memb[i].ndims) { - fprintf(stream, "["); - for (j = 0; j < dt->shared->u.compnd.memb[i].ndims; j++) { - fprintf(stream, "%s%lu", j ? ", " : "", - (unsigned long)(dt->shared->u.compnd.memb[i].dim[j])); - } - fprintf(stream, "]"); - } -#endif /* OLD_WAY */ fprintf(stream, " "); H5T_debug(dt->shared->u.compnd.memb[i].type, stream); } diff --git a/src/H5Tarray.c b/src/H5Tarray.c index 5a63011..71c80b8 100644 --- a/src/H5Tarray.c +++ b/src/H5Tarray.c @@ -25,14 +25,9 @@ #include "H5private.h" /* Generic Functions */ #include "H5Eprivate.h" /* Error handling */ -#include "H5FLprivate.h" /* Free Lists */ #include "H5Iprivate.h" /* IDs */ #include "H5Tpkg.h" /* Datatypes */ -/* Declare extern the free list for H5T_t's */ -H5FL_EXTERN(H5T_t); -H5FL_EXTERN(H5T_shared_t); - /*-------------------------------------------------------------------------- NAME diff --git a/src/H5Tbit.c b/src/H5Tbit.c index e3769fe..d298d4c 100644 --- a/src/H5Tbit.c +++ b/src/H5Tbit.c @@ -240,12 +240,12 @@ done: * *------------------------------------------------------------------------- */ -hsize_t +uint64_t H5T_bit_get_d (uint8_t *buf, size_t offset, size_t size) { - hsize_t val=0; + uint64_t val=0; size_t i, hs; - hsize_t ret_value; /* Return value */ + uint64_t ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOFUNC(H5T_bit_get_d); @@ -290,7 +290,7 @@ H5T_bit_get_d (uint8_t *buf, size_t offset, size_t size) *------------------------------------------------------------------------- */ void -H5T_bit_set_d (uint8_t *buf, size_t offset, size_t size, hsize_t val) +H5T_bit_set_d (uint8_t *buf, size_t offset, size_t size, uint64_t val) { size_t i, hs; diff --git a/src/H5Tcommit.c b/src/H5Tcommit.c index 098450d..c42b9dd 100644 --- a/src/H5Tcommit.c +++ b/src/H5Tcommit.c @@ -25,6 +25,7 @@ #include "H5private.h" /* Generic Functions */ #include "H5Eprivate.h" /* Error handling */ +#include "H5FLprivate.h" /* Free Lists */ #include "H5FOprivate.h" /* File objects */ #include "H5Iprivate.h" /* IDs */ #include "H5Oprivate.h" /* Object headers */ @@ -32,8 +33,9 @@ #include "H5Tpkg.h" /* Datatypes */ /* Static local functions */ -static herr_t H5T_commit(H5G_entry_t *loc, const char *name, H5T_t *type, +static herr_t H5T_commit(H5G_loc_t *loc, const char *name, H5T_t *type, hid_t dxpl_id, hid_t tcpl_id, hid_t tapl_id); +static H5T_t *H5T_open_oid(H5G_loc_t *loc, hid_t dxpl_id); /*-------------------------------------------------------------------------- @@ -69,36 +71,33 @@ H5T_init_commit_interface(void) * Programmer: Robb Matzke * Monday, June 1, 1998 * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t H5Tcommit(hid_t loc_id, const char *name, hid_t type_id) { - H5G_entry_t *loc = NULL; + H5G_loc_t loc; H5T_t *type = NULL; - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(H5Tcommit, FAIL) H5TRACE3("e","isi",loc_id,name,type_id); /* Check arguments */ - if (NULL==(loc=H5G_loc (loc_id))) - HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") - if (!name || !*name) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "no name") - if (NULL==(type=H5I_object_verify(type_id, H5I_DATATYPE))) - HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype") + if(H5G_loc(loc_id, &loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + if(!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") + if(NULL == (type = H5I_object_verify(type_id, H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype") /* Commit the type */ - if (H5T_commit(loc, name, type, H5AC_dxpl_id, H5P_DATATYPE_CREATE_DEFAULT, - H5P_DEFAULT)<0) - HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to commit datatype") + if(H5T_commit(&loc, name, type, H5AC_dxpl_id, H5P_DATATYPE_CREATE_DEFAULT, H5P_DEFAULT) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to commit datatype") done: FUNC_LEAVE_API(ret_value) -} +} /* end H5Tcommit() */ /*------------------------------------------------------------------------- @@ -113,26 +112,24 @@ done: * Programmer: Peter Cao * May 17, 2005 * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t H5Tcommit_expand(hid_t loc_id, const char *name, hid_t type_id, hid_t tcpl_id, hid_t tapl_id) { - H5G_entry_t *loc = NULL; + H5G_loc_t loc; H5T_t *type = NULL; herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_API(H5Tcommit_expand, FAIL) /* Check arguments */ - if (NULL==(loc=H5G_loc (loc_id))) - HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") - if (!name || !*name) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "no name") - if (NULL==(type=H5I_object_verify(type_id, H5I_DATATYPE))) - HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype") + if(H5G_loc (loc_id, &loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + if(!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") + if(NULL == (type = H5I_object_verify(type_id, H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype") /* Get correct property list */ if(H5P_DEFAULT == tcpl_id) @@ -151,12 +148,12 @@ H5Tcommit_expand(hid_t loc_id, const char *name, hid_t type_id, hid_t tcpl_id, h #endif /* LATER */ /* Commit the type */ - if (H5T_commit(loc, name, type, H5AC_dxpl_id, tcpl_id, tapl_id)<0) + if(H5T_commit(&loc, name, type, H5AC_dxpl_id, tcpl_id, tapl_id) < 0) HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to commit datatype") done: FUNC_LEAVE_API(ret_value) -} +} /* end H5Tcommit_expand() */ /*------------------------------------------------------------------------- @@ -170,29 +167,25 @@ done: * Programmer: Robb Matzke * Monday, June 1, 1998 * - * Modifications: - * Added datatype creation & access property lists - * Peter Cao - * May 17, 2005 - * *------------------------------------------------------------------------- */ static herr_t -H5T_commit(H5G_entry_t *loc, const char *name, H5T_t *type, hid_t dxpl_id, +H5T_commit(H5G_loc_t *loc, const char *name, H5T_t *type, hid_t dxpl_id, hid_t tcpl_id, hid_t UNUSED tapl_id) { H5F_t *file = NULL; H5P_genplist_t *tc_plist; /* Property list created */ - herr_t ret_value=SUCCEED; /* Return value */ + H5G_loc_t type_loc; /* Dataset location */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5T_commit) - HDassert (loc); - HDassert (name && *name); - HDassert (type); - HDassert (tcpl_id != H5P_DEFAULT); + HDassert(loc); + HDassert(name && *name); + HDassert(type); + HDassert(tcpl_id != H5P_DEFAULT); #ifdef LATER - HDassert (tapl_id != H5P_DEFAULT); + HDassert(tapl_id != H5P_DEFAULT); #endif /* LATER */ /* @@ -200,51 +193,56 @@ H5T_commit(H5G_entry_t *loc, const char *name, H5T_t *type, hid_t dxpl_id, * normally fails on such types (try H5Tclose(H5T_NATIVE_INT)) but closing * a named type should always succeed. */ - if (H5T_STATE_NAMED==type->shared->state || H5T_STATE_OPEN==type->shared->state) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "datatype is already committed") - if (H5T_STATE_IMMUTABLE==type->shared->state) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "datatype is immutable") + if(H5T_STATE_NAMED == type->shared->state || H5T_STATE_OPEN == type->shared->state) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "datatype is already committed") + if(H5T_STATE_IMMUTABLE == type->shared->state) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "datatype is immutable") /* Find the insertion file */ - if (NULL==(file=H5G_insertion_file(loc, name, dxpl_id))) + if(NULL == (file = H5G_insertion_file(loc, name, dxpl_id))) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to find insertion point") /* Check for a "sensible" datatype to store on disk */ - if(H5T_is_sensible(type)<=0) + if(H5T_is_sensible(type) <= 0) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "datatype is not sensible") /* Mark datatype as being on disk now. This step changes the size of datatype as * stored on disk. */ - if(H5T_set_loc(type, file, H5T_LOC_DISK)<0) + if(H5T_set_loc(type, file, H5T_LOC_DISK) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "cannot mark datatype on disk") + /* Set up & reset datatype location */ + type_loc.oloc = &(type->oloc); + type_loc.path = &(type->path); + H5G_loc_reset(&type_loc); + /* * Create the object header and open it for write access. Insert the data * type message and then give the object header a name. */ - if (H5O_create (file, dxpl_id, 64, &(type->ent))<0) - HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to create datatype object header") - if (H5O_modify (&(type->ent), H5O_DTYPE_ID, 0, H5O_FLAG_CONSTANT, H5O_UPDATE_TIME, type, dxpl_id)<0) - HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to update type header message") + if(H5O_create(file, dxpl_id, 64, &(type->oloc)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to create datatype object header") + if(H5O_modify(&(type->oloc), H5O_DTYPE_ID, 0, H5O_FLAG_CONSTANT, H5O_UPDATE_TIME, type, dxpl_id) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to update type header message") /* Get the property list */ - if (NULL == (tc_plist = H5I_object(tcpl_id))) + if(NULL == (tc_plist = H5I_object(tcpl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list") /* * Give the datatype a name. That is, create and add a new object to the * group this datatype is being initially created in. */ - if (H5G_insert (loc, name, &(type->ent), dxpl_id, tc_plist)<0) - HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to name datatype") + if(H5G_insert(loc, name, &type_loc, dxpl_id, tc_plist) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to name datatype") type->shared->state = H5T_STATE_OPEN; type->shared->fo_count=1; /* Add datatype to the list of open objects in the file */ - if(H5FO_top_incr(type->ent.file, type->ent.header)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't incr object ref. count") - if(H5FO_insert(type->ent.file, type->ent.header, type->shared)<0) + if(H5FO_top_incr(type->oloc.file, type->oloc.addr) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, FAIL, "can't incr object ref. count") + if(H5FO_insert(type->oloc.file, type->oloc.addr, type->shared) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "can't insert datatype into list of open objects") /* Mark datatype as being on memory now. Since this datatype may still be used in memory @@ -253,18 +251,18 @@ H5T_commit(H5G_entry_t *loc, const char *name, H5T_t *type, hid_t dxpl_id, HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "cannot mark datatype in memory") done: - if (ret_value<0) { - if ((type->shared->state==H5T_STATE_TRANSIENT || type->shared->state==H5T_STATE_RDONLY) && H5F_addr_defined(type->ent.header)) { - if(H5O_close(&(type->ent))<0) + if(ret_value < 0) { + if((type->shared->state == H5T_STATE_TRANSIENT || type->shared->state == H5T_STATE_RDONLY) && H5F_addr_defined(type->oloc.addr)) { + if(H5O_close(&(type->oloc)) < 0) HDONE_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, FAIL, "unable to release object header") - if(H5O_delete(file, dxpl_id,type->ent.header)<0) + if(H5O_delete(file, dxpl_id, type->oloc.addr) < 0) HDONE_ERROR(H5E_DATATYPE, H5E_CANTDELETE, FAIL, "unable to delete object header") - type->ent.header = HADDR_UNDEF; - } - } + type->oloc.addr = HADDR_UNDEF; + } /* end if */ + } /* end if */ FUNC_LEAVE_NOAPI(ret_value) -} +} /* H5T_commit() */ /*------------------------------------------------------------------------- @@ -279,8 +277,6 @@ done: * Programmer: Robb Matzke * Thursday, June 4, 1998 * - * Modifications: - * *------------------------------------------------------------------------- */ htri_t @@ -293,15 +289,15 @@ H5Tcommitted(hid_t type_id) H5TRACE1("t","i",type_id); /* Check arguments */ - if (NULL==(type=H5I_object_verify(type_id,H5I_DATATYPE))) - HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype") + if(NULL == (type = H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype") /* Set return value */ - ret_value= H5T_committed(type); + ret_value = H5T_committed(type); done: FUNC_LEAVE_API(ret_value) -} +} /* end H5Tcommitted() */ /*------------------------------------------------------------------------- @@ -314,8 +310,6 @@ done: * Programmer: Quincey Koziol * Wednesday, September 24, 2003 * - * Modifications: - * *------------------------------------------------------------------------- */ htri_t @@ -324,9 +318,9 @@ H5T_committed(const H5T_t *type) /* Use no-init for efficiency */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_committed) - assert (type); + HDassert(type); - FUNC_LEAVE_NOAPI(H5T_STATE_OPEN==type->shared->state || H5T_STATE_NAMED==type->shared->state) + FUNC_LEAVE_NOAPI(H5T_STATE_OPEN == type->shared->state || H5T_STATE_NAMED == type->shared->state) } /* end H5T_committed() */ @@ -343,8 +337,6 @@ H5T_committed(const H5T_t *type) * Programmer: Quincey Koziol * Friday, September 26, 2003 * - * Modifications: - * *------------------------------------------------------------------------- */ int @@ -355,13 +347,234 @@ H5T_link(const H5T_t *type, int adjust, hid_t dxpl_id) /* Use no-init for efficiency */ FUNC_ENTER_NOAPI(H5T_link,FAIL) - assert (type); + HDassert(type); /* Adjust the link count on the named datatype */ - if((ret_value=H5O_link(&(type->ent),adjust,dxpl_id))<0) - HGOTO_ERROR (H5E_DATATYPE, H5E_LINK, FAIL, "unable to adjust named datatype link count") + if((ret_value = H5O_link(&(type->oloc), adjust, dxpl_id)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_LINK, FAIL, "unable to adjust named datatype link count") done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5T_link() */ + +/*------------------------------------------------------------------------- + * Function: H5Topen + * + * Purpose: Opens a named datatype. + * + * Return: Success: Object ID of the named datatype. + * + * Failure: Negative + * + * Programmer: Robb Matzke + * Monday, June 1, 1998 + * + *------------------------------------------------------------------------- + */ +hid_t +H5Topen(hid_t loc_id, const char *name) +{ + H5T_t *type = NULL; + H5G_loc_t loc; + H5G_name_t path; /* Datatype group hier. path */ + H5O_loc_t oloc; /* Datatype object location */ + H5G_loc_t type_loc; /* Group object for datatype */ + hbool_t obj_found = FALSE; /* Object at 'name' found */ + hid_t dxpl_id = H5AC_dxpl_id; /* dxpl to use to open datatype */ + hid_t ret_value = FAIL; + + FUNC_ENTER_API(H5Topen, FAIL) + H5TRACE2("i","is",loc_id,name); + + /* Check args */ + if(H5G_loc(loc_id, &loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + if(!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name") + + /* Set up datatype location to fill in */ + type_loc.oloc = &oloc; + type_loc.path = &path; + H5G_loc_reset(&type_loc); + + /* + * Find the named datatype object header and read the datatype message + * from it. + */ + if(H5G_loc_find(&loc, name, &type_loc/*out*/, dxpl_id) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, FAIL, "not found") + obj_found = TRUE; + + /* Check that the object found is the correct type */ + if(H5O_obj_type(&oloc, dxpl_id) != H5G_TYPE) + HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, FAIL, "not a named datatype") + + /* Open it */ + if((type = H5T_open(&type_loc, dxpl_id)) == NULL) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, FAIL, "unable to open named datatype") + + /* Register the type and return the ID */ + if((ret_value = H5I_register(H5I_DATATYPE, type)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register named datatype") + +done: + if(ret_value < 0) { + if(type != NULL) + H5T_close(type); + else { + if(obj_found && H5F_addr_defined(type_loc.oloc->addr)) + H5G_name_free(type_loc.path); + } /* end else */ + } /* end if */ + + FUNC_LEAVE_API(ret_value) +} /* end H5Topen() */ + + +/*------------------------------------------------------------------------- + * Function: H5T_open + * + * Purpose: Open a named datatype. + * + * Return: Success: Ptr to a new datatype. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * Monday, June 1, 1998 + * + *------------------------------------------------------------------------- + */ +H5T_t * +H5T_open(H5G_loc_t *loc, hid_t dxpl_id) +{ + H5T_shared_t *shared_fo = NULL; + H5T_t *dt = NULL; + H5T_t *ret_value; + + FUNC_ENTER_NOAPI(H5T_open, NULL) + + HDassert(loc); + + /* Check if datatype was already open */ + if((shared_fo = H5FO_opened(loc->oloc->file, loc->oloc->addr)) == NULL) { + /* Clear any errors from H5FO_opened() */ + H5E_clear_stack(NULL); + + /* Open the datatype object */ + if((dt = H5T_open_oid(loc, dxpl_id)) == NULL) + HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, NULL, "not found") + + /* Add the datatype to the list of opened objects in the file */ + if(H5FO_insert(dt->oloc.file, dt->oloc.addr, dt->shared) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, NULL, "can't insert datatype into list of open objects") + + /* Increment object count for the object in the top file */ + if(H5FO_top_incr(dt->oloc.file, dt->oloc.addr) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count") + + /* Mark any datatypes as being in memory now */ + if(H5T_set_loc(dt, NULL, H5T_LOC_MEMORY) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "invalid datatype location") + + dt->shared->fo_count = 1; + } /* end if */ + else { + if(NULL == (dt = H5FL_MALLOC(H5T_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate space for datatype") + + /* Shallow copy (take ownership) of the object location object */ + if(H5O_loc_copy(&(dt->oloc), loc->oloc, H5O_COPY_SHALLOW) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy object location") + + /* Shallow copy (take ownership) of the group hier. path */ + if(H5G_name_copy(&(dt->path), loc->path, H5G_COPY_SHALLOW) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy path") + + dt->shared = shared_fo; + + shared_fo->fo_count++; + + /* Check if the object has been opened through the top file yet */ + if(H5FO_top_count(dt->oloc.file, dt->oloc.addr) == 0) { + /* Open the object through this top file */ + if(H5O_open(&(dt->oloc)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to open object header") + } /* end if */ + + /* Increment object count for the object in the top file */ + if(H5FO_top_incr(dt->oloc.file, dt->oloc.addr) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count") + } /* end else */ + + ret_value = dt; + +done: + if(ret_value == NULL) { + if(dt) { + if(shared_fo == NULL) /* Need to free shared fo */ + H5FL_FREE(H5T_shared_t, dt->shared); + H5FL_FREE(H5T_t, dt); + } /* end if */ + + if(shared_fo) + shared_fo->fo_count--; + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T_open() */ + + +/*------------------------------------------------------------------------- + * Function: H5T_open_oid + * + * Purpose: Open a named datatype. + * + * Return: Success: Ptr to a new datatype. + * + * Failure: NULL + * + * Programmer: Quincey Koziol + * Wednesday, March 17, 1999 + * + *------------------------------------------------------------------------- + */ +static H5T_t * +H5T_open_oid(H5G_loc_t *loc, hid_t dxpl_id) +{ + H5T_t *dt = NULL; + H5T_t *ret_value; + + FUNC_ENTER_NOAPI(H5T_open_oid, NULL) + + HDassert(loc); + + if(H5O_open(loc->oloc) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to open named datatype") + if(NULL == (dt = H5O_read(loc->oloc, H5O_DTYPE_ID, 0, NULL, dxpl_id))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to load type message from object header") + + /* Mark the type as named and open */ + dt->shared->state = H5T_STATE_OPEN; + + /* Shallow copy (take ownership) of the object location object */ + if(H5O_loc_copy(&(dt->oloc), loc->oloc, H5O_COPY_SHALLOW) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy object location") + + /* Shallow copy (take ownership) of the group hier. path */ + if(H5G_name_copy(&(dt->path), loc->path, H5G_COPY_SHALLOW) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy path") + + /* Set return value */ + ret_value = dt; + +done: + if(ret_value == NULL) { + if(dt == NULL) + H5O_close(loc->oloc); + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T_open_oid() */ + diff --git a/src/H5Tconv.c b/src/H5Tconv.c index 5cfdfba..32f647e 100644 --- a/src/H5Tconv.c +++ b/src/H5Tconv.c @@ -21,6 +21,7 @@ #include "H5private.h" /*generic functions */ #include "H5Eprivate.h" /*error handling */ #include "H5FLprivate.h" /*Free Lists */ +#include "H5HGprivate.h" /* Global Heaps */ #include "H5Iprivate.h" /*ID functions */ #include "H5MMprivate.h" /*memory management */ #include "H5Pprivate.h" /* Property Lists */ @@ -3555,7 +3556,7 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, size_t elmtno; /*element number */ size_t half_size; /*half the type size */ size_t olap; /*num overlapping elements */ - ssize_t bitno; /*bit number */ + ssize_t bitno = 0; /*bit number */ uint8_t *s, *sp, *d, *dp; /*source and dest traversal ptrs*/ uint8_t *src_rev=NULL; /*order-reversed source buffer */ uint8_t dbuf[64]; /*temp destination buffer */ @@ -4200,7 +4201,8 @@ H5T_conv_s_s (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, while (nchars>0 && ' '==s[nchars-1]) --nchars; nchars = MIN(dst->shared->size, nchars); - HDmemcpy(d, s, nchars); + if(d != s) + HDmemcpy(d, s, nchars); break; case H5T_STR_RESERVED_3: diff --git a/src/H5Tenum.c b/src/H5Tenum.c index be80563..6d45e57 100644 --- a/src/H5Tenum.c +++ b/src/H5Tenum.c @@ -25,15 +25,10 @@ #include "H5private.h" /*generic functions */ #include "H5Eprivate.h" /*error handling */ -#include "H5FLprivate.h" /*Free Lists */ #include "H5Iprivate.h" /*ID functions */ #include "H5MMprivate.h" /*memory management */ #include "H5Tpkg.h" /*data-type functions */ -/* Declare extern the free lists for H5T_t's and H5T_shared_t's */ -H5FL_EXTERN(H5T_t); -H5FL_EXTERN(H5T_shared_t); - /* Static local functions */ static char *H5T_enum_nameof(const H5T_t *dt, const void *value, char *name/*out*/, size_t size); diff --git a/src/H5Tpkg.h b/src/H5Tpkg.h index 35c3781..522329b 100644 --- a/src/H5Tpkg.h +++ b/src/H5Tpkg.h @@ -39,6 +39,8 @@ /* Other private headers needed by this file */ #include "H5Fprivate.h" /* Files */ +#include "H5FLprivate.h" /* Free Lists */ +#include "H5Oprivate.h" /* Object headers */ /* Other public headers needed by this file */ #include "H5Spublic.h" /* Dataspace functions */ @@ -150,6 +152,8 @@ #if (H5_WANT_DATA_ACCURACY && H5_FP_TO_ULLONG_ACCURATE && H5_FP_TO_ULLONG_RIGHT_MAXIMUM) || \ (!H5_WANT_DATA_ACCURACY) #define H5T_CONV_INTERNAL_FP_ULLONG 1 +#else +#define H5T_CONV_INTERNAL_FP_ULLONG 0 #endif /* Define an internal macro for converting long double to all integers. SGI compilers give some incorrect @@ -158,6 +162,8 @@ H5_FP_TO_ULLONG_ACCURATE && H5_FP_TO_ULLONG_RIGHT_MAXIMUM) || \ (!H5_WANT_DATA_ACCURACY && H5_LDOUBLE_TO_INTEGER_WORKS) #define H5T_CONV_INTERNAL_LDOUBLE_ULLONG 1 +#else +#define H5T_CONV_INTERNAL_LDOUBLE_ULLONG 0 #endif /* Statistics about a conversion function */ @@ -311,8 +317,9 @@ typedef struct H5T_shared_t { } H5T_shared_t; struct H5T_t { - H5G_entry_t ent; /* entry information if the type is a named type */ H5T_shared_t *shared; /* all other information */ + H5O_loc_t oloc; /* object location information if the type is a named type */ + H5G_name_t path; /* group hier. path if the type is a named type */ }; /* A compound datatype member */ @@ -425,6 +432,10 @@ H5_DLLVAR double H5T_NATIVE_LDOUBLE_POS_INF_g; H5_DLLVAR double H5T_NATIVE_LDOUBLE_NEG_INF_g; #endif +/* Declare extern the free lists for H5T_t's and H5T_shared_t's */ +H5FL_EXTERN(H5T_t); +H5FL_EXTERN(H5T_shared_t); + /* Common functions */ H5_DLL H5T_t *H5T_create(H5T_class_t type, size_t size); H5_DLL H5T_t *H5T_alloc(void); @@ -1288,9 +1299,9 @@ H5_DLL void H5T_bit_copy(uint8_t *dst, size_t dst_offset, const uint8_t *src, H5_DLL void H5T_bit_shift(uint8_t *buf, ssize_t shift_dist, size_t offset, size_t size); H5_DLL void H5T_bit_set(uint8_t *buf, size_t offset, size_t size, hbool_t value); -H5_DLL hsize_t H5T_bit_get_d(uint8_t *buf, size_t offset, size_t size); +H5_DLL uint64_t H5T_bit_get_d(uint8_t *buf, size_t offset, size_t size); H5_DLL void H5T_bit_set_d(uint8_t *buf, size_t offset, size_t size, - hsize_t val); + uint64_t val); H5_DLL ssize_t H5T_bit_find(uint8_t *buf, size_t offset, size_t size, H5T_sdir_t direction, hbool_t value); H5_DLL htri_t H5T_bit_inc(uint8_t *buf, size_t start, size_t size); diff --git a/src/H5Tprivate.h b/src/H5Tprivate.h index 0ec08a7..62a4e13 100644 --- a/src/H5Tprivate.h +++ b/src/H5Tprivate.h @@ -66,17 +66,17 @@ typedef struct H5T_conv_cb_t { /* Private functions */ H5_DLL herr_t H5TN_init_interface(void); H5_DLL herr_t H5T_init(void); -H5_DLL htri_t H5T_isa(H5G_entry_t *ent, hid_t dxpl_id); -H5_DLL H5T_t *H5T_open(H5G_entry_t *ent, hid_t dxpl_id); +H5_DLL htri_t H5T_isa(struct H5O_loc_t *loc, hid_t dxpl_id); H5_DLL H5T_t *H5T_copy(const H5T_t *old_dt, H5T_copy_t method); H5_DLL herr_t H5T_lock(H5T_t *dt, hbool_t immutable); H5_DLL herr_t H5T_close(H5T_t *dt); H5_DLL H5T_class_t H5T_get_class(const H5T_t *dt, htri_t internal); -H5_DLL htri_t H5T_detect_class (const H5T_t *dt, H5T_class_t cls); +H5_DLL htri_t H5T_detect_class(const H5T_t *dt, H5T_class_t cls); H5_DLL size_t H5T_get_size(const H5T_t *dt); H5_DLL int H5T_cmp(const H5T_t *dt1, const H5T_t *dt2, hbool_t superset); H5_DLL herr_t H5T_debug(const H5T_t *dt, FILE * stream); -H5_DLL H5G_entry_t *H5T_entof(H5T_t *dt); +H5_DLL struct H5O_loc_t *H5T_oloc(H5T_t *dt); +H5_DLL H5G_name_t *H5T_nameof(H5T_t *dt); H5_DLL htri_t H5T_is_immutable(const H5T_t *dt); H5_DLL htri_t H5T_is_named(const H5T_t *dt); H5_DLL htri_t H5T_is_relocatable(const H5T_t *dt); @@ -91,10 +91,13 @@ H5_DLL herr_t H5T_vlen_reclaim(void *elem, hid_t type_id, unsigned ndim, const h H5_DLL herr_t H5T_vlen_get_alloc_info(hid_t dxpl_id, H5T_vlen_alloc_info_t **vl_alloc_info); H5_DLL htri_t H5T_set_loc(H5T_t *dt, H5F_t *f, H5T_loc_t loc); H5_DLL htri_t H5T_is_sensible(const H5T_t *dt); -H5_DLL htri_t H5T_committed(const H5T_t *type); -H5_DLL int H5T_link(const H5T_t *type, int adjust, hid_t dxpl_id); /* Reference specific functions */ H5_DLL H5R_type_t H5T_get_ref_type(const H5T_t *dt); +/* Operations on named datatypes */ +H5_DLL H5T_t *H5T_open(H5G_loc_t *loc, hid_t dxpl_id); +H5_DLL htri_t H5T_committed(const H5T_t *type); +H5_DLL int H5T_link(const H5T_t *type, int adjust, hid_t dxpl_id); + #endif diff --git a/src/H5Tvlen.c b/src/H5Tvlen.c index 081d896..e4b40f9 100644 --- a/src/H5Tvlen.c +++ b/src/H5Tvlen.c @@ -26,7 +26,6 @@ #include "H5private.h" /* Generic Functions */ #include "H5Dprivate.h" /* Dataset functions */ #include "H5Eprivate.h" /* Error handling */ -#include "H5FLprivate.h" /* Free Lists */ #include "H5HGprivate.h" /* Global Heaps */ #include "H5Iprivate.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ @@ -64,10 +63,6 @@ static H5T_vlen_alloc_info_t H5T_vlen_def_vl_alloc_info ={ H5D_XFER_VLEN_FREE_INFO_DEF }; -/* Declare extern the free lists for H5T_t's and H5T_shared_t's */ -H5FL_EXTERN(H5T_t); -H5FL_EXTERN(H5T_shared_t); - /*-------------------------------------------------------------------------- NAME diff --git a/src/H5err.txt b/src/H5err.txt index 76a9de0..65c4e1f 100644 --- a/src/H5err.txt +++ b/src/H5err.txt @@ -176,6 +176,7 @@ MINOR, OHDR, H5E_ALIGNMENT, Alignment error MINOR, OHDR, H5E_BADMESG, Unrecognized message MINOR, OHDR, H5E_CANTDELETE, Can't delete message MINOR, OHDR, H5E_BADITER, Iteration failed +MINOR, OHDR, H5E_CANTPACK, Can't pack messages # Group related errors MINOR, GROUP, H5E_CANTOPENOBJ, Can't open object diff --git a/src/H5private.h b/src/H5private.h index 9b45463..28ec832 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -1392,6 +1392,7 @@ H5_DLL int H5E_term_interface(void); H5_DLL int H5F_term_interface(void); H5_DLL int H5G_term_interface(void); H5_DLL int H5I_term_interface(void); +H5_DLL int H5O_term_interface(void); H5_DLL int H5P_term_interface(void); H5_DLL int H5R_term_interface(void); H5_DLL int H5S_term_interface(void); diff --git a/src/Makefile.am b/src/Makefile.am index b4307a0..cf9ebd1 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -49,12 +49,18 @@ libhdf5_la_SOURCES= H5.c H5A.c H5AC.c H5B.c H5Bcache.c H5B2.c H5B2cache.c \ H5FDfamily.c H5FDfphdf5.c H5FDlog.c H5FDmpi.c H5FDmpio.c \ H5FDmpiposix.c H5FDmulti.c H5FDsec2.c H5FDstdio.c \ H5FDstream.c H5FL.c H5FO.c H5FP.c H5FPclient.c H5FPserver.c H5FS.c \ - H5G.c H5Gent.c H5Gnode.c H5Gstab.c \ + H5G.c H5Gent.c H5Glink.c H5Gloc.c H5Gname.c H5Gnode.c H5Gobj.c \ + H5Gstab.c \ + H5Gtest.c \ + H5Gtraverse.c \ H5HG.c H5HGdbg.c H5HL.c H5HLdbg.c H5HP.c H5I.c H5MF.c H5MM.c \ H5MP.c H5MPtest.c \ H5O.c \ - H5Oattr.c H5Obogus.c \ - H5Ocont.c H5Odtype.c H5Oefl.c H5Ofill.c H5Olayout.c H5Omtime.c \ + H5Oattr.c H5Obogus.c H5Ocache.c \ + H5Ocont.c H5Odtype.c H5Oefl.c H5Ofill.c H5Oginfo.c H5Olayout.c \ + H5Olinfo.c \ + H5Olink.c \ + H5Omtime.c \ H5Oname.c H5Onull.c H5Opline.c H5Osdspace.c H5Oshared.c H5Ostab.c \ H5P.c H5Pdcpl.c H5Pdxpl.c H5Pfapl.c H5Pfcpl.c H5Pgcpl.c H5Pocpl.c \ H5Ptest.c \ diff --git a/src/Makefile.in b/src/Makefile.in index 516859b..2ae474f 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -92,10 +92,12 @@ am_libhdf5_la_OBJECTS = H5.lo H5A.lo H5AC.lo H5B.lo H5Bcache.lo \ H5FDfphdf5.lo H5FDlog.lo H5FDmpi.lo H5FDmpio.lo \ H5FDmpiposix.lo H5FDmulti.lo H5FDsec2.lo H5FDstdio.lo \ H5FDstream.lo H5FL.lo H5FO.lo H5FP.lo H5FPclient.lo \ - H5FPserver.lo H5FS.lo H5G.lo H5Gent.lo H5Gnode.lo H5Gstab.lo \ - H5HG.lo H5HGdbg.lo H5HL.lo H5HLdbg.lo H5HP.lo H5I.lo H5MF.lo \ - H5MM.lo H5MP.lo H5MPtest.lo H5O.lo H5Oattr.lo H5Obogus.lo \ - H5Ocont.lo H5Odtype.lo H5Oefl.lo H5Ofill.lo H5Olayout.lo \ + H5FPserver.lo H5FS.lo H5G.lo H5Gent.lo H5Glink.lo H5Gloc.lo \ + H5Gname.lo H5Gnode.lo H5Gobj.lo H5Gstab.lo H5Gtest.lo \ + H5Gtraverse.lo H5HG.lo H5HGdbg.lo H5HL.lo H5HLdbg.lo H5HP.lo \ + H5I.lo H5MF.lo H5MM.lo H5MP.lo H5MPtest.lo H5O.lo H5Oattr.lo \ + H5Obogus.lo H5Ocache.lo H5Ocont.lo H5Odtype.lo H5Oefl.lo \ + H5Ofill.lo H5Oginfo.lo H5Olayout.lo H5Olinfo.lo H5Olink.lo \ H5Omtime.lo H5Oname.lo H5Onull.lo H5Opline.lo H5Osdspace.lo \ H5Oshared.lo H5Ostab.lo H5P.lo H5Pdcpl.lo H5Pdxpl.lo \ H5Pfapl.lo H5Pfcpl.lo H5Pgcpl.lo H5Pocpl.lo H5Ptest.lo H5R.lo \ @@ -396,12 +398,18 @@ libhdf5_la_SOURCES = H5.c H5A.c H5AC.c H5B.c H5Bcache.c H5B2.c H5B2cache.c \ H5FDfamily.c H5FDfphdf5.c H5FDlog.c H5FDmpi.c H5FDmpio.c \ H5FDmpiposix.c H5FDmulti.c H5FDsec2.c H5FDstdio.c \ H5FDstream.c H5FL.c H5FO.c H5FP.c H5FPclient.c H5FPserver.c H5FS.c \ - H5G.c H5Gent.c H5Gnode.c H5Gstab.c \ + H5G.c H5Gent.c H5Glink.c H5Gloc.c H5Gname.c H5Gnode.c H5Gobj.c \ + H5Gstab.c \ + H5Gtest.c \ + H5Gtraverse.c \ H5HG.c H5HGdbg.c H5HL.c H5HLdbg.c H5HP.c H5I.c H5MF.c H5MM.c \ H5MP.c H5MPtest.c \ H5O.c \ - H5Oattr.c H5Obogus.c \ - H5Ocont.c H5Odtype.c H5Oefl.c H5Ofill.c H5Olayout.c H5Omtime.c \ + H5Oattr.c H5Obogus.c H5Ocache.c \ + H5Ocont.c H5Odtype.c H5Oefl.c H5Ofill.c H5Oginfo.c H5Olayout.c \ + H5Olinfo.c \ + H5Olink.c \ + H5Omtime.c \ H5Oname.c H5Onull.c H5Opline.c H5Osdspace.c H5Oshared.c H5Ostab.c \ H5P.c H5Pdcpl.c H5Pdxpl.c H5Pfapl.c H5Pfcpl.c H5Pgcpl.c H5Pocpl.c \ H5Ptest.c \ @@ -601,8 +609,14 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fsuper.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5G.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Gent.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Glink.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Gloc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Gname.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Gnode.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Gobj.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Gstab.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Gtest.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Gtraverse.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HG.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HGdbg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HL.Plo@am__quote@ @@ -616,11 +630,15 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5O.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Oattr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Obogus.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Ocache.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Ocont.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Odtype.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Oefl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Ofill.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Oginfo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Olayout.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Olinfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Olink.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Omtime.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Oname.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Onull.Plo@am__quote@ |