mirror of
https://github.com/HDFGroup/hdf5.git
synced 2025-03-31 17:10:47 +08:00
[svn-r13041] Description:
Migrate "internalish" attribute operations into new source code file. Add test & basic support for opening attributes in dense storage (shared attributes not tested or supported yet). Tested on: Linux/32 2.6 (chicago) Linux/64 2.6 (chicago2)
This commit is contained in:
parent
e8d8f70f51
commit
dc73eca159
1
MANIFEST
1
MANIFEST
@ -574,6 +574,7 @@
|
||||
./src/H5O.c
|
||||
./src/H5Oalloc.c
|
||||
./src/H5Oattr.c
|
||||
./src/H5Oattribute.c
|
||||
./src/H5Obogus.c
|
||||
./src/H5Ocache.c
|
||||
./src/H5Ocont.c
|
||||
|
109
src/H5A.c
109
src/H5A.c
@ -17,6 +17,7 @@
|
||||
/****************/
|
||||
|
||||
#define H5A_PACKAGE /*suppress error about including H5Apkg */
|
||||
#define H5O_PACKAGE /*suppress error about including H5Opkg */
|
||||
|
||||
/* Interface initialization */
|
||||
#define H5_INTERFACE_INIT_FUNC H5A_init_interface
|
||||
@ -31,6 +32,7 @@
|
||||
#include "H5FLprivate.h" /* Free Lists */
|
||||
#include "H5Iprivate.h" /* IDs */
|
||||
#include "H5MMprivate.h" /* Memory management */
|
||||
#include "H5Opkg.h" /* Object headers */
|
||||
#include "H5Sprivate.h" /* Dataspace functions */
|
||||
#include "H5SMprivate.h" /* Shared Object Header Messages */
|
||||
|
||||
@ -64,8 +66,10 @@ typedef struct H5A_iter_cb1 {
|
||||
/********************/
|
||||
|
||||
static hid_t H5A_create(const H5G_loc_t *loc, const char *name,
|
||||
const H5T_t *type, const H5S_t *space, hid_t acpl_id, hid_t dxpl_id);
|
||||
const H5T_t *type, const H5S_t *space, hid_t acpl_id, hid_t dxpl_id);
|
||||
static hid_t H5A_open(H5G_loc_t *loc, unsigned idx, hid_t dxpl_id);
|
||||
static H5A_t *H5A_open_by_name(const H5G_loc_t *loc, const char *name,
|
||||
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(H5O_loc_t *loc, const char *name, hid_t dxpl_id);
|
||||
@ -548,7 +552,7 @@ hid_t
|
||||
H5Aopen_name(hid_t loc_id, const char *name)
|
||||
{
|
||||
H5G_loc_t loc; /* Object location */
|
||||
int idx;
|
||||
H5A_t *attr = NULL; /* Attribute opened */
|
||||
hid_t ret_value;
|
||||
|
||||
FUNC_ENTER_API(H5Aopen_name, FAIL)
|
||||
@ -562,13 +566,13 @@ H5Aopen_name(hid_t loc_id, const char *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(loc.oloc, name, H5AC_ind_dxpl_id)) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, "attribute not found")
|
||||
/* Open the attribute on the object header */
|
||||
if(NULL == (attr = H5A_open_by_name(&loc, name, H5AC_ind_dxpl_id)))
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "can't open attribute")
|
||||
|
||||
/* Go do the real work for opening the attribute */
|
||||
if((ret_value = H5A_open(&loc, (unsigned)idx, H5AC_dxpl_id)) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to open attribute")
|
||||
/* Register the attribute and get an ID for it */
|
||||
if((ret_value = H5I_register(H5I_ATTR, attr)) < 0)
|
||||
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register attribute for ID")
|
||||
|
||||
done:
|
||||
FUNC_LEAVE_API(ret_value)
|
||||
@ -676,7 +680,7 @@ H5A_open(H5G_loc_t *loc, unsigned idx, hid_t dxpl_id)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open")
|
||||
attr->obj_opened = TRUE;
|
||||
|
||||
/* Register the new attribute and get an ID for it */
|
||||
/* Register the attribute and get an ID for it */
|
||||
if((ret_value = H5I_register(H5I_ATTR, attr)) < 0)
|
||||
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register attribute for ID")
|
||||
|
||||
@ -689,6 +693,77 @@ done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* H5A_open() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5A_open_by_name
|
||||
*
|
||||
* Purpose:
|
||||
* Open an attribute in an object header, according to it's name
|
||||
*
|
||||
* Usage:
|
||||
* herr_t H5A_open(loc, name, dxpl_id)
|
||||
* const H5G_loc_t *loc; IN: Pointer to group location for object
|
||||
* const char *name; IN: Name of attribute to open
|
||||
* hid_t dxpl_id; IN: DXPL for operation
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Quincey Koziol
|
||||
* December 11, 2006
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static H5A_t *
|
||||
H5A_open_by_name(const H5G_loc_t *loc, const char *name, hid_t dxpl_id)
|
||||
{
|
||||
H5A_t *attr = NULL; /* Attribute from object header */
|
||||
H5A_t *ret_value; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI_NOINIT(H5A_open_by_name)
|
||||
|
||||
/* check args */
|
||||
HDassert(loc);
|
||||
HDassert(name);
|
||||
|
||||
/* Read in attribute from object header */
|
||||
if(NULL == (attr = H5O_attr_open(loc->oloc, name, dxpl_id)))
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to load attribute info from object header")
|
||||
attr->initialized = TRUE;
|
||||
|
||||
#if defined(H5_USING_PURIFY) || !defined(NDEBUG)
|
||||
/* Clear object location */
|
||||
if(H5O_loc_reset(&(attr->oloc)) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to reset location")
|
||||
|
||||
/* Clear path name */
|
||||
if(H5G_name_reset(&(attr->path)) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to reset path")
|
||||
#endif /* H5_USING_PURIFY */
|
||||
|
||||
/* Deep copy of the symbol table entry */
|
||||
if(H5O_loc_copy(&(attr->oloc), loc->oloc, H5_COPY_DEEP) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to copy entry")
|
||||
|
||||
/* Deep copy of the group hier. path */
|
||||
if(H5G_name_copy(&(attr->path), loc->path, H5_COPY_DEEP) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to copy entry")
|
||||
|
||||
/* Hold the symbol table entry (and file) open */
|
||||
if(H5O_open(&(attr->oloc)) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to open")
|
||||
attr->obj_opened = TRUE;
|
||||
|
||||
/* Set return value */
|
||||
ret_value = attr;
|
||||
|
||||
done:
|
||||
/* Cleanup on failure */
|
||||
if(ret_value == NULL && attr)
|
||||
(void)H5A_close(attr);
|
||||
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* H5A_open_by_name() */
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
NAME
|
||||
@ -1200,14 +1275,14 @@ H5Aget_name(hid_t attr_id, size_t buf_size, char *buf)
|
||||
|
||||
/* Terminate the string */
|
||||
buf[copy_len]='\0';
|
||||
}
|
||||
} /* end if */
|
||||
|
||||
/* Set return value */
|
||||
ret_value = (ssize_t)nbytes;
|
||||
|
||||
done:
|
||||
FUNC_LEAVE_API(ret_value)
|
||||
} /* H5Aget_type() */
|
||||
} /* H5Aget_name() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
@ -1511,9 +1586,12 @@ H5A_copy(H5A_t *_new_attr, const H5A_t *old_attr)
|
||||
new_attr->obj_opened = FALSE;
|
||||
|
||||
/* Copy the guts of the attribute */
|
||||
new_attr->name = H5MM_xstrdup(old_attr->name);
|
||||
new_attr->dt = H5T_copy(old_attr->dt, H5T_COPY_ALL);
|
||||
new_attr->ds = H5S_copy(old_attr->ds, FALSE);
|
||||
if(NULL == (new_attr->name = H5MM_xstrdup(old_attr->name)))
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "unable to copy attribute name")
|
||||
if(NULL == (new_attr->dt = H5T_copy(old_attr->dt, H5T_COPY_ALL)))
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "unable to copy attribute datatype")
|
||||
if(NULL == (new_attr->ds = H5S_copy(old_attr->ds, FALSE)))
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "unable to copy attribute dataspace")
|
||||
/* XXX: Copy the object location and group path? -QAK */
|
||||
|
||||
/* Copy the attribute data, if there is any */
|
||||
@ -1530,10 +1608,9 @@ H5A_copy(H5A_t *_new_attr, const H5A_t *old_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 */
|
||||
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5A_copy() */
|
||||
|
@ -247,6 +247,100 @@ done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5A_dense_create() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5A_dense_open_cb
|
||||
*
|
||||
* Purpose: Callback when an attribute is located in an index
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Quincey Koziol
|
||||
* koziol@hdfgroup.org
|
||||
* Dec 11 2006
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static herr_t
|
||||
H5A_dense_open_cb(const void *_attr, void *_user_attr)
|
||||
{
|
||||
const H5A_t *attr = (const H5A_t *)_attr; /* Record from B-tree */
|
||||
H5A_t **user_attr = (H5A_t **)_user_attr; /* User data from v2 B-tree attribute lookup */
|
||||
herr_t ret_value = SUCCEED; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI_NOINIT(H5A_dense_open_cb)
|
||||
|
||||
/*
|
||||
* Check arguments.
|
||||
*/
|
||||
HDassert(attr);
|
||||
HDassert(user_attr);
|
||||
|
||||
/* Copy attribute information */
|
||||
if(NULL == (*user_attr = H5A_copy(NULL, attr)))
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute")
|
||||
|
||||
done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5A_dense_open_cb() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5A_dense_open
|
||||
*
|
||||
* Purpose: Open an attribute in dense storage structures for an object
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Quincey Koziol
|
||||
* koziol@hdfgroup.org
|
||||
* Dec 11 2006
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
H5A_t *
|
||||
H5A_dense_open(H5F_t *f, hid_t dxpl_id, const H5O_t *oh, const char *name)
|
||||
{
|
||||
H5A_bt2_ud_common_t udata; /* User data for v2 B-tree modify */
|
||||
H5HF_t *fheap = NULL; /* Fractal heap handle */
|
||||
H5A_t *ret_value = NULL; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI(H5A_dense_open, NULL)
|
||||
|
||||
/*
|
||||
* Check arguments.
|
||||
*/
|
||||
HDassert(f);
|
||||
HDassert(oh);
|
||||
HDassert(name);
|
||||
|
||||
/* Open the fractal heap */
|
||||
if(NULL == (fheap = H5HF_open(f, dxpl_id, oh->attr_fheap_addr)))
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to open fractal heap")
|
||||
|
||||
/* Create the "udata" information for v2 B-tree record modify */
|
||||
udata.f = f;
|
||||
udata.dxpl_id = dxpl_id;
|
||||
udata.fheap = fheap;
|
||||
udata.name = name;
|
||||
udata.name_hash = H5_checksum_lookup3(name, HDstrlen(name), 0);
|
||||
udata.flags = 0;
|
||||
udata.corder = -1; /* XXX: None yet */
|
||||
udata.found_op = H5A_dense_open_cb; /* v2 B-tree comparison callback */
|
||||
udata.found_op_data = &ret_value;
|
||||
|
||||
/* Find & copy the attribute in the 'name' index */
|
||||
if(H5B2_find(f, dxpl_id, H5A_BT2_NAME, oh->name_bt2_addr, &udata, NULL, NULL) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "can't locate attribute in name index")
|
||||
|
||||
done:
|
||||
/* Release resources */
|
||||
if(fheap && H5HF_close(fheap, dxpl_id) < 0)
|
||||
HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, NULL, "can't close fractal heap")
|
||||
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5A_dense_open() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5A_dense_insert
|
||||
|
@ -140,11 +140,17 @@ H5_DLL herr_t H5A_free(H5A_t *attr);
|
||||
H5_DLL herr_t H5A_close(H5A_t *attr);
|
||||
|
||||
/* Attribute "dense" storage routines */
|
||||
H5_DLL H5A_t *H5A_dense_open(H5F_t *f, hid_t dxpl_id, const H5O_t *oh,
|
||||
const char *name);
|
||||
H5_DLL herr_t H5A_dense_write(H5F_t *f, hid_t dxpl_id, const H5O_t *oh,
|
||||
const H5A_t *attr);
|
||||
H5_DLL herr_t H5A_dense_iterate(H5F_t *f, hid_t dxpl_id, hid_t loc_id,
|
||||
haddr_t attr_fheap_addr, haddr_t name_bt2_addr, unsigned skip,
|
||||
unsigned *last_attr, H5A_operator_t op, void *op_data);
|
||||
|
||||
/* Attribute object header routines */
|
||||
H5_DLL herr_t H5O_attr_reset(void *_mesg);
|
||||
H5_DLL herr_t H5O_attr_get_share(const void *_mesg, H5O_shared_t *sh);
|
||||
|
||||
#endif /* _H5Apkg_H */
|
||||
|
||||
|
@ -482,12 +482,9 @@ H5G_dense_lookup_cb(const void *_lnk, void *_user_lnk)
|
||||
HDassert(lnk);
|
||||
HDassert(user_lnk);
|
||||
|
||||
/* Check if we want the link information */
|
||||
if(user_lnk) {
|
||||
/* Copy link information */
|
||||
if(H5O_msg_copy(H5O_LINK_ID, lnk, user_lnk) == NULL)
|
||||
HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy link message")
|
||||
} /* end if */
|
||||
/* Copy link information */
|
||||
if(H5O_msg_copy(H5O_LINK_ID, lnk, user_lnk) == NULL)
|
||||
HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy link message")
|
||||
|
||||
done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
|
668
src/H5Oattr.c
668
src/H5Oattr.c
@ -21,63 +21,17 @@
|
||||
#include "H5Apkg.h" /* Attributes */
|
||||
#include "H5Dprivate.h" /* Datasets */
|
||||
#include "H5Eprivate.h" /* Error handling */
|
||||
#include "H5FLprivate.h" /* Free Lists */
|
||||
#include "H5Gprivate.h" /* Groups */
|
||||
#include "H5Iprivate.h" /* IDs */
|
||||
#include "H5MMprivate.h" /* Memory management */
|
||||
#include "H5Opkg.h" /* Object headers */
|
||||
#include "H5Spkg.h" /* Dataspaces */
|
||||
#include "H5SMprivate.h" /* Shared Object Header Messages */
|
||||
|
||||
/* User data for iteration when converting attributes to dense storage */
|
||||
typedef struct {
|
||||
H5F_t *f; /* Pointer to file for insertion */
|
||||
hid_t dxpl_id; /* DXPL during iteration */
|
||||
} H5O_iter_cvt_t;
|
||||
|
||||
/* User data for iteration when updating an attribute */
|
||||
typedef struct {
|
||||
/* down */
|
||||
H5F_t *f; /* Pointer to file attribute is in */
|
||||
hid_t dxpl_id; /* DXPL for operation */
|
||||
H5A_t *attr; /* Attribute data to update object header with */
|
||||
|
||||
/* up */
|
||||
hbool_t found; /* Whether the attribute was found */
|
||||
} H5O_iter_wrt_t;
|
||||
|
||||
/* User data for iteration when renaming an attribute */
|
||||
typedef struct {
|
||||
/* down */
|
||||
H5F_t *f; /* Pointer to file attribute is in */
|
||||
hid_t dxpl_id; /* DXPL for operation */
|
||||
const char *old_name; /* Old name of attribute */
|
||||
const char *new_name; /* New name of attribute */
|
||||
|
||||
/* up */
|
||||
hbool_t found; /* Whether the attribute was found */
|
||||
} H5O_iter_ren_t;
|
||||
|
||||
/* User data for iteration when iterating over attributes */
|
||||
typedef struct {
|
||||
/* down */
|
||||
H5F_t *f; /* Pointer to file attribute is in */
|
||||
hid_t dxpl_id; /* DXPL for operation */
|
||||
hid_t loc_id; /* ID of object being iterated over */
|
||||
unsigned skip; /* # of attributes to skip over */
|
||||
H5A_operator_t op; /* Callback routine for each attribute */
|
||||
void *op_data; /* User data for callback */
|
||||
|
||||
/* up */
|
||||
unsigned count; /* Count of attributes examined */
|
||||
} H5O_iter_itr_t;
|
||||
|
||||
/* 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);
|
||||
static void *H5O_attr_copy(const void *_mesg, void *_dest);
|
||||
static size_t H5O_attr_size(const H5F_t *f, const void *_mesg);
|
||||
static herr_t H5O_attr_reset(void *_mesg);
|
||||
static herr_t H5O_attr_free(void *mesg);
|
||||
static herr_t H5O_attr_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link);
|
||||
static herr_t H5O_attr_link(H5F_t *f, hid_t dxpl_id, const void *_mesg);
|
||||
@ -86,7 +40,6 @@ static herr_t H5O_attr_pre_copy_file(H5F_t *file_src, const H5O_msg_class_t *typ
|
||||
static void *H5O_attr_copy_file(H5F_t *file_src, const H5O_msg_class_t *mesg_type,
|
||||
void *native_src, H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info,
|
||||
void *udata);
|
||||
static herr_t H5O_attr_get_share(const void *_mesg, H5O_shared_t *sh);
|
||||
static herr_t H5O_attr_set_share(void *_mesg, const H5O_shared_t *sh);
|
||||
static htri_t H5O_attr_is_shared(const void *_mesg);
|
||||
static herr_t H5O_attr_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg,
|
||||
@ -639,7 +592,7 @@ H5O_attr_size(const H5F_t *f, const void *_mesg)
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static herr_t
|
||||
herr_t
|
||||
H5O_attr_reset(void *_mesg)
|
||||
{
|
||||
H5A_t *attr = (H5A_t *)_mesg;
|
||||
@ -1098,7 +1051,7 @@ done:
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static herr_t
|
||||
herr_t
|
||||
H5O_attr_get_share(const void *_mesg, H5O_shared_t *sh /*out*/)
|
||||
{
|
||||
const H5A_t *mesg = (const H5A_t *)_mesg;
|
||||
@ -1271,620 +1224,3 @@ done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5O_attr_debug() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5O_msg_attr_to_dense_cb
|
||||
*
|
||||
* Purpose: Object header iterator callback routine to convert compact
|
||||
* attributes to dense attributes
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Quincey Koziol
|
||||
* koziol@hdfgroup.org
|
||||
* Dec 4 2006
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static herr_t
|
||||
H5A_attr_to_dense_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
|
||||
unsigned UNUSED sequence, unsigned *oh_flags_ptr, void *_udata/*in,out*/)
|
||||
{
|
||||
H5O_iter_cvt_t *udata = (H5O_iter_cvt_t *)_udata; /* Operator user data */
|
||||
herr_t ret_value = H5_ITER_CONT; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI_NOINIT(H5A_attr_to_dense_cb)
|
||||
|
||||
/* check args */
|
||||
HDassert(oh);
|
||||
HDassert(mesg);
|
||||
|
||||
/* Insert attribute into dense storage */
|
||||
if(H5A_dense_insert(udata->f, udata->dxpl_id, oh, mesg->flags, mesg->native) < 0)
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, H5_ITER_ERROR, "unable to add to dense storage")
|
||||
|
||||
/* Convert message into a null message */
|
||||
if(H5O_release_mesg(udata->f, udata->dxpl_id, oh, mesg, TRUE, FALSE) < 0)
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, H5_ITER_ERROR, "unable to convert into null message")
|
||||
|
||||
/* Indicate that the object header was modified */
|
||||
*oh_flags_ptr |= H5AC__DIRTIED_FLAG;
|
||||
|
||||
done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5A_attr_to_dense_cb() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5O_attr_create
|
||||
*
|
||||
* Purpose: Create a new attribute in the object header.
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Quincey Koziol
|
||||
* Friday, December 8, 2006
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5O_attr_create(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr)
|
||||
{
|
||||
H5O_t *oh = NULL; /* Pointer to actual object header */
|
||||
unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for object header */
|
||||
unsigned mesg_flags = 0; /* Flags for storing message */
|
||||
htri_t shared_mesg; /* Should this message be stored in the Shared Message table? */
|
||||
herr_t ret_value = SUCCEED; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_create)
|
||||
|
||||
/* Check arguments */
|
||||
HDassert(loc);
|
||||
HDassert(attr);
|
||||
|
||||
/* Should this message be written as a SOHM? */
|
||||
if((shared_mesg = H5SM_try_share(loc->file, dxpl_id, H5O_ATTR_ID, attr)) > 0)
|
||||
/* Mark the message as shared */
|
||||
mesg_flags |= H5O_MSG_FLAG_SHARED;
|
||||
else if(shared_mesg < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_WRITEERROR, FAIL, "error determining if message should be shared")
|
||||
|
||||
/* Protect the object header to iterate over */
|
||||
if(NULL == (oh = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, FAIL, "unable to load object header")
|
||||
|
||||
#ifdef QAK
|
||||
HDfprintf(stderr, "%s: adding attribute to new-style object header\n", FUNC);
|
||||
HDfprintf(stderr, "%s: oh->nattrs = %Hu\n", FUNC, oh->nattrs);
|
||||
HDfprintf(stderr, "%s: oh->max_compact = %u\n", FUNC, oh->max_compact);
|
||||
HDfprintf(stderr, "%s: oh->min_dense = %u\n", FUNC, oh->min_dense);
|
||||
#endif /* QAK */
|
||||
/* Check for switching to "dense" attribute storage */
|
||||
if(oh->version > H5O_VERSION_1 && oh->nattrs == oh->max_compact &&
|
||||
!H5F_addr_defined(oh->attr_fheap_addr)) {
|
||||
H5O_iter_cvt_t udata; /* User data for callback */
|
||||
H5O_mesg_operator_t op; /* Wrapper for operator */
|
||||
#ifdef QAK
|
||||
HDfprintf(stderr, "%s: converting attributes to dense storage\n", FUNC);
|
||||
#endif /* QAK */
|
||||
|
||||
/* Create dense storage for attributes */
|
||||
if(H5A_dense_create(loc->file, dxpl_id, oh) < 0)
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to create dense storage for attributes")
|
||||
|
||||
/* Set up user data for callback */
|
||||
udata.f = loc->file;
|
||||
udata.dxpl_id = dxpl_id;
|
||||
|
||||
/* Iterate over existing attributes, moving them to dense storage */
|
||||
op.lib_op = H5A_attr_to_dense_cb;
|
||||
if(H5O_msg_iterate_real(loc->file, oh, H5O_MSG_ATTR, TRUE, op, &udata, dxpl_id, &oh_flags) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTCONVERT, FAIL, "error converting attributes to dense storage")
|
||||
} /* end if */
|
||||
|
||||
/* Increment attribute count */
|
||||
oh->nattrs++;
|
||||
|
||||
/* Check for storing attribute with dense storage */
|
||||
if(H5F_addr_defined(oh->attr_fheap_addr)) {
|
||||
/* Insert attribute into dense storage */
|
||||
#ifdef QAK
|
||||
HDfprintf(stderr, "%s: inserting attribute to dense storage\n", FUNC);
|
||||
#endif /* QAK */
|
||||
if(H5A_dense_insert(loc->file, dxpl_id, oh, mesg_flags, attr) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to add to dense storage")
|
||||
} /* end if */
|
||||
else {
|
||||
/* Append new message to object header */
|
||||
if(H5O_msg_append_real(loc->file, dxpl_id, oh, H5O_MSG_ATTR, mesg_flags, 0, attr, &oh_flags) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to create new attribute in header")
|
||||
} /* end else */
|
||||
|
||||
/* Update the modification time, if any */
|
||||
if(H5O_touch_oh(loc->file, dxpl_id, oh, FALSE, &oh_flags) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update time on object")
|
||||
|
||||
done:
|
||||
if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0)
|
||||
HDONE_ERROR(H5E_ATTR, H5E_PROTECT, FAIL, "unable to release object header")
|
||||
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5O_attr_create */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5O_attr_write_cb
|
||||
*
|
||||
* Purpose: Object header iterator callback routine to update an
|
||||
* attribute stored compactly.
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Quincey Koziol
|
||||
* koziol@hdfgroup.org
|
||||
* Dec 4 2006
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static herr_t
|
||||
H5O_attr_write_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
|
||||
unsigned UNUSED sequence, unsigned *oh_flags_ptr, void *_udata/*in,out*/)
|
||||
{
|
||||
H5O_iter_wrt_t *udata = (H5O_iter_wrt_t *)_udata; /* Operator user data */
|
||||
herr_t ret_value = H5_ITER_CONT; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_write_cb)
|
||||
|
||||
/* check args */
|
||||
HDassert(oh);
|
||||
HDassert(mesg);
|
||||
HDassert(!udata->found);
|
||||
|
||||
/* Check for shared message */
|
||||
if(mesg->flags & H5O_MSG_FLAG_SHARED) {
|
||||
H5A_t shared_attr; /* Copy of shared attribute */
|
||||
|
||||
/*
|
||||
* If the message is shared then then the native pointer points to an
|
||||
* H5O_MSG_SHARED message. We use that information to look up the real
|
||||
* message in the global heap or some other object header.
|
||||
*/
|
||||
if(NULL == H5O_shared_read(udata->f, udata->dxpl_id, mesg->native, H5O_MSG_ATTR, &shared_attr))
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, H5_ITER_ERROR, "unable to read shared attribute")
|
||||
|
||||
/* Check for correct attribute message to modify */
|
||||
if(HDstrcmp(shared_attr.name, udata->attr->name) == 0) {
|
||||
htri_t shared_mesg; /* Whether the message should be shared */
|
||||
|
||||
/* Store new version of message as a SOHM */
|
||||
/* (should always work, since we're not changing the size of the attribute) */
|
||||
if((shared_mesg = H5SM_try_share(udata->f, udata->dxpl_id, H5O_ATTR_ID, udata->attr)) == 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_BADMESG, H5_ITER_ERROR, "attribute changed sharing status")
|
||||
else if(shared_mesg < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_BADMESG, H5_ITER_ERROR, "can't share attribute")
|
||||
|
||||
/* Remove the old attribut from the SOHM index */
|
||||
if(H5SM_try_delete(udata->f, udata->dxpl_id, H5O_ATTR_ID, mesg->native) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, H5_ITER_ERROR, "unable to delete shared attribute in shared storage")
|
||||
|
||||
/* Extract shared message info from current attribute */
|
||||
if(H5O_attr_get_share(udata->attr, mesg->native) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_BADMESG, H5_ITER_ERROR, "can't get shared info")
|
||||
|
||||
/* Indicate that we found the correct attribute */
|
||||
udata->found = TRUE;
|
||||
} /* end if */
|
||||
|
||||
/* Release copy of shared attribute */
|
||||
H5O_attr_reset(&shared_attr);
|
||||
} /* end if */
|
||||
else {
|
||||
/* Check for correct attribute message to modify */
|
||||
if(HDstrcmp(((H5A_t *)mesg->native)->name, udata->attr->name) == 0) {
|
||||
/* Allocate storage for the message's data, if necessary */
|
||||
if(((H5A_t *)mesg->native)->data == NULL)
|
||||
if(NULL == (((H5A_t *)mesg->native)->data = H5FL_BLK_MALLOC(attr_buf, udata->attr->data_size)))
|
||||
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5_ITER_ERROR, "memory allocation failed")
|
||||
|
||||
/* Copy the data */
|
||||
HDmemcpy(((H5A_t *)mesg->native)->data, udata->attr->data, udata->attr->data_size);
|
||||
|
||||
/* Indicate that we found the correct attribute */
|
||||
udata->found = TRUE;
|
||||
} /* end if */
|
||||
} /* end else */
|
||||
|
||||
/* Set common info, if we found the correct attribute */
|
||||
if(udata->found) {
|
||||
/* Mark message as dirty */
|
||||
mesg->dirty = TRUE;
|
||||
|
||||
/* Stop iterating */
|
||||
ret_value = H5_ITER_STOP;
|
||||
|
||||
/* Indicate that the object header was modified */
|
||||
*oh_flags_ptr |= H5AC__DIRTIED_FLAG;
|
||||
} /* end if */
|
||||
|
||||
done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5O_attr_write_cb() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5O_attr_write
|
||||
*
|
||||
* Purpose: Write a new value to an attribute.
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Quincey Koziol
|
||||
* Monday, December 4, 2006
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5O_attr_write(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr)
|
||||
{
|
||||
H5O_t *oh = NULL; /* Pointer to actual object header */
|
||||
unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for object header */
|
||||
herr_t ret_value = SUCCEED; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_write)
|
||||
|
||||
/* Check arguments */
|
||||
HDassert(loc);
|
||||
HDassert(attr);
|
||||
|
||||
/* Protect the object header to iterate over */
|
||||
if(NULL == (oh = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, FAIL, "unable to load object header")
|
||||
|
||||
/* Check for attributes stored densely */
|
||||
if(H5F_addr_defined(oh->attr_fheap_addr)) {
|
||||
/* Modify the attribute data in dense storage */
|
||||
if(H5A_dense_write(loc->file, dxpl_id, oh, attr) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "error updating attribute")
|
||||
} /* end if */
|
||||
else {
|
||||
H5O_iter_wrt_t udata; /* User data for callback */
|
||||
H5O_mesg_operator_t op; /* Wrapper for operator */
|
||||
|
||||
/* Set up user data for callback */
|
||||
udata.f = loc->file;
|
||||
udata.dxpl_id = dxpl_id;
|
||||
udata.attr = attr;
|
||||
udata.found = FALSE;
|
||||
|
||||
/* Iterate over attributes, to locate correct one to update */
|
||||
op.lib_op = H5O_attr_write_cb;
|
||||
if(H5O_msg_iterate_real(loc->file, oh, H5O_MSG_ATTR, TRUE, op, &udata, dxpl_id, &oh_flags) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "error updating attribute")
|
||||
|
||||
/* Check that we found the attribute */
|
||||
if(!udata.found)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "can't locate open attribute?")
|
||||
} /* end else */
|
||||
|
||||
/* Update the modification time, if any */
|
||||
if(H5O_touch_oh(loc->file, dxpl_id, oh, FALSE, &oh_flags) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update time on object")
|
||||
|
||||
done:
|
||||
if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0)
|
||||
HDONE_ERROR(H5E_ATTR, H5E_PROTECT, FAIL, "unable to release object header")
|
||||
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5O_attr_write */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5O_attr_rename_dup_cb
|
||||
*
|
||||
* Purpose: Object header iterator callback routine to check for
|
||||
* duplicate name during rename
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Quincey Koziol
|
||||
* koziol@hdfgroup.org
|
||||
* Dec 5 2006
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static herr_t
|
||||
H5O_attr_rename_dup_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
|
||||
unsigned UNUSED sequence, unsigned UNUSED *oh_flags_ptr, void *_udata/*in,out*/)
|
||||
{
|
||||
H5O_iter_ren_t *udata = (H5O_iter_ren_t *)_udata; /* Operator user data */
|
||||
herr_t ret_value = H5_ITER_CONT; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_rename_dup_cb)
|
||||
|
||||
/* check args */
|
||||
HDassert(oh);
|
||||
HDassert(mesg);
|
||||
HDassert(!udata->found);
|
||||
|
||||
/* Check for shared message */
|
||||
if(mesg->flags & H5O_MSG_FLAG_SHARED) {
|
||||
H5A_t shared_attr; /* Copy of shared attribute */
|
||||
|
||||
/*
|
||||
* If the message is shared then then the native pointer points to an
|
||||
* H5O_MSG_SHARED message. We use that information to look up the real
|
||||
* message in the global heap or some other object header.
|
||||
*/
|
||||
if(NULL == H5O_shared_read(udata->f, udata->dxpl_id, mesg->native, H5O_MSG_ATTR, &shared_attr))
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, H5_ITER_ERROR, "unable to read shared attribute")
|
||||
|
||||
/* Check for existing attribute with new name */
|
||||
if(HDstrcmp(shared_attr.name, udata->new_name) == 0) {
|
||||
/* Indicate that we found an existing attribute with the new name*/
|
||||
udata->found = TRUE;
|
||||
|
||||
/* Stop iterating */
|
||||
ret_value = H5_ITER_STOP;
|
||||
} /* end if */
|
||||
|
||||
/* Release copy of shared attribute */
|
||||
H5O_attr_reset(&shared_attr);
|
||||
} /* end if */
|
||||
else {
|
||||
/* Check for existing attribute with new name */
|
||||
if(HDstrcmp(((H5A_t *)mesg->native)->name, udata->new_name) == 0) {
|
||||
/* Indicate that we found an existing attribute with the new name*/
|
||||
udata->found = TRUE;
|
||||
|
||||
/* Stop iterating */
|
||||
ret_value = H5_ITER_STOP;
|
||||
} /* end if */
|
||||
} /* end else */
|
||||
|
||||
done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5O_attr_rename_dup_cb() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5O_attr_rename_mod_cb
|
||||
*
|
||||
* Purpose: Object header iterator callback routine to change name of
|
||||
* attribute during rename
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Quincey Koziol
|
||||
* koziol@hdfgroup.org
|
||||
* Dec 5 2006
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static herr_t
|
||||
H5O_attr_rename_mod_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
|
||||
unsigned UNUSED sequence, unsigned *oh_flags_ptr, void *_udata/*in,out*/)
|
||||
{
|
||||
H5O_iter_ren_t *udata = (H5O_iter_ren_t *)_udata; /* Operator user data */
|
||||
herr_t ret_value = H5_ITER_CONT; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_rename_mod_cb)
|
||||
|
||||
/* check args */
|
||||
HDassert(oh);
|
||||
HDassert(mesg);
|
||||
HDassert(!udata->found);
|
||||
|
||||
/* Check for shared message */
|
||||
if(mesg->flags & H5O_MSG_FLAG_SHARED) {
|
||||
H5A_t shared_attr; /* Copy of shared attribute */
|
||||
|
||||
/*
|
||||
* If the message is shared then then the native pointer points to an
|
||||
* H5O_MSG_SHARED message. We use that information to look up the real
|
||||
* message in the global heap or some other object header.
|
||||
*/
|
||||
if(NULL == H5O_shared_read(udata->f, udata->dxpl_id, mesg->native, H5O_MSG_ATTR, &shared_attr))
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, H5_ITER_ERROR, "unable to read shared attribute")
|
||||
|
||||
/* Check for correct attribute message to modify */
|
||||
if(HDstrcmp(shared_attr.name, udata->old_name) == 0) {
|
||||
/* XXX: fix me */
|
||||
HDfprintf(stderr, "%s: renaming a shared attribute not supported yet!\n", FUNC);
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, H5_ITER_ERROR, "renaming a shared attribute not supported yet")
|
||||
} /* end if */
|
||||
|
||||
/* Release copy of shared attribute */
|
||||
H5O_attr_reset(&shared_attr);
|
||||
} /* end if */
|
||||
else {
|
||||
/* Find correct attribute message to rename */
|
||||
if(HDstrcmp(((H5A_t *)mesg->native)->name, udata->old_name) == 0) {
|
||||
/* Change the name for the attribute */
|
||||
H5MM_xfree(((H5A_t *)mesg->native)->name);
|
||||
((H5A_t *)mesg->native)->name = H5MM_xstrdup(udata->new_name);
|
||||
|
||||
/* Indicate that we found an existing attribute with the old name*/
|
||||
udata->found = TRUE;
|
||||
|
||||
/* Mark message as dirty */
|
||||
mesg->dirty = TRUE;
|
||||
|
||||
/* Stop iterating */
|
||||
ret_value = H5_ITER_STOP;
|
||||
|
||||
/* Indicate that the object header was modified */
|
||||
*oh_flags_ptr |= H5AC__DIRTIED_FLAG;
|
||||
} /* end if */
|
||||
} /* end else */
|
||||
|
||||
done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5O_attr_rename_mod_cb() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5O_attr_rename
|
||||
*
|
||||
* Purpose: Rename an attribute.
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Quincey Koziol
|
||||
* Tuesday, December 5, 2006
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5O_attr_rename(const H5O_loc_t *loc, hid_t dxpl_id, const char *old_name, const char *new_name)
|
||||
{
|
||||
H5O_t *oh = NULL; /* Pointer to actual object header */
|
||||
unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for object header */
|
||||
herr_t ret_value = SUCCEED; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_rename)
|
||||
|
||||
/* Check arguments */
|
||||
HDassert(loc);
|
||||
HDassert(old_name);
|
||||
HDassert(new_name);
|
||||
|
||||
/* Protect the object header to iterate over */
|
||||
if(NULL == (oh = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, FAIL, "unable to load object header")
|
||||
|
||||
/* Check for attributes stored densely */
|
||||
if(H5F_addr_defined(oh->attr_fheap_addr)) {
|
||||
/* XXX: fix me */
|
||||
HDfprintf(stderr, "%s: renaming attributes in dense storage not supported yet!\n", FUNC);
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "renaming attributes in dense storage not supported yet")
|
||||
} /* end if */
|
||||
else {
|
||||
H5O_iter_ren_t udata; /* User data for callback */
|
||||
H5O_mesg_operator_t op; /* Wrapper for operator */
|
||||
|
||||
/* Set up user data for callback */
|
||||
udata.f = loc->file;
|
||||
udata.dxpl_id = dxpl_id;
|
||||
udata.old_name = old_name;
|
||||
udata.new_name = new_name;
|
||||
udata.found = FALSE;
|
||||
|
||||
/* Iterate over attributes, to check if "new name" exists already */
|
||||
op.lib_op = H5O_attr_rename_dup_cb;
|
||||
if(H5O_msg_iterate_real(loc->file, oh, H5O_MSG_ATTR, TRUE, op, &udata, dxpl_id, &oh_flags) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "error updating attribute")
|
||||
|
||||
/* If the new name was found, indicate an error */
|
||||
if(udata.found)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_EXISTS, FAIL, "attribute with new name already exists")
|
||||
|
||||
/* Iterate over attributes again, to actually rename attribute with old name */
|
||||
op.lib_op = H5O_attr_rename_mod_cb;
|
||||
if(H5O_msg_iterate_real(loc->file, oh, H5O_MSG_ATTR, TRUE, op, &udata, dxpl_id, &oh_flags) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "error updating attribute")
|
||||
} /* end else */
|
||||
|
||||
/* Update the modification time, if any */
|
||||
if(H5O_touch_oh(loc->file, dxpl_id, oh, FALSE, &oh_flags) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update time on object")
|
||||
|
||||
done:
|
||||
if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0)
|
||||
HDONE_ERROR(H5E_ATTR, H5E_PROTECT, FAIL, "unable to release object header")
|
||||
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5O_attr_rename */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5O_attr_iterate
|
||||
*
|
||||
* Purpose: Iterate over attributes for an object.
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Quincey Koziol
|
||||
* Tuesday, December 5, 2006
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5O_attr_iterate(hid_t loc_id, const H5O_loc_t *loc, hid_t dxpl_id,
|
||||
unsigned skip, unsigned *last_attr, H5A_operator_t op, void *op_data)
|
||||
{
|
||||
H5O_t *oh = NULL; /* Pointer to actual object header */
|
||||
haddr_t attr_fheap_addr; /* Address of fractal heap for dense attribute storage */
|
||||
haddr_t name_bt2_addr; /* Address of v2 B-tree for name index on dense attribute storage */
|
||||
herr_t ret_value = SUCCEED; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_iterate)
|
||||
|
||||
/* Check arguments */
|
||||
HDassert(loc);
|
||||
HDassert(op);
|
||||
|
||||
/* Protect the object header to iterate over */
|
||||
if(NULL == (oh = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, FAIL, "unable to load object header")
|
||||
|
||||
/* Retrieve the information about dense attribute storage */
|
||||
if(oh->version > H5O_VERSION_1 && H5F_addr_defined(oh->attr_fheap_addr)) {
|
||||
attr_fheap_addr = oh->attr_fheap_addr;
|
||||
name_bt2_addr = oh->name_bt2_addr;
|
||||
} /* end if */
|
||||
else
|
||||
attr_fheap_addr = name_bt2_addr = HADDR_UNDEF;
|
||||
|
||||
/* Release the object header */
|
||||
if(H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
|
||||
HDONE_ERROR(H5E_ATTR, H5E_PROTECT, FAIL, "unable to release object header")
|
||||
oh = NULL;
|
||||
|
||||
/* Check for attributes stored densely */
|
||||
if(H5F_addr_defined(attr_fheap_addr)) {
|
||||
if((ret_value = H5A_dense_iterate(loc->file, dxpl_id, loc_id, attr_fheap_addr,
|
||||
name_bt2_addr, skip, last_attr, op, op_data)) < 0)
|
||||
HERROR(H5E_ATTR, H5E_BADITER, "error iterating over attributes");
|
||||
} /* end if */
|
||||
else {
|
||||
unsigned idx; /* Current attribute to operate on */
|
||||
|
||||
/* Check for skipping over too many attributes */
|
||||
if((int)skip < H5O_msg_count(loc, H5O_ATTR_ID, dxpl_id)) {
|
||||
H5A_t found_attr; /* Copy of attribute for callback */
|
||||
|
||||
/* Read each attribute and call application's callback */
|
||||
/* (this could be made more efficient by iterating over the
|
||||
* attribute header messages with H5O_msg_iterate, but then
|
||||
* the object header would be locked during the callback into
|
||||
* the application code, causing problems if they attempt to
|
||||
* do anything with the object the attribute is on - QAK)
|
||||
*/
|
||||
idx = skip;
|
||||
while(H5O_msg_read(loc, H5O_ATTR_ID, (int)idx, &found_attr, dxpl_id) != NULL) {
|
||||
/* Call application's callback */
|
||||
idx++;
|
||||
if((ret_value = (op)(loc_id, found_attr.name, op_data)) != 0) {
|
||||
H5A_free(&found_attr);
|
||||
break;
|
||||
} /* end if */
|
||||
H5A_free(&found_attr);
|
||||
} /* end while */
|
||||
|
||||
/* Clear error stack from running off end of attributes */
|
||||
if(ret_value == 0)
|
||||
H5E_clear_stack(NULL);
|
||||
} /* end if */
|
||||
else
|
||||
if(skip > 0)
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified")
|
||||
|
||||
/* Update last attribute looked at */
|
||||
if(last_attr)
|
||||
*last_attr = idx;
|
||||
} /* end else */
|
||||
|
||||
done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5O_attr_iterate */
|
||||
|
||||
|
892
src/H5Oattribute.c
Normal file
892
src/H5Oattribute.c
Normal file
@ -0,0 +1,892 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* 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: H5Oattribute.c
|
||||
* Dec 11 2006
|
||||
* Quincey Koziol <koziol@hdfgroup.org>
|
||||
*
|
||||
* Purpose: Object header attribute routines.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/****************/
|
||||
/* Module Setup */
|
||||
/****************/
|
||||
|
||||
#define H5A_PACKAGE /*suppress error about including H5Apkg */
|
||||
#define H5O_PACKAGE /*suppress error about including H5Opkg */
|
||||
|
||||
/***********/
|
||||
/* Headers */
|
||||
/***********/
|
||||
#include "H5private.h" /* Generic Functions */
|
||||
#include "H5Apkg.h" /* Attributes */
|
||||
#include "H5Eprivate.h" /* Error handling */
|
||||
#include "H5MMprivate.h" /* Memory management */
|
||||
#include "H5Opkg.h" /* Object headers */
|
||||
#include "H5SMprivate.h" /* Shared Object Header Messages */
|
||||
|
||||
|
||||
/****************/
|
||||
/* Local Macros */
|
||||
/****************/
|
||||
|
||||
|
||||
/******************/
|
||||
/* Local Typedefs */
|
||||
/******************/
|
||||
|
||||
/* User data for iteration when converting attributes to dense storage */
|
||||
typedef struct {
|
||||
H5F_t *f; /* Pointer to file for insertion */
|
||||
hid_t dxpl_id; /* DXPL during iteration */
|
||||
} H5O_iter_cvt_t;
|
||||
|
||||
/* User data for iteration when opening an attribute */
|
||||
typedef struct {
|
||||
/* down */
|
||||
H5F_t *f; /* Pointer to file attribute is in */
|
||||
hid_t dxpl_id; /* DXPL for operation */
|
||||
const char *name; /* Name of attribute to open */
|
||||
|
||||
/* up */
|
||||
H5A_t *attr; /* Attribute data to update object header with */
|
||||
} H5O_iter_opn_t;
|
||||
|
||||
/* User data for iteration when updating an attribute */
|
||||
typedef struct {
|
||||
/* down */
|
||||
H5F_t *f; /* Pointer to file attribute is in */
|
||||
hid_t dxpl_id; /* DXPL for operation */
|
||||
H5A_t *attr; /* Attribute data to update object header with */
|
||||
|
||||
/* up */
|
||||
hbool_t found; /* Whether the attribute was found */
|
||||
} H5O_iter_wrt_t;
|
||||
|
||||
/* User data for iteration when renaming an attribute */
|
||||
typedef struct {
|
||||
/* down */
|
||||
H5F_t *f; /* Pointer to file attribute is in */
|
||||
hid_t dxpl_id; /* DXPL for operation */
|
||||
const char *old_name; /* Old name of attribute */
|
||||
const char *new_name; /* New name of attribute */
|
||||
|
||||
/* up */
|
||||
hbool_t found; /* Whether the attribute was found */
|
||||
} H5O_iter_ren_t;
|
||||
|
||||
/* User data for iteration when iterating over attributes */
|
||||
typedef struct {
|
||||
/* down */
|
||||
H5F_t *f; /* Pointer to file attribute is in */
|
||||
hid_t dxpl_id; /* DXPL for operation */
|
||||
hid_t loc_id; /* ID of object being iterated over */
|
||||
unsigned skip; /* # of attributes to skip over */
|
||||
H5A_operator_t op; /* Callback routine for each attribute */
|
||||
void *op_data; /* User data for callback */
|
||||
|
||||
/* up */
|
||||
unsigned count; /* Count of attributes examined */
|
||||
} H5O_iter_itr_t;
|
||||
|
||||
|
||||
/********************/
|
||||
/* Package Typedefs */
|
||||
/********************/
|
||||
|
||||
|
||||
/********************/
|
||||
/* Local Prototypes */
|
||||
/********************/
|
||||
|
||||
|
||||
/*********************/
|
||||
/* Package Variables */
|
||||
/*********************/
|
||||
|
||||
|
||||
/*****************************/
|
||||
/* Library Private Variables */
|
||||
/*****************************/
|
||||
|
||||
|
||||
/*******************/
|
||||
/* Local Variables */
|
||||
/*******************/
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5O_msg_attr_to_dense_cb
|
||||
*
|
||||
* Purpose: Object header iterator callback routine to convert compact
|
||||
* attributes to dense attributes
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Quincey Koziol
|
||||
* koziol@hdfgroup.org
|
||||
* Dec 4 2006
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static herr_t
|
||||
H5A_attr_to_dense_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
|
||||
unsigned UNUSED sequence, unsigned *oh_flags_ptr, void *_udata/*in,out*/)
|
||||
{
|
||||
H5O_iter_cvt_t *udata = (H5O_iter_cvt_t *)_udata; /* Operator user data */
|
||||
herr_t ret_value = H5_ITER_CONT; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI_NOINIT(H5A_attr_to_dense_cb)
|
||||
|
||||
/* check args */
|
||||
HDassert(oh);
|
||||
HDassert(mesg);
|
||||
|
||||
/* Insert attribute into dense storage */
|
||||
if(H5A_dense_insert(udata->f, udata->dxpl_id, oh, mesg->flags, mesg->native) < 0)
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, H5_ITER_ERROR, "unable to add to dense storage")
|
||||
|
||||
/* Convert message into a null message */
|
||||
if(H5O_release_mesg(udata->f, udata->dxpl_id, oh, mesg, TRUE, FALSE) < 0)
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, H5_ITER_ERROR, "unable to convert into null message")
|
||||
|
||||
/* Indicate that the object header was modified */
|
||||
*oh_flags_ptr |= H5AC__DIRTIED_FLAG;
|
||||
|
||||
done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5A_attr_to_dense_cb() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5O_attr_create
|
||||
*
|
||||
* Purpose: Create a new attribute in the object header.
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Quincey Koziol
|
||||
* Friday, December 8, 2006
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5O_attr_create(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr)
|
||||
{
|
||||
H5O_t *oh = NULL; /* Pointer to actual object header */
|
||||
unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for object header */
|
||||
unsigned mesg_flags = 0; /* Flags for storing message */
|
||||
htri_t shared_mesg; /* Should this message be stored in the Shared Message table? */
|
||||
herr_t ret_value = SUCCEED; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_create)
|
||||
|
||||
/* Check arguments */
|
||||
HDassert(loc);
|
||||
HDassert(attr);
|
||||
|
||||
/* Should this message be written as a SOHM? */
|
||||
if((shared_mesg = H5SM_try_share(loc->file, dxpl_id, H5O_ATTR_ID, attr)) > 0)
|
||||
/* Mark the message as shared */
|
||||
mesg_flags |= H5O_MSG_FLAG_SHARED;
|
||||
else if(shared_mesg < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_WRITEERROR, FAIL, "error determining if message should be shared")
|
||||
|
||||
/* Protect the object header to iterate over */
|
||||
if(NULL == (oh = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, FAIL, "unable to load object header")
|
||||
|
||||
#ifdef QAK
|
||||
HDfprintf(stderr, "%s: adding attribute to new-style object header\n", FUNC);
|
||||
HDfprintf(stderr, "%s: oh->nattrs = %Hu\n", FUNC, oh->nattrs);
|
||||
HDfprintf(stderr, "%s: oh->max_compact = %u\n", FUNC, oh->max_compact);
|
||||
HDfprintf(stderr, "%s: oh->min_dense = %u\n", FUNC, oh->min_dense);
|
||||
#endif /* QAK */
|
||||
/* Check for switching to "dense" attribute storage */
|
||||
if(oh->version > H5O_VERSION_1 && oh->nattrs == oh->max_compact &&
|
||||
!H5F_addr_defined(oh->attr_fheap_addr)) {
|
||||
H5O_iter_cvt_t udata; /* User data for callback */
|
||||
H5O_mesg_operator_t op; /* Wrapper for operator */
|
||||
#ifdef QAK
|
||||
HDfprintf(stderr, "%s: converting attributes to dense storage\n", FUNC);
|
||||
#endif /* QAK */
|
||||
|
||||
/* Create dense storage for attributes */
|
||||
if(H5A_dense_create(loc->file, dxpl_id, oh) < 0)
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to create dense storage for attributes")
|
||||
|
||||
/* Set up user data for callback */
|
||||
udata.f = loc->file;
|
||||
udata.dxpl_id = dxpl_id;
|
||||
|
||||
/* Iterate over existing attributes, moving them to dense storage */
|
||||
op.lib_op = H5A_attr_to_dense_cb;
|
||||
if(H5O_msg_iterate_real(loc->file, oh, H5O_MSG_ATTR, TRUE, op, &udata, dxpl_id, &oh_flags) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTCONVERT, FAIL, "error converting attributes to dense storage")
|
||||
} /* end if */
|
||||
|
||||
/* Increment attribute count */
|
||||
oh->nattrs++;
|
||||
|
||||
/* Check for storing attribute with dense storage */
|
||||
if(H5F_addr_defined(oh->attr_fheap_addr)) {
|
||||
/* Insert attribute into dense storage */
|
||||
#ifdef QAK
|
||||
HDfprintf(stderr, "%s: inserting attribute to dense storage\n", FUNC);
|
||||
#endif /* QAK */
|
||||
if(H5A_dense_insert(loc->file, dxpl_id, oh, mesg_flags, attr) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to add to dense storage")
|
||||
} /* end if */
|
||||
else {
|
||||
/* Append new message to object header */
|
||||
if(H5O_msg_append_real(loc->file, dxpl_id, oh, H5O_MSG_ATTR, mesg_flags, 0, attr, &oh_flags) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to create new attribute in header")
|
||||
} /* end else */
|
||||
|
||||
/* Update the modification time, if any */
|
||||
if(H5O_touch_oh(loc->file, dxpl_id, oh, FALSE, &oh_flags) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update time on object")
|
||||
|
||||
done:
|
||||
if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0)
|
||||
HDONE_ERROR(H5E_ATTR, H5E_PROTECT, FAIL, "unable to release object header")
|
||||
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5O_attr_create */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5O_attr_open_cb
|
||||
*
|
||||
* Purpose: Object header iterator callback routine to open an
|
||||
* attribute stored compactly.
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Quincey Koziol
|
||||
* koziol@hdfgroup.org
|
||||
* Dec 11 2006
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static herr_t
|
||||
H5O_attr_open_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
|
||||
unsigned UNUSED sequence, unsigned UNUSED *oh_flags_ptr, void *_udata/*in,out*/)
|
||||
{
|
||||
H5O_iter_opn_t *udata = (H5O_iter_opn_t *)_udata; /* Operator user data */
|
||||
herr_t ret_value = H5_ITER_CONT; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_open_cb)
|
||||
|
||||
/* check args */
|
||||
HDassert(oh);
|
||||
HDassert(mesg);
|
||||
HDassert(!udata->attr);
|
||||
|
||||
/* Check for shared message */
|
||||
if(mesg->flags & H5O_MSG_FLAG_SHARED) {
|
||||
H5A_t shared_attr; /* Copy of shared attribute */
|
||||
|
||||
/*
|
||||
* If the message is shared then then the native pointer points to an
|
||||
* H5O_MSG_SHARED message. We use that information to look up the real
|
||||
* message in the global heap or some other object header.
|
||||
*/
|
||||
if(NULL == H5O_shared_read(udata->f, udata->dxpl_id, mesg->native, H5O_MSG_ATTR, &shared_attr))
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, H5_ITER_ERROR, "unable to read shared attribute")
|
||||
|
||||
/* Check for correct attribute message to modify */
|
||||
if(HDstrcmp(shared_attr.name, udata->name) == 0) {
|
||||
/* Make a copy of the attribute to return */
|
||||
if(NULL == (udata->attr = H5A_copy(NULL, &shared_attr)))
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "unable to copy attribute")
|
||||
} /* end if */
|
||||
|
||||
/* Release copy of shared attribute */
|
||||
H5O_attr_reset(&shared_attr);
|
||||
} /* end if */
|
||||
else {
|
||||
/* Check for correct attribute message to modify */
|
||||
if(HDstrcmp(((H5A_t *)mesg->native)->name, udata->name) == 0) {
|
||||
/* Make a copy of the attribute to return */
|
||||
if(NULL == (udata->attr = H5A_copy(NULL, (H5A_t *)mesg->native)))
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "unable to copy attribute")
|
||||
} /* end if */
|
||||
} /* end else */
|
||||
|
||||
/* Set common info, if we found the correct attribute */
|
||||
if(udata->attr) {
|
||||
/* Stop iterating */
|
||||
ret_value = H5_ITER_STOP;
|
||||
} /* end if */
|
||||
|
||||
done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5O_attr_open_cb() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5O_attr_open
|
||||
*
|
||||
* Purpose: Open an existing attribute in an object header.
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Quincey Koziol
|
||||
* Monday, December 11, 2006
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
H5A_t *
|
||||
H5O_attr_open(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
|
||||
{
|
||||
H5O_t *oh = NULL; /* Pointer to actual object header */
|
||||
unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for object header */
|
||||
H5A_t *ret_value; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_open)
|
||||
|
||||
/* Check arguments */
|
||||
HDassert(loc);
|
||||
HDassert(name);
|
||||
|
||||
/* Protect the object header to iterate over */
|
||||
if(NULL == (oh = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, NULL, "unable to load object header")
|
||||
|
||||
#ifdef QAK
|
||||
HDfprintf(stderr, "%s: opening attribute to new-style object header\n", FUNC);
|
||||
HDfprintf(stderr, "%s: oh->nattrs = %Hu\n", FUNC, oh->nattrs);
|
||||
HDfprintf(stderr, "%s: oh->max_compact = %u\n", FUNC, oh->max_compact);
|
||||
HDfprintf(stderr, "%s: oh->min_dense = %u\n", FUNC, oh->min_dense);
|
||||
#endif /* QAK */
|
||||
/* Check for opening attribute with dense storage */
|
||||
if(H5F_addr_defined(oh->attr_fheap_addr)) {
|
||||
/* Open attribute in dense storage */
|
||||
if(NULL == (ret_value = H5A_dense_open(loc->file, dxpl_id, oh, name)))
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "can't open attribute")
|
||||
} /* end if */
|
||||
else {
|
||||
H5O_iter_opn_t udata; /* User data for callback */
|
||||
H5O_mesg_operator_t op; /* Wrapper for operator */
|
||||
|
||||
/* Set up user data for callback */
|
||||
udata.f = loc->file;
|
||||
udata.dxpl_id = dxpl_id;
|
||||
udata.name = name;
|
||||
udata.attr = NULL;
|
||||
|
||||
/* Iterate over attributes, to locate correct one to update */
|
||||
op.lib_op = H5O_attr_open_cb;
|
||||
if(H5O_msg_iterate_real(loc->file, oh, H5O_MSG_ATTR, TRUE, op, &udata, dxpl_id, &oh_flags) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, NULL, "error updating attribute")
|
||||
|
||||
/* Check that we found the attribute */
|
||||
if(!udata.attr)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "can't locate attribute")
|
||||
|
||||
/* Get attribute opened from object header */
|
||||
HDassert(udata.attr);
|
||||
ret_value = udata.attr;
|
||||
} /* end else */
|
||||
|
||||
done:
|
||||
if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0)
|
||||
HDONE_ERROR(H5E_ATTR, H5E_PROTECT, NULL, "unable to release object header")
|
||||
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5O_attr_open */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5O_attr_write_cb
|
||||
*
|
||||
* Purpose: Object header iterator callback routine to update an
|
||||
* attribute stored compactly.
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Quincey Koziol
|
||||
* koziol@hdfgroup.org
|
||||
* Dec 4 2006
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static herr_t
|
||||
H5O_attr_write_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
|
||||
unsigned UNUSED sequence, unsigned *oh_flags_ptr, void *_udata/*in,out*/)
|
||||
{
|
||||
H5O_iter_wrt_t *udata = (H5O_iter_wrt_t *)_udata; /* Operator user data */
|
||||
herr_t ret_value = H5_ITER_CONT; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_write_cb)
|
||||
|
||||
/* check args */
|
||||
HDassert(oh);
|
||||
HDassert(mesg);
|
||||
HDassert(!udata->found);
|
||||
|
||||
/* Check for shared message */
|
||||
if(mesg->flags & H5O_MSG_FLAG_SHARED) {
|
||||
H5A_t shared_attr; /* Copy of shared attribute */
|
||||
|
||||
/*
|
||||
* If the message is shared then then the native pointer points to an
|
||||
* H5O_MSG_SHARED message. We use that information to look up the real
|
||||
* message in the global heap or some other object header.
|
||||
*/
|
||||
if(NULL == H5O_shared_read(udata->f, udata->dxpl_id, mesg->native, H5O_MSG_ATTR, &shared_attr))
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, H5_ITER_ERROR, "unable to read shared attribute")
|
||||
|
||||
/* Check for correct attribute message to modify */
|
||||
if(HDstrcmp(shared_attr.name, udata->attr->name) == 0) {
|
||||
htri_t shared_mesg; /* Whether the message should be shared */
|
||||
|
||||
/* Store new version of message as a SOHM */
|
||||
/* (should always work, since we're not changing the size of the attribute) */
|
||||
if((shared_mesg = H5SM_try_share(udata->f, udata->dxpl_id, H5O_ATTR_ID, udata->attr)) == 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_BADMESG, H5_ITER_ERROR, "attribute changed sharing status")
|
||||
else if(shared_mesg < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_BADMESG, H5_ITER_ERROR, "can't share attribute")
|
||||
|
||||
/* Remove the old attribut from the SOHM index */
|
||||
if(H5SM_try_delete(udata->f, udata->dxpl_id, H5O_ATTR_ID, mesg->native) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, H5_ITER_ERROR, "unable to delete shared attribute in shared storage")
|
||||
|
||||
/* Extract shared message info from current attribute */
|
||||
if(H5O_attr_get_share(udata->attr, mesg->native) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_BADMESG, H5_ITER_ERROR, "can't get shared info")
|
||||
|
||||
/* Indicate that we found the correct attribute */
|
||||
udata->found = TRUE;
|
||||
} /* end if */
|
||||
|
||||
/* Release copy of shared attribute */
|
||||
H5O_attr_reset(&shared_attr);
|
||||
} /* end if */
|
||||
else {
|
||||
/* Check for correct attribute message to modify */
|
||||
if(HDstrcmp(((H5A_t *)mesg->native)->name, udata->attr->name) == 0) {
|
||||
/* Allocate storage for the message's data, if necessary */
|
||||
if(((H5A_t *)mesg->native)->data == NULL)
|
||||
if(NULL == (((H5A_t *)mesg->native)->data = H5FL_BLK_MALLOC(attr_buf, udata->attr->data_size)))
|
||||
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5_ITER_ERROR, "memory allocation failed")
|
||||
|
||||
/* Copy the data */
|
||||
HDmemcpy(((H5A_t *)mesg->native)->data, udata->attr->data, udata->attr->data_size);
|
||||
|
||||
/* Indicate that we found the correct attribute */
|
||||
udata->found = TRUE;
|
||||
} /* end if */
|
||||
} /* end else */
|
||||
|
||||
/* Set common info, if we found the correct attribute */
|
||||
if(udata->found) {
|
||||
/* Mark message as dirty */
|
||||
mesg->dirty = TRUE;
|
||||
|
||||
/* Stop iterating */
|
||||
ret_value = H5_ITER_STOP;
|
||||
|
||||
/* Indicate that the object header was modified */
|
||||
*oh_flags_ptr |= H5AC__DIRTIED_FLAG;
|
||||
} /* end if */
|
||||
|
||||
done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5O_attr_write_cb() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5O_attr_write
|
||||
*
|
||||
* Purpose: Write a new value to an attribute.
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Quincey Koziol
|
||||
* Monday, December 4, 2006
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5O_attr_write(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr)
|
||||
{
|
||||
H5O_t *oh = NULL; /* Pointer to actual object header */
|
||||
unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for object header */
|
||||
herr_t ret_value = SUCCEED; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_write)
|
||||
|
||||
/* Check arguments */
|
||||
HDassert(loc);
|
||||
HDassert(attr);
|
||||
|
||||
/* Protect the object header to iterate over */
|
||||
if(NULL == (oh = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, FAIL, "unable to load object header")
|
||||
|
||||
/* Check for attributes stored densely */
|
||||
if(H5F_addr_defined(oh->attr_fheap_addr)) {
|
||||
/* Modify the attribute data in dense storage */
|
||||
if(H5A_dense_write(loc->file, dxpl_id, oh, attr) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "error updating attribute")
|
||||
} /* end if */
|
||||
else {
|
||||
H5O_iter_wrt_t udata; /* User data for callback */
|
||||
H5O_mesg_operator_t op; /* Wrapper for operator */
|
||||
|
||||
/* Set up user data for callback */
|
||||
udata.f = loc->file;
|
||||
udata.dxpl_id = dxpl_id;
|
||||
udata.attr = attr;
|
||||
udata.found = FALSE;
|
||||
|
||||
/* Iterate over attributes, to locate correct one to update */
|
||||
op.lib_op = H5O_attr_write_cb;
|
||||
if(H5O_msg_iterate_real(loc->file, oh, H5O_MSG_ATTR, TRUE, op, &udata, dxpl_id, &oh_flags) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "error updating attribute")
|
||||
|
||||
/* Check that we found the attribute */
|
||||
if(!udata.found)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "can't locate open attribute?")
|
||||
} /* end else */
|
||||
|
||||
/* Update the modification time, if any */
|
||||
if(H5O_touch_oh(loc->file, dxpl_id, oh, FALSE, &oh_flags) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update time on object")
|
||||
|
||||
done:
|
||||
if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0)
|
||||
HDONE_ERROR(H5E_ATTR, H5E_PROTECT, FAIL, "unable to release object header")
|
||||
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5O_attr_write */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5O_attr_rename_dup_cb
|
||||
*
|
||||
* Purpose: Object header iterator callback routine to check for
|
||||
* duplicate name during rename
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Quincey Koziol
|
||||
* koziol@hdfgroup.org
|
||||
* Dec 5 2006
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static herr_t
|
||||
H5O_attr_rename_dup_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
|
||||
unsigned UNUSED sequence, unsigned UNUSED *oh_flags_ptr, void *_udata/*in,out*/)
|
||||
{
|
||||
H5O_iter_ren_t *udata = (H5O_iter_ren_t *)_udata; /* Operator user data */
|
||||
herr_t ret_value = H5_ITER_CONT; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_rename_dup_cb)
|
||||
|
||||
/* check args */
|
||||
HDassert(oh);
|
||||
HDassert(mesg);
|
||||
HDassert(!udata->found);
|
||||
|
||||
/* Check for shared message */
|
||||
if(mesg->flags & H5O_MSG_FLAG_SHARED) {
|
||||
H5A_t shared_attr; /* Copy of shared attribute */
|
||||
|
||||
/*
|
||||
* If the message is shared then then the native pointer points to an
|
||||
* H5O_MSG_SHARED message. We use that information to look up the real
|
||||
* message in the global heap or some other object header.
|
||||
*/
|
||||
if(NULL == H5O_shared_read(udata->f, udata->dxpl_id, mesg->native, H5O_MSG_ATTR, &shared_attr))
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, H5_ITER_ERROR, "unable to read shared attribute")
|
||||
|
||||
/* Check for existing attribute with new name */
|
||||
if(HDstrcmp(shared_attr.name, udata->new_name) == 0) {
|
||||
/* Indicate that we found an existing attribute with the new name*/
|
||||
udata->found = TRUE;
|
||||
|
||||
/* Stop iterating */
|
||||
ret_value = H5_ITER_STOP;
|
||||
} /* end if */
|
||||
|
||||
/* Release copy of shared attribute */
|
||||
H5O_attr_reset(&shared_attr);
|
||||
} /* end if */
|
||||
else {
|
||||
/* Check for existing attribute with new name */
|
||||
if(HDstrcmp(((H5A_t *)mesg->native)->name, udata->new_name) == 0) {
|
||||
/* Indicate that we found an existing attribute with the new name*/
|
||||
udata->found = TRUE;
|
||||
|
||||
/* Stop iterating */
|
||||
ret_value = H5_ITER_STOP;
|
||||
} /* end if */
|
||||
} /* end else */
|
||||
|
||||
done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5O_attr_rename_dup_cb() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5O_attr_rename_mod_cb
|
||||
*
|
||||
* Purpose: Object header iterator callback routine to change name of
|
||||
* attribute during rename
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Quincey Koziol
|
||||
* koziol@hdfgroup.org
|
||||
* Dec 5 2006
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static herr_t
|
||||
H5O_attr_rename_mod_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
|
||||
unsigned UNUSED sequence, unsigned *oh_flags_ptr, void *_udata/*in,out*/)
|
||||
{
|
||||
H5O_iter_ren_t *udata = (H5O_iter_ren_t *)_udata; /* Operator user data */
|
||||
herr_t ret_value = H5_ITER_CONT; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_rename_mod_cb)
|
||||
|
||||
/* check args */
|
||||
HDassert(oh);
|
||||
HDassert(mesg);
|
||||
HDassert(!udata->found);
|
||||
|
||||
/* Check for shared message */
|
||||
if(mesg->flags & H5O_MSG_FLAG_SHARED) {
|
||||
H5A_t shared_attr; /* Copy of shared attribute */
|
||||
|
||||
/*
|
||||
* If the message is shared then then the native pointer points to an
|
||||
* H5O_MSG_SHARED message. We use that information to look up the real
|
||||
* message in the global heap or some other object header.
|
||||
*/
|
||||
if(NULL == H5O_shared_read(udata->f, udata->dxpl_id, mesg->native, H5O_MSG_ATTR, &shared_attr))
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, H5_ITER_ERROR, "unable to read shared attribute")
|
||||
|
||||
/* Check for correct attribute message to modify */
|
||||
if(HDstrcmp(shared_attr.name, udata->old_name) == 0) {
|
||||
/* XXX: fix me */
|
||||
HDfprintf(stderr, "%s: renaming a shared attribute not supported yet!\n", FUNC);
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, H5_ITER_ERROR, "renaming a shared attribute not supported yet")
|
||||
} /* end if */
|
||||
|
||||
/* Release copy of shared attribute */
|
||||
H5O_attr_reset(&shared_attr);
|
||||
} /* end if */
|
||||
else {
|
||||
/* Find correct attribute message to rename */
|
||||
if(HDstrcmp(((H5A_t *)mesg->native)->name, udata->old_name) == 0) {
|
||||
/* Change the name for the attribute */
|
||||
H5MM_xfree(((H5A_t *)mesg->native)->name);
|
||||
((H5A_t *)mesg->native)->name = H5MM_xstrdup(udata->new_name);
|
||||
|
||||
/* Indicate that we found an existing attribute with the old name*/
|
||||
udata->found = TRUE;
|
||||
|
||||
/* Mark message as dirty */
|
||||
mesg->dirty = TRUE;
|
||||
|
||||
/* Stop iterating */
|
||||
ret_value = H5_ITER_STOP;
|
||||
|
||||
/* Indicate that the object header was modified */
|
||||
*oh_flags_ptr |= H5AC__DIRTIED_FLAG;
|
||||
} /* end if */
|
||||
} /* end else */
|
||||
|
||||
done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5O_attr_rename_mod_cb() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5O_attr_rename
|
||||
*
|
||||
* Purpose: Rename an attribute.
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Quincey Koziol
|
||||
* Tuesday, December 5, 2006
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5O_attr_rename(const H5O_loc_t *loc, hid_t dxpl_id, const char *old_name, const char *new_name)
|
||||
{
|
||||
H5O_t *oh = NULL; /* Pointer to actual object header */
|
||||
unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for object header */
|
||||
herr_t ret_value = SUCCEED; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_rename)
|
||||
|
||||
/* Check arguments */
|
||||
HDassert(loc);
|
||||
HDassert(old_name);
|
||||
HDassert(new_name);
|
||||
|
||||
/* Protect the object header to iterate over */
|
||||
if(NULL == (oh = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, FAIL, "unable to load object header")
|
||||
|
||||
/* Check for attributes stored densely */
|
||||
if(H5F_addr_defined(oh->attr_fheap_addr)) {
|
||||
/* XXX: fix me */
|
||||
HDfprintf(stderr, "%s: renaming attributes in dense storage not supported yet!\n", FUNC);
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "renaming attributes in dense storage not supported yet")
|
||||
} /* end if */
|
||||
else {
|
||||
H5O_iter_ren_t udata; /* User data for callback */
|
||||
H5O_mesg_operator_t op; /* Wrapper for operator */
|
||||
|
||||
/* Set up user data for callback */
|
||||
udata.f = loc->file;
|
||||
udata.dxpl_id = dxpl_id;
|
||||
udata.old_name = old_name;
|
||||
udata.new_name = new_name;
|
||||
udata.found = FALSE;
|
||||
|
||||
/* Iterate over attributes, to check if "new name" exists already */
|
||||
op.lib_op = H5O_attr_rename_dup_cb;
|
||||
if(H5O_msg_iterate_real(loc->file, oh, H5O_MSG_ATTR, TRUE, op, &udata, dxpl_id, &oh_flags) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "error updating attribute")
|
||||
|
||||
/* If the new name was found, indicate an error */
|
||||
if(udata.found)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_EXISTS, FAIL, "attribute with new name already exists")
|
||||
|
||||
/* Iterate over attributes again, to actually rename attribute with old name */
|
||||
op.lib_op = H5O_attr_rename_mod_cb;
|
||||
if(H5O_msg_iterate_real(loc->file, oh, H5O_MSG_ATTR, TRUE, op, &udata, dxpl_id, &oh_flags) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "error updating attribute")
|
||||
} /* end else */
|
||||
|
||||
/* Update the modification time, if any */
|
||||
if(H5O_touch_oh(loc->file, dxpl_id, oh, FALSE, &oh_flags) < 0)
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update time on object")
|
||||
|
||||
done:
|
||||
if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, oh_flags) < 0)
|
||||
HDONE_ERROR(H5E_ATTR, H5E_PROTECT, FAIL, "unable to release object header")
|
||||
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5O_attr_rename */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5O_attr_iterate
|
||||
*
|
||||
* Purpose: Iterate over attributes for an object.
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Quincey Koziol
|
||||
* Tuesday, December 5, 2006
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5O_attr_iterate(hid_t loc_id, const H5O_loc_t *loc, hid_t dxpl_id,
|
||||
unsigned skip, unsigned *last_attr, H5A_operator_t op, void *op_data)
|
||||
{
|
||||
H5O_t *oh = NULL; /* Pointer to actual object header */
|
||||
haddr_t attr_fheap_addr; /* Address of fractal heap for dense attribute storage */
|
||||
haddr_t name_bt2_addr; /* Address of v2 B-tree for name index on dense attribute storage */
|
||||
herr_t ret_value = SUCCEED; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_iterate)
|
||||
|
||||
/* Check arguments */
|
||||
HDassert(loc);
|
||||
HDassert(op);
|
||||
|
||||
/* Protect the object header to iterate over */
|
||||
if(NULL == (oh = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
|
||||
HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, FAIL, "unable to load object header")
|
||||
|
||||
/* Retrieve the information about dense attribute storage */
|
||||
if(oh->version > H5O_VERSION_1 && H5F_addr_defined(oh->attr_fheap_addr)) {
|
||||
attr_fheap_addr = oh->attr_fheap_addr;
|
||||
name_bt2_addr = oh->name_bt2_addr;
|
||||
} /* end if */
|
||||
else
|
||||
attr_fheap_addr = name_bt2_addr = HADDR_UNDEF;
|
||||
|
||||
/* Release the object header */
|
||||
if(H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
|
||||
HDONE_ERROR(H5E_ATTR, H5E_PROTECT, FAIL, "unable to release object header")
|
||||
oh = NULL;
|
||||
|
||||
/* Check for attributes stored densely */
|
||||
if(H5F_addr_defined(attr_fheap_addr)) {
|
||||
if((ret_value = H5A_dense_iterate(loc->file, dxpl_id, loc_id, attr_fheap_addr,
|
||||
name_bt2_addr, skip, last_attr, op, op_data)) < 0)
|
||||
HERROR(H5E_ATTR, H5E_BADITER, "error iterating over attributes");
|
||||
} /* end if */
|
||||
else {
|
||||
unsigned idx; /* Current attribute to operate on */
|
||||
|
||||
/* Check for skipping over too many attributes */
|
||||
if((int)skip < H5O_msg_count(loc, H5O_ATTR_ID, dxpl_id)) {
|
||||
H5A_t found_attr; /* Copy of attribute for callback */
|
||||
|
||||
/* Read each attribute and call application's callback */
|
||||
/* (this could be made more efficient by iterating over the
|
||||
* attribute header messages with H5O_msg_iterate, but then
|
||||
* the object header would be locked during the callback into
|
||||
* the application code, causing problems if they attempt to
|
||||
* do anything with the object the attribute is on - QAK)
|
||||
*/
|
||||
idx = skip;
|
||||
while(H5O_msg_read(loc, H5O_ATTR_ID, (int)idx, &found_attr, dxpl_id) != NULL) {
|
||||
/* Call application's callback */
|
||||
idx++;
|
||||
if((ret_value = (op)(loc_id, found_attr.name, op_data)) != 0) {
|
||||
H5A_free(&found_attr);
|
||||
break;
|
||||
} /* end if */
|
||||
H5A_free(&found_attr);
|
||||
} /* end while */
|
||||
|
||||
/* Clear error stack from running off end of attributes */
|
||||
if(ret_value == 0)
|
||||
H5E_clear_stack(NULL);
|
||||
} /* end if */
|
||||
else
|
||||
if(skip > 0)
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified")
|
||||
|
||||
/* Update last attribute looked at */
|
||||
if(last_attr)
|
||||
*last_attr = idx;
|
||||
} /* end else */
|
||||
|
||||
done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5O_attr_iterate */
|
||||
|
12
src/H5Opkg.h
12
src/H5Opkg.h
@ -23,6 +23,7 @@
|
||||
#include "H5Oprivate.h" /* Object headers */
|
||||
|
||||
/* Other private headers needed by this file */
|
||||
#include "H5Aprivate.h" /* Attributes */
|
||||
#include "H5ACprivate.h" /* Metadata cache */
|
||||
|
||||
/* Object header macros */
|
||||
@ -418,6 +419,17 @@ H5_DLL herr_t H5O_release_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
|
||||
H5_DLL void * H5O_shared_read(H5F_t *f, hid_t dxpl_id, const H5O_shared_t *shared,
|
||||
const H5O_msg_class_t *type, void *mesg);
|
||||
|
||||
/* Attribute operations */
|
||||
H5_DLL herr_t H5O_attr_create(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr);
|
||||
H5_DLL H5A_t *H5O_attr_open(const H5O_loc_t *loc, const char *name,
|
||||
hid_t dxpl_id);
|
||||
H5_DLL herr_t H5O_attr_write(const H5O_loc_t *loc, hid_t dxpl_id,
|
||||
H5A_t *attr);
|
||||
H5_DLL herr_t H5O_attr_rename(const H5O_loc_t *loc, hid_t dxpl_id,
|
||||
const char *old_name, const char *new_name);
|
||||
H5_DLL herr_t H5O_attr_iterate(hid_t loc_id, const H5O_loc_t *loc, hid_t dxpl_id,
|
||||
unsigned skip, unsigned *last_attr, H5A_operator_t op, void *op_data);
|
||||
|
||||
/* These functions operate on object locations */
|
||||
H5_DLL H5O_loc_t *H5O_get_loc(hid_t id);
|
||||
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include "H5Opublic.h" /* Object header functions */
|
||||
|
||||
/* Public headers needed by this file */
|
||||
#include "H5Apublic.h" /* Attributes */
|
||||
#include "H5Dpublic.h" /* Dataset functions */
|
||||
#include "H5Lpublic.h" /* Link functions */
|
||||
#include "H5Spublic.h" /* Dataspace functions */
|
||||
@ -375,7 +374,6 @@ typedef herr_t (*H5O_operator_t)(const void *mesg/*in*/, unsigned idx,
|
||||
struct H5P_genplist_t;
|
||||
struct H5SL_t;
|
||||
struct H5O_t;
|
||||
struct H5A_t;
|
||||
|
||||
/* Object header routines */
|
||||
H5_DLL herr_t H5O_init(void);
|
||||
@ -463,14 +461,5 @@ H5_DLL herr_t H5O_fill_convert(void *_fill, H5T_t *type, hid_t dxpl_id);
|
||||
/* Link operators */
|
||||
H5_DLL herr_t H5O_link_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link);
|
||||
|
||||
/* Attribute operations */
|
||||
H5_DLL herr_t H5O_attr_create(const H5O_loc_t *loc, hid_t dxpl_id, struct H5A_t *attr);
|
||||
H5_DLL herr_t H5O_attr_write(const H5O_loc_t *loc, hid_t dxpl_id,
|
||||
struct H5A_t *attr);
|
||||
H5_DLL herr_t H5O_attr_rename(const H5O_loc_t *loc, hid_t dxpl_id,
|
||||
const char *old_name, const char *new_name);
|
||||
H5_DLL herr_t H5O_attr_iterate(hid_t loc_id, const H5O_loc_t *loc, hid_t dxpl_id,
|
||||
unsigned skip, unsigned *last_attr, H5A_operator_t op, void *op_data);
|
||||
|
||||
#endif /* _H5Oprivate_H */
|
||||
|
||||
|
@ -58,7 +58,7 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
|
||||
H5HFspace.c H5HFstat.c H5HFtest.c H5HFtiny.c \
|
||||
H5HG.c H5HGdbg.c H5HL.c H5HLdbg.c H5HP.c H5I.c H5MF.c H5MM.c \
|
||||
H5MP.c H5MPtest.c H5L.c H5Lexternal.c H5O.c H5Oalloc.c H5Oattr.c \
|
||||
H5Obogus.c H5Ocache.c \
|
||||
H5Oattribute.c H5Obogus.c H5Ocache.c \
|
||||
H5Ocont.c H5Ocopy.c H5Odbg.c H5Odtype.c H5Oefl.c H5Ofill.c H5Oginfo.c \
|
||||
H5Olayout.c \
|
||||
H5Olinfo.c H5Olink.c H5Omessage.c H5Omtime.c \
|
||||
|
@ -99,7 +99,7 @@ am_libhdf5_la_OBJECTS = H5.lo H5checksum.lo H5dbg.lo H5system.lo \
|
||||
H5HFspace.lo H5HFstat.lo H5HFtest.lo H5HFtiny.lo H5HG.lo \
|
||||
H5HGdbg.lo H5HL.lo H5HLdbg.lo H5HP.lo H5I.lo H5MF.lo H5MM.lo \
|
||||
H5MP.lo H5MPtest.lo H5L.lo H5Lexternal.lo H5O.lo H5Oalloc.lo \
|
||||
H5Oattr.lo H5Obogus.lo H5Ocache.lo H5Ocont.lo H5Ocopy.lo \
|
||||
H5Oattr.lo H5Oattribute.lo H5Obogus.lo H5Ocache.lo H5Ocont.lo H5Ocopy.lo \
|
||||
H5Odbg.lo H5Odtype.lo H5Oefl.lo H5Ofill.lo H5Oginfo.lo \
|
||||
H5Olayout.lo H5Olinfo.lo H5Olink.lo H5Omessage.lo H5Omtime.lo H5Oname.lo \
|
||||
H5Onull.lo H5Opline.lo H5Osdspace.lo H5Oshared.lo H5Ostab.lo H5Otest.lo \
|
||||
@ -414,7 +414,7 @@ libhdf5_la_SOURCES = H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
|
||||
H5HFspace.c H5HFstat.c H5HFtest.c H5HFtiny.c \
|
||||
H5HG.c H5HGdbg.c H5HL.c H5HLdbg.c H5HP.c H5I.c H5MF.c H5MM.c \
|
||||
H5MP.c H5MPtest.c H5L.c H5Lexternal.c H5O.c H5Oalloc.c H5Oattr.c \
|
||||
H5Obogus.c H5Ocache.c \
|
||||
H5Oattribute.c H5Obogus.c H5Ocache.c \
|
||||
H5Ocont.c H5Ocopy.c H5Odbg.c H5Odtype.c H5Oefl.c H5Ofill.c H5Oginfo.c \
|
||||
H5Olayout.c \
|
||||
H5Olinfo.c H5Olink.c H5Omessage.c H5Omtime.c \
|
||||
@ -660,6 +660,7 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5O.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Oalloc.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Oattr.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Oattribute.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@
|
||||
|
134
test/tattr.c
134
test/tattr.c
@ -1683,12 +1683,12 @@ test_attr_dtype_shared(hid_t fapl)
|
||||
|
||||
/****************************************************************
|
||||
**
|
||||
** test_attr_dense(): Test basic H5A (attribute) code.
|
||||
** Tests "dense" attribute storage
|
||||
** test_attr_dense_create(): Test basic H5A (attribute) code.
|
||||
** Tests "dense" attribute storage creation
|
||||
**
|
||||
****************************************************************/
|
||||
static void
|
||||
test_attr_dense(hid_t fapl)
|
||||
test_attr_dense_create(hid_t fapl)
|
||||
{
|
||||
hid_t fid; /* HDF5 File ID */
|
||||
hid_t dataset; /* Dataset ID */
|
||||
@ -1703,7 +1703,7 @@ test_attr_dense(hid_t fapl)
|
||||
herr_t ret; /* Generic return value */
|
||||
|
||||
/* Output message about test being performed */
|
||||
MESSAGE(5, ("Testing Dense Attribute Storage\n"));
|
||||
MESSAGE(5, ("Testing Dense Attribute Storage Creation\n"));
|
||||
|
||||
/* Create file */
|
||||
fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, fapl);
|
||||
@ -1781,7 +1781,128 @@ HDfprintf(stderr, "max_compact = %u, min_dense = %u\n", max_compact, min_dense);
|
||||
/* Close file */
|
||||
ret = H5Fclose(fid);
|
||||
CHECK(ret, FAIL, "H5Fclose");
|
||||
} /* test_attr_dense() */
|
||||
} /* test_attr_dense_create() */
|
||||
|
||||
/****************************************************************
|
||||
**
|
||||
** test_attr_dense_open(): Test basic H5A (attribute) code.
|
||||
** Tests opening attributes in "dense" storage
|
||||
**
|
||||
****************************************************************/
|
||||
static void
|
||||
test_attr_dense_open(hid_t fapl)
|
||||
{
|
||||
hid_t fid; /* HDF5 File ID */
|
||||
hid_t dataset; /* Dataset ID */
|
||||
hid_t sid; /* Dataspace ID */
|
||||
hid_t attr; /* Attribute ID */
|
||||
hid_t dcpl; /* Dataset creation property list ID */
|
||||
char attrname[NAME_BUF_SIZE]; /* Name of attribute */
|
||||
unsigned max_compact; /* Maximum # of attributes to store compactly */
|
||||
unsigned min_dense; /* Minimum # of attributes to store "densely" */
|
||||
htri_t is_dense; /* Are attributes stored densely? */
|
||||
unsigned u; /* Local index variable */
|
||||
herr_t ret; /* Generic return value */
|
||||
|
||||
/* Output message about test being performed */
|
||||
MESSAGE(5, ("Testing Opening Attributes in Dense Storage\n"));
|
||||
|
||||
/* Create file */
|
||||
fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, fapl);
|
||||
CHECK(fid, FAIL, "H5Fcreate");
|
||||
|
||||
/* Create dataspace for dataset */
|
||||
sid = H5Screate(H5S_SCALAR);
|
||||
CHECK(sid, FAIL, "H5Screate");
|
||||
|
||||
/* Query the group creation properties */
|
||||
dcpl = H5Pcreate(H5P_DATASET_CREATE);
|
||||
CHECK(dcpl, FAIL, "H5Pcreate");
|
||||
|
||||
/* Create a dataset */
|
||||
dataset = H5Dcreate(fid, DSET1_NAME, H5T_NATIVE_UCHAR, sid, dcpl);
|
||||
CHECK(dataset, FAIL, "H5Dcreate");
|
||||
|
||||
/* Retrieve limits for compact/dense attribute storage */
|
||||
ret = H5Pget_attr_phase_change(dcpl, &max_compact, &min_dense);
|
||||
CHECK(ret, FAIL, "H5Pget_attr_phase_change");
|
||||
#ifdef QAK
|
||||
HDfprintf(stderr, "max_compact = %u, min_dense = %u\n", max_compact, min_dense);
|
||||
#endif /* QAK */
|
||||
|
||||
/* Check on dataset's attribute storage status */
|
||||
is_dense = H5O_is_attr_dense_test(dataset);
|
||||
VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");
|
||||
|
||||
/* Add attributes, until just before coverting to dense storage */
|
||||
for(u = 0; u < max_compact; u++) {
|
||||
/* Create attribute */
|
||||
sprintf(attrname, "attr %02u", u);
|
||||
attr = H5Acreate(dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
|
||||
CHECK(attr, FAIL, "H5Acreate");
|
||||
|
||||
/* Write data into the attribute */
|
||||
ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
|
||||
CHECK(ret, FAIL, "H5Awrite");
|
||||
|
||||
/* Close attribute */
|
||||
ret = H5Aclose(attr);
|
||||
CHECK(ret, FAIL, "H5Aclose");
|
||||
} /* end for */
|
||||
|
||||
/* Check on dataset's attribute storage status */
|
||||
is_dense = H5O_is_attr_dense_test(dataset);
|
||||
VERIFY(is_dense, FALSE, "H5O_is_attr_dense_test");
|
||||
|
||||
/* Add one more attribute, to push into "dense" storage */
|
||||
/* Create attribute */
|
||||
sprintf(attrname, "attr %02u", u);
|
||||
attr = H5Acreate(dataset, attrname, H5T_NATIVE_UINT, sid, H5P_DEFAULT);
|
||||
CHECK(attr, FAIL, "H5Acreate");
|
||||
|
||||
/* Check on dataset's attribute storage status */
|
||||
is_dense = H5O_is_attr_dense_test(dataset);
|
||||
VERIFY(is_dense, TRUE, "H5O_is_attr_dense_test");
|
||||
|
||||
/* Write data into the attribute */
|
||||
ret = H5Awrite(attr, H5T_NATIVE_UINT, &u);
|
||||
CHECK(ret, FAIL, "H5Awrite");
|
||||
|
||||
/* Close attribute */
|
||||
ret = H5Aclose(attr);
|
||||
CHECK(ret, FAIL, "H5Aclose");
|
||||
|
||||
/* Close dataspace */
|
||||
ret = H5Sclose(sid);
|
||||
CHECK(ret, FAIL, "H5Sclose");
|
||||
|
||||
/* Re-open all the attributes and verify the data */
|
||||
for(u = 0; u <= max_compact; u++) {
|
||||
unsigned value;
|
||||
|
||||
/* Open attribute */
|
||||
sprintf(attrname, "attr %02u", u);
|
||||
attr = H5Aopen_name(dataset, attrname);
|
||||
CHECK(attr, FAIL, "H5Aopen");
|
||||
|
||||
/* Read data from the attribute */
|
||||
ret = H5Aread(attr, H5T_NATIVE_UINT, &value);
|
||||
CHECK(ret, FAIL, "H5Aread");
|
||||
VERIFY(value, u, "H5Aread");
|
||||
|
||||
/* Close attribute */
|
||||
ret = H5Aclose(attr);
|
||||
CHECK(ret, FAIL, "H5Aclose");
|
||||
} /* end for */
|
||||
|
||||
/* Close Dataset */
|
||||
ret = H5Dclose(dataset);
|
||||
CHECK(ret, FAIL, "H5Dclose");
|
||||
|
||||
/* Close file */
|
||||
ret = H5Fclose(fid);
|
||||
CHECK(ret, FAIL, "H5Fclose");
|
||||
} /* test_attr_dense_open() */
|
||||
|
||||
/****************************************************************
|
||||
**
|
||||
@ -1852,7 +1973,8 @@ test_attr(void)
|
||||
} /* end for */
|
||||
|
||||
/* Tests on "new format" attribute storage */
|
||||
test_attr_dense(fapl2); /* Test dense attribute storage */
|
||||
test_attr_dense_create(fapl2); /* Test dense attribute storage creation */
|
||||
test_attr_dense_open(fapl2); /* Test opening attributes in dense storage */
|
||||
#else /* QAK */
|
||||
HDfprintf(stderr, "Uncomment tests!\n");
|
||||
#endif /* QAK */
|
||||
|
Loading…
x
Reference in New Issue
Block a user