diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2007-02-21 19:58:48 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2007-02-21 19:58:48 (GMT) |
commit | 1e07756ac265fad1171cd18efcdb2b0ba9bb903d (patch) | |
tree | 92f09eaab8d0ad899a15ef089cc1b7c5f4e07440 /src | |
parent | 9deb5961eeb5265c54df1a8a9daf0cea6c3cded6 (diff) | |
download | hdf5-1e07756ac265fad1171cd18efcdb2b0ba9bb903d.zip hdf5-1e07756ac265fad1171cd18efcdb2b0ba9bb903d.tar.gz hdf5-1e07756ac265fad1171cd18efcdb2b0ba9bb903d.tar.bz2 |
[svn-r13367] Description:
Allow "big" attributes to push attribute storage into "dense" form
immediately, to accomodate storing the attribute. (This is only allowed
in the "latest" version of the format).
Tested on:
Linux/32 2.6 (chicago)
Linux/64 2.6 (chicago2)
Diffstat (limited to 'src')
-rw-r--r-- | src/H5HF.c | 8 | ||||
-rw-r--r-- | src/H5HFhuge.c | 75 | ||||
-rw-r--r-- | src/H5HFpkg.h | 2 | ||||
-rw-r--r-- | src/H5Oattribute.c | 44 | ||||
-rwxr-xr-x | src/H5SM.c | 154 | ||||
-rwxr-xr-x | src/H5SMpkg.h | 13 | ||||
-rwxr-xr-x | src/H5SMprivate.h | 25 |
7 files changed, 263 insertions, 58 deletions
@@ -602,12 +602,12 @@ H5HF_write(H5HF_t *fh, hid_t dxpl_id, void *_id, hbool_t UNUSED *id_changed, /* Operate on object from managed heap blocks */ /* (ID can't change and modifying object is "easy" to manage) */ if(H5HF_man_write(fh->hdr, dxpl_id, id, obj) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "can't operate on object from fractal heap") + HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "can't write to 'managed' heap object") } /* end if */ else if((id_flags & H5HF_ID_TYPE_MASK) == H5HF_ID_TYPE_HUGE) { - /* Check for writing a 'huge' object */ - /* (which isn't supported yet - ID could change and lots of work to re-compress changed object) */ - HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "modifying 'huge' object not supported yet") + /* Operate on "huge" object */ + if(H5HF_huge_write(fh->hdr, dxpl_id, id, obj) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "can't write to 'huge' heap object") } /* end if */ else if((id_flags & H5HF_ID_TYPE_MASK) == H5HF_ID_TYPE_TINY) { /* Check for writing a 'tiny' object */ diff --git a/src/H5HFhuge.c b/src/H5HFhuge.c index 623210d..198ef62 100644 --- a/src/H5HFhuge.c +++ b/src/H5HFhuge.c @@ -708,6 +708,81 @@ done: /*------------------------------------------------------------------------- + * Function: H5HF_huge_write + * + * Purpose: Write a 'huge' object to the heap + * + * Note: This implementation somewhat limited: it doesn't handle + * heaps with filters, which would require re-compressing the + * huge object and probably changing the address of the object + * on disk (and possibly the heap ID for "direct" huge IDs). + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Feb 21 2007 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_huge_write(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id, + const void *obj) +{ + haddr_t obj_addr; /* Object's address in the file */ + size_t obj_size; /* Object's size in the file */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_huge_write) + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(id); + HDassert(obj); + + /* Check for filters on the heap */ + if(hdr->filter_len > 0) + HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "modifying 'huge' object with filters not supported yet") + + /* Skip over the flag byte */ + id++; + + /* Check for 'huge' object ID that encodes address & length directly */ + if(hdr->huge_ids_direct) { + /* Retrieve the object's address and length (common) */ + H5F_addr_decode(hdr->f, &id, &obj_addr); + H5F_DECODE_LENGTH(hdr->f, id, obj_size); + } /* end if */ + else { + H5HF_huge_bt2_indir_rec_t found_rec; /* Record found from tracking object */ + H5HF_huge_bt2_indir_rec_t search_rec; /* Record for searching for object */ + + /* Get ID for looking up 'huge' object in v2 B-tree */ + UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size) + + /* Look up object in v2 B-tree */ + if(H5B2_find(hdr->f, dxpl_id, H5HF_BT2_INDIR, hdr->huge_bt2_addr, + &search_rec, H5HF_huge_bt2_indir_found, &found_rec) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in B-tree") + + /* Retrieve the object's address & length */ + obj_addr = found_rec.addr; + H5_ASSIGN_OVERFLOW(/* To: */ obj_size, /* From: */ found_rec.len, /* From: */ hsize_t, /* To: */ size_t); + } /* end else */ + + /* Write the object's data to the file */ + /* (writes directly from application's buffer) */ + if(H5F_block_write(hdr->f, H5FD_MEM_FHEAP_HUGE_OBJ, obj_addr, obj_size, dxpl_id, obj) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "writing 'huge' object to file failed") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_huge_write() */ + + +/*------------------------------------------------------------------------- * Function: H5HF_huge_read * * Purpose: Read a 'huge' object from the heap diff --git a/src/H5HFpkg.h b/src/H5HFpkg.h index a1415a1..6dc1498 100644 --- a/src/H5HFpkg.h +++ b/src/H5HFpkg.h @@ -638,6 +638,8 @@ H5_DLL herr_t H5HF_huge_get_obj_len(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id, size_t *obj_len_p); H5_DLL herr_t H5HF_huge_read(H5HF_hdr_t *fh, hid_t dxpl_id, const uint8_t *id, void *obj); +H5_DLL herr_t H5HF_huge_write(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id, + const void *obj); H5_DLL herr_t H5HF_huge_op(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id, H5HF_operator_t op, void *op_data); H5_DLL herr_t H5HF_huge_remove(H5HF_hdr_t *fh, hid_t dxpl_id, const uint8_t *id); diff --git a/src/H5Oattribute.c b/src/H5Oattribute.c index 3d3ae2c..9377bd0 100644 --- a/src/H5Oattribute.c +++ b/src/H5Oattribute.c @@ -221,24 +221,38 @@ H5O_attr_create(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr) if(NULL == (oh = (H5O_t *)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 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 */ + /* Check if switching to "dense" attribute storage is possible */ + if(oh->version > H5O_VERSION_1 && !H5F_addr_defined(oh->attr_fheap_addr)) { + htri_t sharable; /* Whether the attribute will be shared */ + size_t raw_size = 0; /* Raw size of message */ + + /* Check for attribute being sharable */ + if((sharable = H5SM_can_share(loc->file, dxpl_id, NULL, NULL, H5O_ATTR_ID, attr)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_BADMESG, FAIL, "can't determine attribute sharing status") + else if(sharable == FALSE) { + /* Compute the size needed to encode the attribute */ + raw_size = (H5O_MSG_ATTR->raw_size)(loc->file, FALSE, attr); + } /* end if */ - /* 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") + /* Check for condititions for switching to "dense" attribute storage are met */ + if(oh->nattrs == oh->max_compact || + (!sharable && raw_size >= H5O_MESG_MAX_SIZE)) { + H5O_iter_cvt_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; + /* 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") - /* Iterate over existing attributes, moving them to dense storage */ - op.lib_op = H5O_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") + /* 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 = H5O_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 */ } /* end if */ /* Increment attribute count */ @@ -761,6 +761,122 @@ done: /*------------------------------------------------------------------------- + * Function: H5SM_can_share_common + * + * Purpose: "trivial" checks for determining if a message can be shared. + * + * Note: These checks are common to the "can share" and "try share" + * routines and are the "fast" checks before we need to protect + * the SOHM master table. + * + * Return: TRUE if message could be a SOHM + * FALSE if this message couldn't be a SOHM + * Negative on failure + * + * Programmer: Quincey Koziol + * Wednesday, February 21, 2007 + * + *------------------------------------------------------------------------- + */ +static htri_t +H5SM_can_share_common(const H5F_t *f, unsigned type_id, const void *mesg) +{ + htri_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5SM_can_share_common) + + /* Check whether this message ought to be shared or not */ + /* If sharing is disabled in this file, don't share the message */ + if(!H5F_addr_defined(f->shared->sohm_addr)) + HGOTO_DONE(FALSE) + + /* Type-specific check */ + if((ret_value = H5O_msg_can_share(type_id, mesg)) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_BADTYPE, FAIL, "can_share callback returned error") + if(ret_value == FALSE) + HGOTO_DONE(FALSE) + + /* At this point, the message passes the "trivial" checks and is worth + * further checks. + */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5SM_can_share_common() */ + + +/*------------------------------------------------------------------------- + * Function: H5SM_can_share + * + * Purpose: Checks if an object header message would be shared or is + * already shared. + * + * If not, returns FALSE and does nothing. + * + * Return: TRUE if message will be a SOHM + * FALSE if this message won't be a SOHM + * Negative on failure + * + * Programmer: Quincey Koziol + * Wednesday, February 21, 2007 + * + *------------------------------------------------------------------------- + */ +htri_t +H5SM_can_share(H5F_t *f, hid_t dxpl_id, H5SM_master_table_t *table, + ssize_t *sohm_index_num, unsigned type_id, const void *mesg) +{ + size_t mesg_size; + H5SM_master_table_t *my_table = NULL; + ssize_t index_num; + htri_t tri_ret; + htri_t ret_value = TRUE; + + FUNC_ENTER_NOAPI(H5SM_can_share, FAIL) + + /* "trivial" sharing checks */ + if((tri_ret = H5SM_can_share_common(f, type_id, mesg)) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_BADTYPE, FAIL, "'trivial' sharing checks returned error") + if(tri_ret == FALSE) + HGOTO_DONE(FALSE) + + /* Look up the master SOHM table */ + /* (use incoming master SOHM table if possible) */ + if(table) + my_table = table; + else { + if(NULL == (my_table = (H5SM_master_table_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_TABLE, f->shared->sohm_addr, NULL, NULL, H5AC_READ))) + HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM master table") + } /* end if */ + + /* Find the right index for this message type. If there is no such index + * then this type of message isn't shareable + */ + if((index_num = H5SM_get_index(my_table, type_id)) < 0) { + H5E_clear_stack(NULL); /*ignore error*/ + HGOTO_DONE(FALSE) + } /* end if */ + + /* If the message isn't big enough, don't bother sharing it */ + if(0 == (mesg_size = H5O_msg_raw_size(f, type_id, TRUE, mesg))) + HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "unable to get OH message size") + if(mesg_size < my_table->indexes[index_num].min_mesg_size) + HGOTO_DONE(FALSE) + + /* At this point, the message will be shared, set the index number if requested. */ + if(sohm_index_num) + *sohm_index_num = index_num; + +done: + /* Release the master SOHM table, if we protected it */ + if(my_table && my_table != table && H5AC_unprotect(f, dxpl_id, H5AC_SOHM_TABLE, f->shared->sohm_addr, my_table, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_SOHM, H5E_CANTRELEASE, FAIL, "unable to close SOHM master table") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5SM_can_share() */ + + +/*------------------------------------------------------------------------- * Function: H5SM_try_share * * Purpose: Attempts to share an object header message. If the message @@ -784,46 +900,29 @@ done: htri_t H5SM_try_share(H5F_t *f, hid_t dxpl_id, unsigned type_id, void *mesg) { - size_t mesg_size; H5SM_master_table_t *table = NULL; unsigned cache_flags = H5AC__NO_FLAGS_SET; ssize_t index_num; htri_t tri_ret; - herr_t ret_value = TRUE; + htri_t ret_value = TRUE; FUNC_ENTER_NOAPI(H5SM_try_share, FAIL) - /* Check whether this message ought to be shared or not */ - /* If sharing is disabled in this file, don't share the message */ - if(f->shared->sohm_addr == HADDR_UNDEF) - HGOTO_DONE(FALSE); - - /* Type-specific check */ - if((tri_ret = H5O_msg_can_share(type_id, mesg)) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_BADTYPE, FAIL, "can_share callback returned error") + /* "trivial" sharing checks */ + if((tri_ret = H5SM_can_share_common(f, type_id, mesg)) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_BADTYPE, FAIL, "'trivial' sharing checks returned error") if(tri_ret == FALSE) - HGOTO_DONE(FALSE); + HGOTO_DONE(FALSE) /* Look up the master SOHM table */ if(NULL == (table = (H5SM_master_table_t *)H5AC_protect(f, dxpl_id, H5AC_SOHM_TABLE, f->shared->sohm_addr, NULL, NULL, H5AC_WRITE))) HGOTO_ERROR(H5E_CACHE, H5E_CANTPROTECT, FAIL, "unable to load SOHM master table") - /* Find the right index for this message type. If there is no such index - * then this type of message isn't shareable - */ - if((index_num = H5SM_get_index(table, type_id)) < 0) - { - H5E_clear_stack(NULL); /*ignore error*/ - HGOTO_DONE(FALSE); - } /* end if */ - - /* If the message isn't big enough, don't bother sharing it */ - if(0 == (mesg_size = H5O_msg_raw_size(f, type_id, TRUE, mesg))) - HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "unable to get OH message size") - if(mesg_size < table->indexes[index_num].min_mesg_size) - HGOTO_DONE(FALSE); - - /* At this point, the message will be shared. */ + /* "complex" sharing checks */ + if((tri_ret = H5SM_can_share(f, dxpl_id, table, &index_num, type_id, mesg)) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_BADTYPE, FAIL, "'complex' sharing checks returned error") + if(tri_ret == FALSE) + HGOTO_DONE(FALSE) /* If the index hasn't been allocated yet, create it */ if(table->indexes[index_num].index_addr == HADDR_UNDEF) @@ -1551,7 +1650,6 @@ H5SM_get_refcount(H5F_t *f, hid_t dxpl_id, unsigned type_id, H5SM_list_t *list = NULL; /* SOHM index list for message type (if in list form) */ H5SM_index_header_t *header=NULL; /* Index header for message type */ H5SM_mesg_key_t key; /* Key for looking up message */ - H5SM_fh_ud_gh_t udata; /* User data for fractal heap 'op' callback */ H5SM_sohm_t message; /* Shared message returned from callback */ size_t buf_size; /* Size of the encoded message */ void *encoding_buf = NULL; /* Buffer for encoded message */ diff --git a/src/H5SMpkg.h b/src/H5SMpkg.h index cf80959..aab7eb3 100755 --- a/src/H5SMpkg.h +++ b/src/H5SMpkg.h @@ -21,10 +21,17 @@ * the H5SM shared object header messages package. Source files * outside the H5SM package should include H5SMprivate.h instead. */ +#ifndef H5SM_PACKAGE +#error "Do not include this file outside the H5SM package!" +#endif + #ifndef _H5SMpkg_H #define _H5SMpkg_H -#include "H5SMprivate.h" +/* Get package's private header */ +#include "H5SMprivate.h" /* Shared Object Header Messages */ + +/* Other private headers needed by this file */ #include "H5B2private.h" /* B-trees */ #include "H5HFprivate.h" /* Fractal heaps */ @@ -141,13 +148,13 @@ typedef struct { /* Typedef for shared object header message master table */ -typedef struct { +struct H5SM_master_table_t { /* Information for H5AC cache functions, _must_ be first field in structure */ H5AC_info_t cache_info; uint8_t num_indexes; /* Number of indexes */ H5SM_index_header_t *indexes; /* Array of num_indexes indexes */ -} H5SM_master_table_t; +}; /* * Data exchange structure to pass through the fractal heap layer for the diff --git a/src/H5SMprivate.h b/src/H5SMprivate.h index 63c953c..49d0916 100755 --- a/src/H5SMprivate.h +++ b/src/H5SMprivate.h @@ -23,22 +23,30 @@ #ifndef _H5SMprivate_H #define _H5SMprivate_H -#include "H5Oprivate.h" -#include "H5Pprivate.h" +#include "H5Oprivate.h" /* Object headers */ +#include "H5Pprivate.h" /* Property lists */ /****************************/ /* Library Private Typedefs */ /****************************/ +/* Forward references of package typedefs */ +typedef struct H5SM_master_table_t H5SM_master_table_t; + + /******************************/ /* Library Private Prototypes */ /******************************/ + +/* Generally useful shared message routines */ H5_DLL herr_t H5SM_init(H5F_t *f, H5P_genplist_t *fc_plist, hid_t dxpl_id); +H5_DLL htri_t H5SM_can_share(H5F_t *f, hid_t dxpl_id, H5SM_master_table_t *table, + ssize_t *sohm_index_num, unsigned type_id, const void *mesg); H5_DLL htri_t H5SM_try_share(H5F_t *f, hid_t dxpl_id, unsigned type_id, - void *mesg); + void *mesg); H5_DLL herr_t H5SM_try_delete(H5F_t *f, hid_t dxpl_id, unsigned type_id, const H5O_shared_t *mesg); H5_DLL herr_t H5SM_get_info(H5F_t *f, unsigned *index_flags, unsigned *minsizes, - unsigned *list_max, unsigned *btree_min, hid_t dxpl_id); + unsigned *list_max, unsigned *btree_min, hid_t dxpl_id); H5_DLL htri_t H5SM_type_shared(H5F_t *f, unsigned type_id, hid_t dxpl_id); H5_DLL herr_t H5SM_get_fheap_addr(H5F_t *f, hid_t dxpl_id, unsigned type_id, haddr_t *fheap_addr); @@ -46,11 +54,12 @@ H5_DLL herr_t H5SM_reconstitute(H5O_shared_t *sh_mesg, H5O_fheap_id_t heap_id); H5_DLL herr_t H5SM_get_refcount(H5F_t *f, hid_t dxpl_id, unsigned type_id, const H5O_shared_t *sh_mesg, hsize_t *ref_count); +/* Debugging routines */ H5_DLL herr_t H5SM_table_debug(H5F_t *f, hid_t dxpl_id, haddr_t table_addr, - FILE *stream, int indent, int fwidth, - unsigned table_vers, unsigned num_indexes); + FILE *stream, int indent, int fwidth, unsigned table_vers, + unsigned num_indexes); H5_DLL herr_t H5SM_list_debug(H5F_t *f, hid_t dxpl_id, haddr_t list_addr, - FILE *stream, int indent, int fwidth, - unsigned list_vers, size_t num_messages); + FILE *stream, int indent, int fwidth, unsigned list_vers, size_t num_messages); + #endif /*_H5SMprivate_H*/ |