summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/H5HF.c8
-rw-r--r--src/H5HFhuge.c75
-rw-r--r--src/H5HFpkg.h2
-rw-r--r--src/H5Oattribute.c44
-rwxr-xr-xsrc/H5SM.c154
-rwxr-xr-xsrc/H5SMpkg.h13
-rwxr-xr-xsrc/H5SMprivate.h25
7 files changed, 263 insertions, 58 deletions
diff --git a/src/H5HF.c b/src/H5HF.c
index 8651a8c..b617ec9 100644
--- a/src/H5HF.c
+++ b/src/H5HF.c
@@ -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 */
diff --git a/src/H5SM.c b/src/H5SM.c
index 58a0730..3f2d9f7 100755
--- a/src/H5SM.c
+++ b/src/H5SM.c
@@ -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*/