diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2005-11-15 02:55:39 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2005-11-15 02:55:39 (GMT) |
commit | a1708eb023f2c8f8ac6c2c17bf1e598c8dff956e (patch) | |
tree | 34c87a3753b36c4c8d689d58bf456eaf261cd235 /src | |
parent | bea1e576c5ef5500678f7ce913d835341b625e8f (diff) | |
download | hdf5-a1708eb023f2c8f8ac6c2c17bf1e598c8dff956e.zip hdf5-a1708eb023f2c8f8ac6c2c17bf1e598c8dff956e.tar.gz hdf5-a1708eb023f2c8f8ac6c2c17bf1e598c8dff956e.tar.bz2 |
[svn-r11712] Purpose:
New feature
Description:
Check in baseline for compact group revisions, which radically revises the
source code for managing groups and object headers.
WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!!
WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!!
This initiates the "unstable" phase of the 1.7.x branch, leading up
to the 1.8.0 release. Please test this code, but do _NOT_ keep files created
with it - the format will change again before the release and you will not
be able to read your old files!!!
WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!!
WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!! WARNING!!!!
Solution:
There's too many changes to really describe them all, but some of them
include:
- Stop abusing the H5G_entry_t structure and split it into two separate
structures for non-symbol table node use within the library: H5O_loc_t
for object locations in a file and H5G_name_t to store the path to
an opened object. H5G_entry_t is now only used for storing symbol
table entries on disk.
- Retire H5G_namei() in favor of a more general mechanism for traversing
group paths and issuing callbacks on objects located. This gets us out
of the business of hacking H5G_namei() for new features, generally.
- Revised H5O* routines to take a H5O_loc_t instead of H5G_entry_t
- Lots more...
Platforms tested:
h5committested and maybe another dozen configurations.... :-)
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@ |