summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/H5Fsuper.c5
-rw-r--r--src/H5O.c61
-rw-r--r--src/H5Oalloc.c4
-rw-r--r--src/H5Opublic.h2
-rw-r--r--src/H5Oshared.c14
-rw-r--r--src/H5Pfcpl.c20
-rwxr-xr-xsrc/H5SM.c84
-rwxr-xr-xsrc/H5SMbtree2.c22
-rw-r--r--src/H5SMcache.c5
-rwxr-xr-xsrc/H5SMpkg.h4
-rwxr-xr-xsrc/H5SMprivate.h2
-rw-r--r--test/tmisc.c4
-rw-r--r--test/tsohm.c2240
13 files changed, 2338 insertions, 129 deletions
diff --git a/src/H5Fsuper.c b/src/H5Fsuper.c
index 61ecacd..f1d2797 100644
--- a/src/H5Fsuper.c
+++ b/src/H5Fsuper.c
@@ -373,13 +373,14 @@ H5F_read_superblock(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc, haddr_t addr,
if(shared->sohm_addr != HADDR_UNDEF)
{
unsigned index_flags[H5SM_MAX_NUM_INDEXES] = {0};
+ unsigned minsizes[H5SM_MAX_NUM_INDEXES] = {0};
size_t sohm_l2b; /* SOHM list-to-btree cutoff */
size_t sohm_b2l; /* SOHM btree-to-list cutoff */
HDassert(shared->sohm_nindexes > 0 && shared->sohm_nindexes <= H5SM_MAX_NUM_INDEXES);
/* Read in the shared OH message information if there is any */
- if(H5SM_get_info(f, index_flags, &sohm_l2b, &sohm_b2l, dxpl_id) < 0)
+ if(H5SM_get_info(f, index_flags, minsizes, &sohm_l2b, &sohm_b2l, dxpl_id) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read SOHM table information")
/* Set values in the property list */
@@ -387,6 +388,8 @@ H5F_read_superblock(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc, haddr_t addr,
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set number of SOHM indexes");
if(H5P_set(c_plist, H5F_CRT_SHMSG_INDEX_TYPES_NAME, index_flags) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set type flags for indexes");
+ if(H5P_set(c_plist, H5F_CRT_SHMSG_INDEX_MINSIZE_NAME, minsizes) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set type flags for indexes");
if(H5P_set(c_plist, H5F_CRT_SHMSG_LIST_MAX_NAME, &sohm_l2b) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set SOHM cutoff in property list");
if(H5P_set(c_plist, H5F_CRT_SHMSG_BTREE_MIN_NAME, &sohm_b2l) < 0)
diff --git a/src/H5O.c b/src/H5O.c
index 72a5c27..253e535 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -1884,7 +1884,7 @@ H5O_modify_real(H5O_loc_t *loc, const H5O_msg_class_t *type, int overwrite,
if(overwrite < 0) {
/* Create a new message */
/* JAMES: why is sh_mesg passed in here? Is it ever used? */
- if((idx = H5O_new_mesg(loc->file, oh, &mesg_flags, type, mesg, &sh_mesg, &type, &mesg, dxpl_id, &oh_flags)) == UFAIL)
+ if((idx = H5O_new_mesg(loc->file, oh, &mesg_flags, type, mesg, &sh_mesg, &write_type, &write_mesg, dxpl_id, &oh_flags)) == UFAIL)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to create new message")
/* Set the correct sequence number for the message created */
@@ -3135,15 +3135,9 @@ H5O_delete_mesg(H5F_t *f, hid_t dxpl_id, H5O_mesg_t *mesg, hbool_t adj_link)
* We shouldn't need to do a search in the SOHM table on delete. */
if(type == H5O_MSG_SHARED)
{
- /* JAMES ugly! And not quite correct. */
- void * mesg_orig;
- if(NULL == (mesg_orig = H5O_shared_read(f, dxpl_id, mesg->native, mesg->type, NULL)))
- HGOTO_ERROR (H5E_OHDR, H5E_BADMESG, FAIL, "unable to read shared message")
-
+ /* The native message here is actually a shared message. */
if(H5SM_try_delete(f, dxpl_id, mesg->type->id, mesg->native) < 0)
HGOTO_ERROR (H5E_OHDR, H5E_CANTFREE, FAIL, "unable to delete message from SOHM table")
-
- H5O_free(mesg->type->id, mesg_orig);
}
if((type->del)(f, dxpl_id, mesg->native, adj_link) < 0)
@@ -3337,6 +3331,9 @@ H5O_iterate_real(const H5O_loc_t *loc, const H5O_msg_class_t *type, H5AC_protect
unsigned idx; /* Absolute index of current message in all messages */
unsigned sequence; /* Relative index of current message for messages of type */
H5O_mesg_t *idx_msg; /* Pointer to current message */
+ void *native_mesg; /* Native, readable message */
+ hbool_t native_mesg_alloc = FALSE; /* True if native_mesg needs to be freed */
+
herr_t ret_value = H5_ITER_CONT; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_iterate_real)
@@ -3355,23 +3352,12 @@ H5O_iterate_real(const H5O_loc_t *loc, const H5O_msg_class_t *type, H5AC_protect
/* Iterate over messages */
for(sequence = 0, idx = 0, idx_msg = &oh->mesg[0]; idx < oh->nmesgs && !ret_value; idx++, idx_msg++) {
if(type->id == idx_msg->type->id) {
- void * unshared_mesg; /* JAMES */
/*
- * Decode the message if necessary. If the message is shared then decode
- * a shared message, ignoring the message type.
+ * Decode the message if necessary.
*/
LOAD_NATIVE(loc->file, dxpl_id, idx_msg, FAIL)
- /* JAMES: test */
- if(idx_msg->flags & H5O_MSG_FLAG_SHARED)
- {
- if(NULL == (unshared_mesg = H5O_shared_read(loc->file, dxpl_id, idx_msg->native, idx_msg->type, NULL)))
- HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "unable to read shared message");
- }
- else
- unshared_mesg = idx_msg->native;
-
/* Check for making an "internal" (i.e. within the H5O package) callback */
if(internal) {
/* Call the "internal" iterator callback */
@@ -3379,19 +3365,28 @@ H5O_iterate_real(const H5O_loc_t *loc, const H5O_msg_class_t *type, H5AC_protect
break;
} /* end if */
else {
+ /* If the message is shared, get the real message it points to */
+ /* JAMES: test */
+ if(idx_msg->flags & H5O_MSG_FLAG_SHARED) {
+ if(NULL == (native_mesg = H5O_shared_read(loc->file, dxpl_id,
+ idx_msg->native, idx_msg->type, NULL)))
+ HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "unable to read shared message");
+ native_mesg_alloc = TRUE;
+ }
+ else {
+ native_mesg = idx_msg->native;
+ }
+
/* Call the iterator callback */
-/* JAMES if((ret_value = (op.app_op)(idx_msg->native, sequence, op_data)) != 0)
+ if((ret_value = (op.app_op)(native_mesg, sequence, op_data)) != 0)
break;
-*/
- if((ret_value = (op.app_op)(unshared_mesg, sequence, op_data)) != 0)
- break;
- } /* end else */
- /* JAMES again */
- if(idx_msg->flags & H5O_MSG_FLAG_SHARED)
- {
- H5O_free_real(idx_msg->type, unshared_mesg);
- }
+ /* Free the "real" message if it was allocated */
+ if(native_mesg_alloc) {
+ H5O_free(idx_msg->type->id, native_mesg);
+ native_mesg_alloc = FALSE;
+ }
+ } /* end else */
/* Check for error from iterator */
if(ret_value < 0)
@@ -3403,6 +3398,12 @@ H5O_iterate_real(const H5O_loc_t *loc, const H5O_msg_class_t *type, H5AC_protect
} /* end for */
done:
+ /* Free the native message if it was allocated */
+ if(native_mesg_alloc) {
+ H5O_free(idx_msg->type->id, native_mesg);
+ native_mesg_alloc = FALSE;
+ }
+
if(oh) {
/* Check if object header was modified */
if(oh_flags & H5AC__DIRTIED_FLAG) {
diff --git a/src/H5Oalloc.c b/src/H5Oalloc.c
index 3d728ce..ae1c5ff 100644
--- a/src/H5Oalloc.c
+++ b/src/H5Oalloc.c
@@ -663,11 +663,11 @@ H5O_alloc_new_chunk(H5F_t *f,
(found_attr < 0 ||
oh->mesg[u].raw_size < oh->mesg[found_attr].raw_size))
found_attr = u;
- } else if(H5O_LINK_ID == msg_id) {
+/* } else if(H5O_LINK_ID == msg_id) {
if(oh->mesg[u].raw_size >= cont_size &&
(found_link < 0 ||
oh->mesg[u].raw_size < oh->mesg[found_link].raw_size))
- found_link = u;
+ found_link = u; JAMES */
} else {
if(oh->mesg[u].raw_size >= cont_size &&
(found_other < 0 ||
diff --git a/src/H5Opublic.h b/src/H5Opublic.h
index 828506f..6895716 100644
--- a/src/H5Opublic.h
+++ b/src/H5Opublic.h
@@ -59,11 +59,9 @@
#define H5O_MESG_ATTR_FLAG 0x0010 /* Attribute Message. */
#define H5O_MESG_ALL_FLAG (H5O_MESG_SDSPACE_FLAG | H5O_MESG_DTYPE_FLAG | H5O_MESG_FILL_FLAG | H5O_MESG_PLINE_FLAG | H5O_MESG_ATTR_FLAG)
-
/*******************/
/* Public Typedefs */
/*******************/
-
/* A struct that's part of the H5G_stat_t routine (deprecated) */
typedef struct H5O_stat_t {
hsize_t size; /* Total size of object header in file */
diff --git a/src/H5Oshared.c b/src/H5Oshared.c
index fa5f0d5..032e2b0 100644
--- a/src/H5Oshared.c
+++ b/src/H5Oshared.c
@@ -109,7 +109,7 @@ H5O_shared_read(H5F_t *f, hid_t dxpl_id, const H5O_shared_t *shared,
{
H5HF_t *fheap = NULL;
unsigned char *buf = NULL; /* Pointer to raw message in heap */
- void * native_mesg = NULL; /* Only used for messages shared in heap */
+ void *native_mesg = NULL; /* Used for messages shared in heap */
void *ret_value = NULL; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_shared_read)
@@ -118,6 +118,7 @@ H5O_shared_read(H5F_t *f, hid_t dxpl_id, const H5O_shared_t *shared,
HDassert(f);
HDassert(shared);
HDassert(type);
+ HDassert(type->set_share);
/* This message could have a heap ID (SOHM) or the address of an object
* header on disk (named datatype)
@@ -153,14 +154,9 @@ H5O_shared_read(H5F_t *f, hid_t dxpl_id, const H5O_shared_t *shared,
if(NULL == (native_mesg = H5O_decode(f, dxpl_id, buf, type->id)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, NULL, "can't decode shared message.")
- /* Make sure that this message is labeled as shared */
- HDassert(type->set_share);
- if(((type->set_share)(f, native_mesg, shared)) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to set sharing information")
-
- /* Get a copy of the message to return */
- if(NULL == (ret_value = H5O_copy(type->id, native_mesg, mesg)))
- HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy message")
+ /* Copy this message to the user's buffer */
+ if(NULL == (ret_value = (type->copy) (native_mesg, mesg, 0)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to copy message to user space")
} /* end if */
else {
HDassert(shared->flags & H5O_COMMITTED_FLAG);
diff --git a/src/H5Pfcpl.c b/src/H5Pfcpl.c
index da8e0fa..d487f29 100644
--- a/src/H5Pfcpl.c
+++ b/src/H5Pfcpl.c
@@ -77,7 +77,6 @@
#define H5F_CRT_SHMSG_NINDEXES_DEF (0)
#define H5F_CRT_SHMSG_INDEX_TYPES_SIZE sizeof(unsigned[H5SM_MAX_NUM_INDEXES])
#define H5F_CRT_SHMSG_INDEX_TYPES_DEF {0,0,0,0,0,0}
-/* JAMES #define H5F_CRT_SHMSG_INDEX_TYPES_DEF { H5O_MESG_FILL_FLAG |H5O_MESG_SDSPACE_FLAG,H5O_MESG_ATTR_FLAG, 0, H5O_MESG_DTYPE_FLAG,0,H5O_MESG_PLINE_FLAG} */
#define H5F_CRT_SHMSG_INDEX_MINSIZE_SIZE sizeof(unsigned[H5SM_MAX_NUM_INDEXES])
#define H5F_CRT_SHMSG_INDEX_MINSIZE_DEF {250,250,250,250,250,250}
/* Definitions for shared object header list/btree phase change cutoffs */
@@ -158,11 +157,11 @@ H5P_fcrt_reg_prop(H5P_genclass_t *pclass)
unsigned freespace_ver = H5F_CRT_FREESPACE_VERS_DEF;/* Default free space version # */
unsigned objectdir_ver = H5F_CRT_OBJ_DIR_VERS_DEF; /* Default object directory version # */
unsigned sharedheader_ver = H5F_CRT_SHARE_HEAD_VERS_DEF; /* Default shared header message version # */
- unsigned num_sohm_indexes = H5F_CRT_SHMSG_NINDEXES_DEF;
- unsigned sohm_index_flags[H5SM_MAX_NUM_INDEXES] = H5F_CRT_SHMSG_INDEX_TYPES_DEF;
- unsigned sohm_index_minsizes[H5SM_MAX_NUM_INDEXES] = H5F_CRT_SHMSG_INDEX_MINSIZE_DEF;
- unsigned sohm_list_max = H5F_CRT_SHMSG_LIST_MAX_DEF;
- unsigned sohm_btree_min = H5F_CRT_SHMSG_BTREE_MIN_DEF;
+ unsigned num_sohm_indexes = H5F_CRT_SHMSG_NINDEXES_DEF;
+ unsigned sohm_index_flags[H5SM_MAX_NUM_INDEXES] = H5F_CRT_SHMSG_INDEX_TYPES_DEF;
+ unsigned sohm_index_minsizes[H5SM_MAX_NUM_INDEXES] = H5F_CRT_SHMSG_INDEX_MINSIZE_DEF;
+ unsigned sohm_list_max = H5F_CRT_SHMSG_LIST_MAX_DEF;
+ unsigned sohm_btree_min = H5F_CRT_SHMSG_BTREE_MIN_DEF;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5P_fcrt_reg_prop)
@@ -798,7 +797,7 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5Pget_shared_imesg_nindexes
+ * Function: H5Pget_shared_mesg_nindexes
*
* Purpose: Get the number of Shared Object Header Message (SOHM)
* indexes specified in this property list.
@@ -852,7 +851,6 @@ H5Pset_shared_mesg_index(hid_t plist_id, unsigned index_num, unsigned mesg_type_
unsigned nindexes; /* Number of SOHM indexes */
unsigned type_flags[H5SM_MAX_NUM_INDEXES]; /* Array of mesg_type_flags*/
unsigned minsizes[H5SM_MAX_NUM_INDEXES]; /* Array of min_mesg_sizes*/
- unsigned x;
herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_API(H5Pset_shared_mesg_index, FAIL);
@@ -885,12 +883,6 @@ H5Pset_shared_mesg_index(hid_t plist_id, unsigned index_num, unsigned mesg_type_
type_flags[index_num - 1] = mesg_type_flags;
minsizes[index_num - 1] = min_mesg_size;
- /* Check that type flags does introduce any duplicate values */
- for(x=0; x < nindexes; ++x) {
- if(x != (index_num - 1) && (type_flags[index_num - 1] & type_flags[x]) != 0)
- HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't assign the same flag to different indexes")
- }
-
/* Write arrays back to plist */
if(H5P_set(plist, H5F_CRT_SHMSG_INDEX_TYPES_NAME, type_flags) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set index type flags");
diff --git a/src/H5SM.c b/src/H5SM.c
index 2984805..dd5b1d2 100755
--- a/src/H5SM.c
+++ b/src/H5SM.c
@@ -104,6 +104,8 @@ H5SM_init(H5F_t *f, H5P_genplist_t * fc_plist, hid_t dxpl_id)
unsigned num_indexes;
unsigned list_to_btree, btree_to_list;
unsigned index_type_flags[H5SM_MAX_NUM_INDEXES];
+ unsigned minsizes[H5SM_MAX_NUM_INDEXES];
+ unsigned type_flags_used;
ssize_t x;
hsize_t table_size;
herr_t ret_value=SUCCEED;
@@ -120,13 +122,28 @@ H5SM_init(H5F_t *f, H5P_genplist_t * fc_plist, hid_t dxpl_id)
/* Get information from fcpl */
if(H5P_get(fc_plist, H5F_CRT_SHMSG_NINDEXES_NAME, &num_indexes)<0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get SOHM information")
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get number of indexes")
if(H5P_get(fc_plist, H5F_CRT_SHMSG_INDEX_TYPES_NAME, &index_type_flags)<0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get SOHM information")
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get SOHM type flags")
if(H5P_get(fc_plist, H5F_CRT_SHMSG_LIST_MAX_NAME, &list_to_btree)<0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get SOHM information")
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get SOHM list maximum")
if(H5P_get(fc_plist, H5F_CRT_SHMSG_BTREE_MIN_NAME, &btree_to_list)<0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get SOHM information")
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get SOHM btree minimum")
+ if(H5P_get(fc_plist, H5F_CRT_SHMSG_INDEX_MINSIZE_NAME, &minsizes) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get SOHM message min sizes")
+
+ /* Verify that values are valid */
+ if(num_indexes > H5SM_MAX_NUM_INDEXES)
+ HGOTO_ERROR(H5E_PLIST, H5E_BADRANGE, FAIL, "number of indexes in property list is too large")
+
+ /* Check that type flags weren't duplicated anywhere */
+ type_flags_used = 0;
+ for(x=0; x<num_indexes; ++x) {
+ if(index_type_flags[x] & type_flags_used) {
+ HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "the same shared message type flag is assigned to more than one index")
+ }
+ type_flags_used |= index_type_flags[x];
+ }
/* Set version and number of indexes in table and in superblock.
* Right now we just use one byte to hold the number of indexes.
@@ -153,12 +170,12 @@ H5SM_init(H5F_t *f, H5P_genplist_t * fc_plist, hid_t dxpl_id)
/* Initialize all of the indexes, but don't allocate space for them to
* hold messages until we actually need to write to them.
*/
- /* JAMES: currently all indexes use the same values */
for(x=0; x<table->num_indexes; x++)
{
table->indexes[x].btree_to_list = btree_to_list;
table->indexes[x].list_to_btree = list_to_btree;
table->indexes[x].mesg_types = index_type_flags[x];
+ table->indexes[x].min_mesg_size = minsizes[x];
table->indexes[x].index_addr = HADDR_UNDEF;
table->indexes[x].heap_addr = HADDR_UNDEF;
table->indexes[x].num_messages = 0;
@@ -422,12 +439,13 @@ H5SM_create_list(H5F_t *f, H5SM_index_header_t * header, hid_t dxpl_id)
if((list->messages = H5FL_ARR_MALLOC(H5SM_sohm_t, num_entries)) == NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, "file allocation failed for SOHM list")
- /* Initialize list */
+ /* Initialize messages in list */
+ HDmemset(list->messages, 0, sizeof(H5SM_sohm_t) * num_entries);
+
/* JAMES: would making fewer operations out of this make it faster? */
- for(x=0; x<num_entries; x++)
- {
- list->messages[x].ref_count=0;
- list->messages[x].fheap_id=0;
+ for(x=0; x<num_entries; x++) {
+// list->messages[x].ref_count=0;
+// list->messages[x].fheap_id=0;
list->messages[x].hash=H5O_HASH_UNDEF;
}
@@ -493,7 +511,7 @@ H5SM_try_share(H5F_t *f, hid_t dxpl_id, unsigned type_id, void *mesg)
H5SM_master_table_t *table = NULL;
unsigned cache_flags = H5AC__NO_FLAGS_SET;
ssize_t index_num;
- herr_t ret_value = SUCCEED;
+ herr_t ret_value = TRUE;
FUNC_ENTER_NOAPI(H5SM_try_share, FAIL)
/* Check whether this message ought to be shared or not */
@@ -501,14 +519,6 @@ H5SM_try_share(H5F_t *f, hid_t dxpl_id, unsigned type_id, void *mesg)
if(f->shared->sohm_addr == HADDR_UNDEF)
HGOTO_DONE(FALSE);
- /* If the message isn't big enough, don't bother sharing it */
- if((mesg_size = H5O_mesg_size(type_id, f, mesg, 0)) == 0)
- HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "unable to get OH message size")
- if(mesg_size < 50) /* JAMES: arbitrary value. Make this per-index, along with index sizes? */
- HGOTO_DONE(FALSE);
-
- /* JAMES_HEAP: skip this step if it's already shared--just increment the refcount on the message itself */
-
/* Type-specific checks */
/* JAMES: should this go here? Should there be a "can share" callback? */
if(type_id == H5O_DTYPE_ID)
@@ -542,7 +552,13 @@ H5SM_try_share(H5F_t *f, hid_t dxpl_id, unsigned type_id, void *mesg)
if(index_num < 0)
HGOTO_DONE(FALSE);
- /* At this point, the message should definitely be shared. */
+ /* If the message isn't big enough, don't bother sharing it */
+ if((mesg_size = H5O_mesg_size(type_id, f, mesg, 0)) <0)
+ 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. */
/* If the index hasn't been allocated yet, create it */
if(table->indexes[index_num].index_addr == HADDR_UNDEF)
@@ -674,16 +690,19 @@ H5SM_write_mesg(H5F_t *f, hid_t dxpl_id, H5SM_index_header_t *header,
/* JAMES: wrap this in a function call? */
- /* Encode the message and get its size */
+ /* Encode the message and get its size */ /* JAMES: already have this */
if((mesg_size = H5O_raw_size(type_id, f, mesg)) == 0)
HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "unable to get size of message")
+ /* JAMES: fix memory problem */
+ shared.u.heap_id = 0;
+
if(H5HF_insert(fheap, dxpl_id, mesg_size, key.encoding, &(shared.u.heap_id)) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "unable to insert message into fractal heap")
/* Check whether the list has grown enough that it needs to become a B-tree */
/* JAMES: make this a separate function */
- if(header->index_type == H5SM_LIST && header->num_messages > header->list_to_btree)
+ if(header->index_type == H5SM_LIST && header->num_messages >= header->list_to_btree)
{
hsize_t list_size; /* Size of list on disk */
haddr_t tree_addr;
@@ -788,7 +807,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5SM_try_delete(H5F_t *f, hid_t dxpl_id, unsigned type_id, const H5O_shared_t *mesg)
+H5SM_try_delete(H5F_t *f, hid_t dxpl_id, unsigned type_id, const H5O_shared_t *sh_mesg)
{
H5SM_master_table_t *table = NULL;
unsigned cache_flags = H5AC__NO_FLAGS_SET;
@@ -797,10 +816,10 @@ H5SM_try_delete(H5F_t *f, hid_t dxpl_id, unsigned type_id, const H5O_shared_t *m
FUNC_ENTER_NOAPI(H5SM_try_delete, FAIL)
HDassert(f);
- HDassert(mesg);
+ HDassert(sh_mesg);
/* Make sure SHARED_IN_HEAP flag is set; if not, there's no message to delete */
- if(0 == (mesg->flags & H5O_SHARED_IN_HEAP_FLAG))
+ if(0 == (sh_mesg->flags & H5O_SHARED_IN_HEAP_FLAG))
HGOTO_DONE(SUCCEED);
HDassert(f->shared->sohm_addr != HADDR_UNDEF);
@@ -814,7 +833,7 @@ H5SM_try_delete(H5F_t *f, hid_t dxpl_id, unsigned type_id, const H5O_shared_t *m
HGOTO_ERROR(H5E_SOHM, H5E_NOTFOUND, FAIL, "unable to find correct SOHM index")
/* JAMES: this triggers some warning on heping. "overflow in implicit constant conversion" */
- if(H5SM_delete_from_index(f, dxpl_id, &(table->indexes[index_num]), type_id, mesg, &cache_flags) < 0)
+ if(H5SM_delete_from_index(f, dxpl_id, &(table->indexes[index_num]), type_id, sh_mesg, &cache_flags) < 0)
HGOTO_ERROR(H5E_SOHM, H5E_CANTDELETE, FAIL, "unable to delete mesage from SOHM index")
done:
@@ -895,7 +914,6 @@ H5SM_delete_from_index(H5F_t *f, hid_t dxpl_id, H5SM_index_header_t *header, uns
HDassert(mesg);
HDassert(cache_flags);
HDassert(mesg->flags & H5O_SHARED_IN_HEAP_FLAG);
-
/* Open the heap that this message is in */
if(NULL == (fheap=H5HF_open(f, dxpl_id, header->heap_addr)))
@@ -957,6 +975,8 @@ H5SM_delete_from_index(H5F_t *f, hid_t dxpl_id, H5SM_index_header_t *header, uns
if(header->index_type == H5SM_LIST)
{
list->messages[list_pos].hash = H5O_HASH_UNDEF;
+ list->messages[list_pos].fheap_id = 0;
+ list->messages[list_pos].ref_count = 0; /* Just in case */
}
else
{
@@ -973,7 +993,7 @@ H5SM_delete_from_index(H5F_t *f, hid_t dxpl_id, H5SM_index_header_t *header, uns
*/
/* JAMES: there's an off-by-one error here */
/* JAMES: make this a separate function */
- if(header->num_messages < header->btree_to_list)
+ if(header->index_type == H5SM_BTREE && header->num_messages < header->btree_to_list)
{
/* Remember the btree address for this index; we'll overwrite the
* address in the index header
@@ -1037,8 +1057,8 @@ done:
*
*-------------------------------------------------------------------------
*/
-herr_t H5SM_get_info(H5F_t *f, unsigned *index_flags, size_t *list_to_btree,
- size_t *btree_to_list, hid_t dxpl_id)
+herr_t H5SM_get_info(H5F_t *f, unsigned *index_flags, unsigned *minsizes,
+ size_t *list_to_btree, size_t *btree_to_list, hid_t dxpl_id)
{
H5SM_master_table_t *table = NULL;
haddr_t table_addr;
@@ -1070,9 +1090,9 @@ herr_t H5SM_get_info(H5F_t *f, unsigned *index_flags, size_t *list_to_btree,
*btree_to_list = table->indexes[0].btree_to_list;
/* Get information about the individual SOHM indexes */
- for(i=0; i<table->num_indexes; ++i)
- {
+ for(i=0; i<table->num_indexes; ++i) {
index_flags[i] = table->indexes[i].mesg_types;
+ minsizes[i] = table->indexes[i].min_mesg_size;
}
done:
diff --git a/src/H5SMbtree2.c b/src/H5SMbtree2.c
index 666ead7..28401d9 100755
--- a/src/H5SMbtree2.c
+++ b/src/H5SMbtree2.c
@@ -89,11 +89,12 @@ const H5B2_class_t H5SM_INDEX[1]={{ /* B-tree class information */
herr_t
H5SM_message_compare(const H5SM_mesg_key_t *rec1, const H5SM_sohm_t *rec2)
{
- herr_t hash_diff;
+ int64_t hash_diff; /* Has to be able to hold two 32-bit values */
herr_t ret_value=0;
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_message_compare)
- hash_diff = (herr_t) (rec1->hash - rec2->hash);
+ hash_diff = rec1->hash;
+ hash_diff -= rec2->hash;
/* If the hash values match, make sure the messages are really the same */
if(0 == hash_diff) {
@@ -122,8 +123,13 @@ H5SM_message_compare(const H5SM_mesg_key_t *rec1, const H5SM_sohm_t *rec2)
ret_value = HDmemcmp(rec1->encoding, buf2, rec1->encoding_size);
}
}
- else
- ret_value = hash_diff;
+ else {
+ /* Compress 64-bit hash_diff to fit in an herr_t */
+ if(hash_diff > 0)
+ ret_value = 1;
+ else
+ ret_value = -1;
+ }
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5SM_message_compare */
@@ -319,9 +325,9 @@ H5SM_incr_ref(void *record, void *op_data, hbool_t *changed)
* remove the record from the B-tree even if the refcount
* reaches zero.
*
- * The new refcount is returned through op_data. If this is
- * zero, the calling function should remove this record from
- * the B-tree.
+ * The new message is returned through op_data. If its
+ * reference count is zero, the calling function should
+ * remove this record from the B-tree.
*
* Return: Non-negative on success
* Negative on failure
@@ -345,7 +351,7 @@ H5SM_decr_ref(void *record, void *op_data, hbool_t *changed)
*changed = TRUE;
if(op_data)
- *(hsize_t *)op_data = message->ref_count;
+ *(H5SM_sohm_t *)op_data = *message;
FUNC_LEAVE_NOAPI(SUCCEED)
}
diff --git a/src/H5SMcache.c b/src/H5SMcache.c
index e21757e..70b7b56 100644
--- a/src/H5SMcache.c
+++ b/src/H5SMcache.c
@@ -139,14 +139,14 @@ H5SM_flush_table(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5SM_ma
HDmemcpy(p, H5SM_TABLE_MAGIC, (size_t)H5SM_TABLE_SIZEOF_MAGIC);
p += H5SM_TABLE_SIZEOF_MAGIC;
- *p++ = H5SM_MASTER_TABLE_VERSION; /* Version */
+ *p++ = table->version; /* Version */
/* Encode each index header */
for(x=0; x<table->num_indexes; ++x) {
*p++ = table->indexes[x].index_type; /* Is message index a list or a B-tree? */
UINT16ENCODE(p, table->indexes[x].mesg_types); /* Type of messages in the index */
-
+ UINT32ENCODE(p, table->indexes[x].min_mesg_size); /* Minimum size of message to share */
UINT16ENCODE(p, table->indexes[x].list_to_btree); /* List cutoff; fewer than this number and index becomes a list */
UINT16ENCODE(p, table->indexes[x].btree_to_list); /* B-tree cutoff; more than this number and index becomes a B-tree */
UINT16ENCODE(p, table->indexes[x].num_messages); /* Number of messages shared */
@@ -239,6 +239,7 @@ H5SM_load_table(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *udata1
table->indexes[x].index_type= *p++; /* type of the index (list or B-tree) */
UINT16DECODE(p, table->indexes[x].mesg_types);
+ UINT32DECODE(p, table->indexes[x].min_mesg_size);
UINT16DECODE(p, table->indexes[x].list_to_btree);
UINT16DECODE(p, table->indexes[x].btree_to_list);
UINT16DECODE(p, table->indexes[x].num_messages);
diff --git a/src/H5SMpkg.h b/src/H5SMpkg.h
index 752ce84..51c6c1f 100755
--- a/src/H5SMpkg.h
+++ b/src/H5SMpkg.h
@@ -40,7 +40,7 @@
#define H5SM_SOHM_ENTRY_SIZE(f) (4 /* Hash value */ \
+ 4 /* reference count*/ \
- + 8) /* JAMES: size of hash value on disk */
+ + 8) /* JAMES: size of heap ID on disk */
#define H5SM_TABLE_SIZE(f) ( H5SM_TABLE_SIZEOF_MAGIC \
+ 1 /* Table version */ \
@@ -48,6 +48,7 @@
#define H5SM_INDEX_HEADER_SIZE(f) (1 /* Whether index is a list or B-tree */ \
+ 2 /* Type of messages stored in the index */ \
+ + 4 /* Minimum size of messages to share */ \
+ (3 * 2) /* B-tree cutoff, list cutoff, # of shared messages */ \
+ H5F_SIZEOF_ADDR(f) /* Location of list or B-tree */ \
+ H5F_SIZEOF_ADDR(f)) /* Address of heap */
@@ -115,6 +116,7 @@ typedef struct {
/* Typedef for a SOHM index header */
typedef struct {
unsigned mesg_types; /* Bit flag vector of message types */
+ size_t min_mesg_size; /* number of messages being tracked */
size_t list_to_btree; /* >= this many messages, index with a B-tree */
size_t btree_to_list; /* <= this many messages, index with a list again */
size_t num_messages; /* number of messages being tracked */
diff --git a/src/H5SMprivate.h b/src/H5SMprivate.h
index 5d75213..4430822 100755
--- a/src/H5SMprivate.h
+++ b/src/H5SMprivate.h
@@ -46,7 +46,7 @@ H5_DLL herr_t H5SM_init(H5F_t *f, H5P_genplist_t *fc_plist, hid_t dxpl_id);
H5_DLL htri_t H5SM_try_share(H5F_t *f, hid_t dxpl_id, unsigned type_id,
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,
+H5_DLL herr_t H5SM_get_info(H5F_t *f, unsigned *index_flags, unsigned *minsizes,
size_t *list_to_btree, size_t *btree_to_list, hid_t dxpl_id);
H5_DLL haddr_t H5SM_get_fheap_addr(H5F_t *f, unsigned type_id, hid_t dxpl_id);
diff --git a/test/tmisc.c b/test/tmisc.c
index 7aad459..3625681 100644
--- a/test/tmisc.c
+++ b/test/tmisc.c
@@ -159,7 +159,7 @@ typedef struct
#define MISC11_SYM_LK 8
#define MISC11_SYM_IK 32
#define MISC11_ISTORE_IK 64
-#define MISC11_NINDEXES 1
+#define MISC11_NINDEXES 1
/* Definitions for misc. test #12 */
#define MISC12_FILE "tmisc12.h5"
@@ -1839,7 +1839,7 @@ test_misc11(void)
CHECK(ret, FAIL, "H5Pset_istore_k");
ret=H5Pset_shared_mesg_nindexes(fcpl,MISC11_NINDEXES);
- CHECK(ret, FAIL, "H5Pset_istore_k");
+ CHECK(ret, FAIL, "H5Pset_shared_mesg");
/* Creating a file with the non-default file creation property list should
* create a version 1 superblock
diff --git a/test/tsohm.c b/test/tsohm.c
index c1dcbc5..482b4af 100644
--- a/test/tsohm.c
+++ b/test/tsohm.c
@@ -27,13 +27,16 @@
*/
/* JAMES: get these three from default fcpl */
#define MAX_INDEXES 6
+
/* Default SOHM values */
#define DEF_NUM_INDEXES 0
const unsigned def_type_flags[MAX_INDEXES] = {0,0,0,0,0,0};
+const unsigned def_minsizes[MAX_INDEXES] = {250,250,250,250,250,250};
#define DEF_L2B 50
#define DEF_B2L 40
/* Non-default SOHM values for testing */
+/* JAMES: make these defined in function */
#define TEST_NUM_INDEXES 4
const unsigned test_type_flags[MAX_INDEXES] =
{H5O_MESG_FILL_FLAG,
@@ -41,11 +44,103 @@ const unsigned test_type_flags[MAX_INDEXES] =
H5O_MESG_SDSPACE_FLAG,
H5O_MESG_PLINE_FLAG,
0, 0};
+const unsigned test_minsizes[MAX_INDEXES] = {0, 2, 40, 100, 3, 1000};
#define TEST_L2B 65
#define TEST_B2L 64
#define FILENAME "tsohm.h5"
+#define NAME_BUF_SIZE 512
+
+/* How much overhead counts as "not much" when converting B-trees, etc. */
+#define OVERHEAD_ALLOWED 1.1
+
+#define NUM_DATASETS 10
+#define NUM_ATTRIBUTES 100
+
+typedef struct dtype1_struct {
+ int i1;
+ char str[10]; /* JAMES */
+ int i2;
+ int i3;
+ int i4;
+ int i5;
+ int i6;
+ int i7;
+ int i8;
+ float f1;
+} dtype1_struct;
+#define DTYPE2_SIZE 1024
+const char *DSETNAME[] = {
+ "dataset0", "dataset1",
+ "dataset2", "dataset3",
+ "dataset4", "dataset5",
+ "dataset6", "dataset7",
+ "dataset8", "dataset9",
+ "dataset10", "dataset11",
+ NULL
+};
+const char *EXTRA_DSETNAME[] = {
+ "ex_dataset0", "ex_dataset1",
+ "ex_dataset2", "ex_dataset3",
+ "ex_dataset4", "ex_dataset5",
+ "ex_dataset6", "ex_dataset7",
+ "ex_dataset8", "ex_dataset9",
+ "ex_dataset10", "ex_dataset11",
+ "ex_dataset12", "ex_dataset13",
+ "ex_dataset14", "ex_dataset15",
+ "ex_dataset16", "ex_dataset17",
+ "ex_dataset18", "ex_dataset19",
+ NULL
+};
+#define SOHM_HELPER_NUM_EX_DSETS 20
+typedef struct complex_t {
+ double re;
+ double im;
+} complex_t;
+#define ENUM_NUM_MEMBS 20
+const char *ENUM_NAME[] = {
+ "enum_member0", "enum_member1",
+ "enum_member2", "enum_member3",
+ "enum_member4", "enum_member5",
+ "enum_member6", "enum_member7",
+ "enum_member8", "enum_member9",
+ "enum_member10", "enum_member11",
+ "enum_member12", "enum_member13",
+ "enum_member14", "enum_member15",
+ "enum_member16", "enum_member17",
+ "enum_member18", "enum_member19",
+ NULL
+};
+const int ENUM_VAL[] = {
+ 0, 13,
+ -500, 63,
+ 64, -64,
+ 65, 2048,
+ 1, 2,
+ -1, 7,
+ 130, -5000,
+ 630, 640,
+ -640, 650,
+ 20480, 10,
+ -1001, -10
+};
+#define SIZE2_RANK1 10
+#define SIZE2_RANK2 20
+#define SIZE2_DIMS {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}
+
+#define LONG_STRING "00 index. A long string used for testing. To create new strings, set the first two characters to be some ASCII number other than 00, such as 01."
+
+/* Struct returned from size2_helper function */
+typedef struct size2_helper_struct {
+ h5_stat_size_t empty_size;
+ h5_stat_size_t first_dset;
+ h5_stat_size_t dsets1;
+ h5_stat_size_t dsets2;
+ h5_stat_size_t interleaved;
+ h5_stat_size_t attrs1;
+ h5_stat_size_t attrs2;
+} size2_helper_struct;
/****************************************************************
**
@@ -54,12 +149,13 @@ const unsigned test_type_flags[MAX_INDEXES] =
**
****************************************************************/
static void check_fcpl_values(hid_t fcpl_id, const unsigned nindexes_in,
- const unsigned *flags_in, size_t l2b, size_t b2l)
+ const unsigned *flags_in, const unsigned *minsizes_in,
+ size_t l2b, size_t b2l)
{
unsigned num_indexes;
unsigned index_flags, min_mesg_size;
- unsigned list_size, btree_size;
- unsigned x;
+ size_t list_size, btree_size;
+ unsigned x;
herr_t ret;
/* Verify number of indexes is set to default */
@@ -67,7 +163,7 @@ static void check_fcpl_values(hid_t fcpl_id, const unsigned nindexes_in,
CHECK_I(ret, "H5Pget_shared_mesg_nindexes");
VERIFY(num_indexes, nindexes_in, "H5Pget_shared_mesg_nindexes");
- /* Verify index flags are set to default */
+ /* Verify index flags and minsizes are set */
for(x=1; x<=num_indexes; ++x)
{
ret = H5Pget_shared_mesg_index(fcpl_id, x, &index_flags, &min_mesg_size);
@@ -78,9 +174,9 @@ static void check_fcpl_values(hid_t fcpl_id, const unsigned nindexes_in,
/* Check list-to-btree and btree-to-list values */
ret = H5Pget_shared_mesg_phase_change(fcpl_id, &list_size, &btree_size);
- CHECK_I(ret, "H5Pget_shared_mesg_phase_change");
- VERIFY(list_size, l2b, "H5Pget_shared_mesg_phase_change");
- VERIFY(btree_size, b2l, "H5Pget_shared_mesg_phase_change");
+ CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
+ VERIFY(list_size, l2b, "H5Pset_shared_mesg_phase_change");
+ VERIFY(btree_size, b2l, "H5Pset_shared_mesg_phase_change");
}
@@ -95,7 +191,7 @@ static void test_sohm_fcpl(void)
hid_t fcpl_id = -1;
hid_t fcpl2_id = -1;
unsigned x;
- unsigned bad_flags[MAX_INDEXES];
+ char filename[NAME_BUF_SIZE];
herr_t ret; /* Generic return value */
/* Output message about test being performed */
@@ -105,18 +201,20 @@ static void test_sohm_fcpl(void)
CHECK_I(fcpl_id, "H5Pcreate");
/* Verify fcpl values */
- check_fcpl_values(fcpl_id, DEF_NUM_INDEXES, def_type_flags, DEF_L2B, DEF_B2L);
+ check_fcpl_values(fcpl_id, DEF_NUM_INDEXES, def_type_flags, def_minsizes, DEF_L2B, DEF_B2L);
/* Create a file with this fcpl and make sure that all the values can be
* retrieved.
*/
- fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
+ h5_fixname(FILENAME, H5P_DEFAULT, filename, sizeof filename);
+ fid = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
CHECK_I(fid, "H5Fcreate");
+
fcpl2_id = H5Fget_create_plist(fid);
CHECK_I(fcpl2_id, "H5Fcreate");
/* Verify fcpl values */
- check_fcpl_values(fcpl2_id, DEF_NUM_INDEXES, def_type_flags, DEF_L2B, DEF_B2L);
+ check_fcpl_values(fcpl2_id, DEF_NUM_INDEXES, def_type_flags, def_minsizes, DEF_L2B, DEF_B2L);
ret = H5Pclose(fcpl2_id);
CHECK_I(ret, "H5Pclose");
@@ -126,14 +224,14 @@ static void test_sohm_fcpl(void)
*/
ret = H5Fclose(fid);
CHECK_I(ret, "H5Fclose");
- fid = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT);
+ fid = H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT);
CHECK_I(fid, "H5Fopen");
fcpl2_id = H5Fget_create_plist(fid);
CHECK_I(ret, "H5Fcreate");
/* Verify fcpl values */
- check_fcpl_values(fcpl_id, DEF_NUM_INDEXES, def_type_flags, DEF_L2B, DEF_B2L);
+ check_fcpl_values(fcpl2_id, DEF_NUM_INDEXES, def_type_flags, def_minsizes, DEF_L2B, DEF_B2L);
/* Clean up */
ret = H5Pclose(fcpl2_id);
@@ -153,23 +251,23 @@ static void test_sohm_fcpl(void)
CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
for(x=1; x<=TEST_NUM_INDEXES; ++x)
{
- ret = H5Pset_shared_mesg_index(fcpl_id, x, test_type_flags[x-1], 15 /* JAMES */);
+ ret = H5Pset_shared_mesg_index(fcpl_id, x, test_type_flags[x-1], test_minsizes[x-1]);
CHECK_I(ret, "H5Pset_shared_mesg_index");
}
ret = H5Pset_shared_mesg_phase_change(fcpl_id, TEST_L2B, TEST_B2L);
CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
- check_fcpl_values(fcpl_id, TEST_NUM_INDEXES, test_type_flags, TEST_L2B, TEST_B2L);
+ check_fcpl_values(fcpl_id, TEST_NUM_INDEXES, test_type_flags, test_minsizes, TEST_L2B, TEST_B2L);
/* Use the fcpl to create a file and get it back again */
- fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
+ fid = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
CHECK_I(fid, "H5Fcreate");
fcpl2_id = H5Fget_create_plist(fid);
CHECK_I(fcpl2_id, "H5Fcreate");
/* Verify fcpl values */
- check_fcpl_values(fcpl_id, TEST_NUM_INDEXES, test_type_flags, TEST_L2B, TEST_B2L);
+ check_fcpl_values(fcpl2_id, TEST_NUM_INDEXES, test_type_flags, test_minsizes, TEST_L2B, TEST_B2L);
ret = H5Pclose(fcpl2_id);
CHECK_I(ret, "H5Pclose");
@@ -179,14 +277,14 @@ static void test_sohm_fcpl(void)
*/
ret = H5Fclose(fid);
CHECK_I(ret, "H5Fclose");
- fid = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT);
+ fid = H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT);
CHECK_I(fid, "H5Fopen");
fcpl2_id = H5Fget_create_plist(fid);
CHECK_I(ret, "H5Fcreate");
/* Verify fcpl values */
- check_fcpl_values(fcpl_id, TEST_NUM_INDEXES, test_type_flags, TEST_L2B, TEST_B2L);
+ check_fcpl_values(fcpl2_id, TEST_NUM_INDEXES, test_type_flags, test_minsizes, TEST_L2B, TEST_B2L);
/* Clean up */
ret = H5Pclose(fcpl2_id);
@@ -214,9 +312,13 @@ static void test_sohm_fcpl(void)
ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_MESG_FILL_FLAG, 15 /* JAMES */);
CHECK_I(ret, "H5Pset_shared_mesg_index");
ret = H5Pset_shared_mesg_index(fcpl_id, 2, H5O_MESG_FILL_FLAG, 15 /* JAMES */);
- VERIFY(ret, -1, "H5Pset_shared_mesg_index");
+ CHECK_I(ret, "H5Pset_shared_mesg_index");
+ fid = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
+ VERIFY(fid, -1, "H5Fcreate");
ret = H5Pset_shared_mesg_index(fcpl_id, 2, H5O_MESG_DTYPE_FLAG | H5O_MESG_FILL_FLAG, 15 /* JAMES */);
- VERIFY(ret, -1, "H5Pset_shared_mesg_index");
+ CHECK_I(ret, "H5Pset_shared_mesg_index");
+ fid = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
+ VERIFY(fid, -1, "H5Fcreate");
/* Test list/btree cutoffs. We can set these to any positive value,
* but if the list max is less than the btree min we'll get an error
@@ -228,11 +330,14 @@ static void test_sohm_fcpl(void)
/* Actually, the list max can be exactly 1 greater than the
* btree min, but no more. Also, the errors above shouldn't
- * have corrupted the fcpl.
+ * have corrupted the fcpl, although we do need to reset the
+ * second index that we changed above.
*/
+ ret = H5Pset_shared_mesg_index(fcpl_id, 2, test_type_flags[1], 15 /* JAMES */);
+ CHECK_I(ret, "H5Pset_shared_mesg_index");
ret = H5Pset_shared_mesg_phase_change(fcpl_id, 10, 11);
CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
- fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
+ fid = H5Fcreate(filename, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
CHECK_I(fid, "H5Fcreate");
/* Clean up */
@@ -242,10 +347,2091 @@ static void test_sohm_fcpl(void)
CHECK_I(ret, "H5Fclose");
}
+
+/*-------------------------------------------------------------------------
+ * Function: make_dtype_1
+ *
+ * Purpose: Creates a complicated datatype for use in testing
+ * shared object header messages. The important thing is that
+ * the datatypes must take a lot of space to store on disk.
+ *
+ * Return: Success: datatype ID (should be closed by calling function)
+ * Failure: negative
+ *
+ * Programmer: James Laird
+ * Saturday, August 26, 2006
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+make_dtype_1()
+{
+ hid_t dtype1_id = -1;
+ hid_t str_id = -1;
+
+ /* Create compound datatype. If the user asked for it, check hash value at each step */
+ if((dtype1_id = H5Tcreate( H5T_COMPOUND, sizeof(struct dtype1_struct)))<0) TEST_ERROR
+
+ if(H5Tinsert(dtype1_id,"i1",HOFFSET(struct dtype1_struct,i1),H5T_NATIVE_INT)<0) TEST_ERROR
+
+ str_id = H5Tcopy(H5T_C_S1);
+ if(H5Tset_size(str_id,10)<0) TEST_ERROR
+
+ if(H5Tinsert(dtype1_id,"vl_string",HOFFSET(dtype1_struct,str),str_id)<0) TEST_ERROR
+ if(H5Tinsert(dtype1_id,"i2",HOFFSET(struct dtype1_struct,i2),H5T_NATIVE_INT)<0) TEST_ERROR
+ if(H5Tinsert(dtype1_id,"i3",HOFFSET(struct dtype1_struct,i3),H5T_NATIVE_INT)<0) TEST_ERROR
+ if(H5Tinsert(dtype1_id,"i4",HOFFSET(struct dtype1_struct,i4),H5T_NATIVE_INT)<0) TEST_ERROR
+ if(H5Tinsert(dtype1_id,"i5",HOFFSET(struct dtype1_struct,i5),H5T_NATIVE_INT)<0) TEST_ERROR
+ if(H5Tinsert(dtype1_id,"i6",HOFFSET(struct dtype1_struct,i6),H5T_NATIVE_INT)<0) TEST_ERROR
+ if(H5Tinsert(dtype1_id,"i7",HOFFSET(struct dtype1_struct,i7),H5T_NATIVE_INT)<0) TEST_ERROR
+ if(H5Tinsert(dtype1_id,"i8",HOFFSET(struct dtype1_struct,i8),H5T_NATIVE_INT)<0) TEST_ERROR
+ if(H5Tinsert(dtype1_id,"f1",HOFFSET(struct dtype1_struct,f1),H5T_NATIVE_FLOAT)<0) TEST_ERROR
+
+ if(H5Tclose(str_id) < 0) TEST_ERROR
+
+ return dtype1_id;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Tclose(str_id);
+ H5Tclose(dtype1_id);
+ } H5E_END_TRY
+ return -1;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: make_dtype_2
+ *
+ * Purpose: Creates complicated datatypes for use in testing
+ * shared object header messages. The important thing is that
+ * the datatypes must take a lot of space to store on disk.
+ *
+ * If record_hash is true, uses fid to record hash values
+ * of the intermediate datatypes in the global hash history
+ * table. Otherwise, fid is ignored.
+ *
+ * Return: Success: datatype ID (should be closed by calling function)
+ * Failure: negative
+ *
+ * Programmer: James Laird
+ * Saturday, August 26, 2006
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+make_dtype_2()
+{
+ hid_t dtype2_id = -1;
+ hid_t enum_id= -1;
+ hid_t int_id=-1;
+ int x;
+ hsize_t dims[] = {2, 1, 2, 4};
+ size_t size;
+
+ /* Create an int with a strange precision */
+ if((int_id = H5Tcopy(H5T_NATIVE_INT)) < 0) TEST_ERROR
+ if(H5Tset_precision(int_id, 24) < 0) TEST_ERROR
+
+ /* Create an enumeration using that int */
+ if((enum_id = H5Tenum_create(int_id)) < 0) TEST_ERROR
+
+ for(x=0; x<ENUM_NUM_MEMBS; x++)
+ {
+ if(H5Tenum_insert(enum_id, ENUM_NAME[x], &ENUM_VAL[x]) < 0) TEST_ERROR
+ }
+
+ /* Create arrays of arrays of arrays of enums */
+ if((dtype2_id = H5Tarray_create(enum_id, 3, dims, NULL)) < 0) TEST_ERROR
+ if((dtype2_id = H5Tarray_create(dtype2_id, 4, dims, NULL)) < 0) TEST_ERROR
+ if((dtype2_id = H5Tarray_create(dtype2_id, 2, dims, NULL)) < 0) TEST_ERROR
+ if((dtype2_id = H5Tarray_create(dtype2_id, 1, dims, NULL)) < 0) TEST_ERROR
+
+ if(H5Tclose(enum_id) < 0) TEST_ERROR
+ if(H5Tclose(int_id) < 0) TEST_ERROR
+
+ /* Check the datatype size. If this is different than the #defined
+ * size then the fills values will have the wrong size.
+ */
+ size = H5Tget_size(dtype2_id);
+ if(size != DTYPE2_SIZE) TEST_ERROR
+
+ return dtype2_id;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Tclose(dtype2_id);
+ H5Tclose(enum_id);
+ H5Tclose(int_id);
+ } H5E_END_TRY
+ return -1;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: close_reopen_file
+ *
+ * Purpose: Closes a file and then reopens it. Used to ensure that
+ * SOHMs are written to and read from disk
+ *
+ * Return: Success: new hid_t for the file
+ * Failure: Negative
+ *
+ * Programmer: James Laird
+ * Wednesday, October 4, 2006
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+close_reopen_file(hid_t file, const char* filename)
+{
+ if(H5Fclose(file) < 0) goto error;
+ return H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT);
+
+error:
+ return -1;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: size1_helper
+ *
+ * Purpose: Creates object headers that use a large datatype message.
+ *
+ * Used in test_sohm_basic. Should close the file ID passed in.
+ * Set test_file_closing to 1 to add file closing and reopening
+ * whenever possible (to test that SOHMs are written correctly
+ * on disk and not just in memory).
+ *
+ * Return: Success: file ID (may not be the same one passed in)
+ * Failure: Negative
+ *
+ * Programmer: James Laird
+ * Monday, April 10, 2006
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static hid_t
+size1_helper(hid_t file, char* filename, int test_file_closing)
+{
+ dtype1_struct wdata = {11, "string", 22, 33, 44, 55, 66, 77, 88, 0.0};
+ dtype1_struct rdata;
+ hid_t dtype1_id, dup_tid, type_id;
+ hid_t space_id;
+ hid_t dset_id;
+ hsize_t dim1[1];
+ int x;
+
+ /* Intialize rdata */
+ strcpy(rdata.str, "\0");
+
+ if((dtype1_id = make_dtype_1()) < 0) TEST_ERROR
+
+ /* Create the dataspace and dataset */
+ dim1[0] = 1;
+ if((space_id=H5Screate_simple(1,dim1,NULL))<0) TEST_ERROR
+
+ if((dset_id = H5Dcreate(file,DSETNAME[0],dtype1_id,space_id,H5P_DEFAULT))<0) TEST_ERROR
+
+ /* Test writing and reading */
+ if(H5Dwrite(dset_id,dtype1_id,H5S_ALL,H5S_ALL,H5P_DEFAULT,&wdata)<0) TEST_ERROR
+
+ if(H5Dread(dset_id,dtype1_id,H5S_ALL,H5S_ALL,H5P_DEFAULT,&rdata)<0) TEST_ERROR
+
+ if(rdata.i1!=wdata.i1 || rdata.i2!=wdata.i2 || HDstrcmp(rdata.str, wdata.str)) {
+ H5_FAILED(); AT();
+ printf("incorrect read data\n");
+ goto error;
+ } /* end if */
+ if(H5Dclose(dset_id)<0) TEST_ERROR
+
+ /* Close and re-open the file if requested*/
+ if(test_file_closing) {
+ if((file = close_reopen_file(file, filename)) < 0) TEST_ERROR
+ }
+
+ /* Create more datasets with the same datatype */
+ if((dset_id = H5Dcreate(file,DSETNAME[1],dtype1_id,space_id,H5P_DEFAULT))<0) TEST_ERROR
+ if(H5Dclose(dset_id)<0) TEST_ERROR
+
+ /* Close and re-open the file if requested*/
+ if(test_file_closing) {
+ if((file = close_reopen_file(file, filename)) < 0) TEST_ERROR
+ }
+
+ if((dset_id = H5Dcreate(file,DSETNAME[2],dtype1_id,space_id,H5P_DEFAULT))<0) TEST_ERROR
+ if(H5Dclose(dset_id)<0) TEST_ERROR
+
+ /* Close and re-open the file if requested*/
+ if(test_file_closing) {
+ if((file = close_reopen_file(file, filename)) < 0) TEST_ERROR
+ }
+
+ if((dset_id = H5Dcreate(file,DSETNAME[3],dtype1_id,space_id,H5P_DEFAULT))<0) TEST_ERROR
+
+ /* Write data to dataset 3 for later */
+ if(H5Dwrite(dset_id,dtype1_id,H5S_ALL,H5S_ALL,H5P_DEFAULT,&wdata)<0) TEST_ERROR
+
+ if(H5Dclose(dset_id)<0) TEST_ERROR
+ if(H5Tclose(dtype1_id)<0) TEST_ERROR
+
+ /* Close and re-open the file if requested*/
+ if(test_file_closing) {
+ if((file = close_reopen_file(file, filename)) < 0) TEST_ERROR
+ }
+
+ /* Make sure the data has been written successfully */
+ if((dset_id = H5Dopen(file, DSETNAME[0]))<0) TEST_ERROR
+
+ if((dtype1_id = H5Dget_type(dset_id))<0) TEST_ERROR
+
+ if((dup_tid = H5Tcopy(dtype1_id))<0) TEST_ERROR
+
+ rdata.i1 = rdata.i2 = 0;
+ strcpy(rdata.str, "\0");
+
+ /* Read data back again */
+ if(H5Dread(dset_id,dup_tid,H5S_ALL,H5S_ALL,H5P_DEFAULT,&rdata)<0) {
+ H5_FAILED(); AT();
+ printf("Can't read data\n");
+ goto error;
+ } /* end if */
+
+ if(rdata.i1!=wdata.i1 || rdata.i2!=wdata.i2 || strcmp(rdata.str, wdata.str)) {
+ H5_FAILED(); AT();
+ printf("incorrect read data\n");
+ goto error;
+ } /* end if */
+
+ if(H5Dclose(dset_id)<0) TEST_ERROR
+ if(H5Tclose(dup_tid)<0) TEST_ERROR
+
+ /* Create several copies of the dataset (this increases the amount of space saved by sharing the datatype message) */
+ for(x=0; x<SOHM_HELPER_NUM_EX_DSETS; x++) {
+ if((type_id = H5Tcopy(dtype1_id)) < 0) TEST_ERROR
+ if((dset_id = H5Dcreate(file,EXTRA_DSETNAME[x],type_id,space_id,H5P_DEFAULT)) < 0) TEST_ERROR
+
+ if(H5Tclose(type_id)<0) TEST_ERROR
+ if(H5Dclose(dset_id)<0) TEST_ERROR
+ /* Close and re-open the file if requested*/
+ if(test_file_closing) {
+ if((file = close_reopen_file(file, filename)) < 0) TEST_ERROR
+ }
+ }
+
+ if(H5Tclose(dtype1_id)<0) TEST_ERROR
+ if(H5Sclose(space_id)<0) TEST_ERROR
+
+ /* Ensure that we can still read data back from dataset 3 */
+ if((dset_id = H5Dopen(file, DSETNAME[3]))<0) TEST_ERROR
+
+ if((dtype1_id = H5Dget_type(dset_id))<0) TEST_ERROR
+
+ if((dup_tid = H5Tcopy(dtype1_id))<0) TEST_ERROR
+
+ rdata.i1 = rdata.i2 = 0;
+
+ /* Read data back again */
+ if(H5Dread(dset_id,dup_tid,H5S_ALL,H5S_ALL,H5P_DEFAULT,&rdata)<0) {
+ H5_FAILED(); AT();
+ printf("Can't read data\n");
+ goto error;
+ } /* end if */
+
+ if(rdata.i1!=wdata.i1 || rdata.i2!=wdata.i2 || strcmp(rdata.str, wdata.str)) {
+ H5_FAILED(); AT();
+ printf("incorrect read data\n");
+ goto error;
+ } /* end if */
+
+ if(H5Dclose(dset_id)<0) TEST_ERROR
+ if(H5Tclose(dtype1_id)<0) TEST_ERROR
+ if(H5Tclose(dup_tid)<0) TEST_ERROR
+ return file;
+
+ error:
+ H5E_BEGIN_TRY {
+ H5Tclose(dtype1_id);
+ H5Tclose(type_id);
+ H5Tclose(dup_tid);
+ H5Dclose(dset_id);
+ H5Fclose(file);
+ } H5E_END_TRY
+ return -1;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: test_sohm_size1
+ *
+ * Purpose: Tests shared object header messages with a large datatype
+ *
+ * Programmer: James Laird
+ * Monday, April 10, 2006
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void test_sohm_size1(void)
+{
+ hid_t file = -1;
+ hid_t fcpl_id = -1;
+ hsize_t norm_oh_size;
+ hsize_t sohm_oh_size;
+ hsize_t sohm_btree_oh_size;
+ h5_stat_size_t norm_empty_filesize;
+ h5_stat_size_t sohm_empty_filesize;
+ h5_stat_size_t sohm_btree_empty_filesize;
+ h5_stat_size_t norm_final_filesize;
+ h5_stat_size_t sohm_final_filesize;
+ h5_stat_size_t sohm_btree_final_filesize;
+ h5_stat_size_t norm_final_filesize2;
+ h5_stat_size_t sohm_final_filesize2;
+ h5_stat_size_t sohm_btree_final_filesize2;
+ H5G_stat_t statbuf;
+ unsigned num_indexes = 1;
+ unsigned index_flags = H5O_MESG_DTYPE_FLAG;
+ unsigned min_mesg_size = 50;
+ unsigned list_max = 11;
+ unsigned btree_min = 10;
+ herr_t ret;
+
+ MESSAGE(5, ("Testing that shared datatypes save space\n"));
+
+
+ /* Create a file with SOHMs disabled and get its size */
+ fcpl_id = H5Pcreate(H5P_FILE_CREATE);
+ CHECK_I(fcpl_id, "H5Pcreate");
+
+ ret = H5Pset_shared_mesg_nindexes(fcpl_id, 0);
+ CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
+
+ file = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
+ CHECK_I(file, "H5Fcreate");
+
+ ret = H5Fclose(file);
+ CHECK_I(ret, "H5Fclose");
+
+ /* Get the file size */
+ norm_empty_filesize = h5_get_file_size(FILENAME);
+
+ /* Add a bunch of large datatypes to the file */
+ file = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT);
+ CHECK_I(file, "H5Fopen");
+ file = size1_helper(file, FILENAME, 0);
+
+ /* Get the size of a dataset object header */
+ ret = H5Gget_objinfo(file, DSETNAME[0], 0, &statbuf);
+ CHECK_I(ret, "H5Gget_objinfo");
+ ret = H5Fclose(file);
+ CHECK_I(ret, "H5Fclose");
+ norm_oh_size = statbuf.ohdr.size;
+
+ /* Get the new file size */
+ norm_final_filesize = h5_get_file_size(FILENAME);
+
+ /* Use the same property list to create a new file. */
+ file = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
+ CHECK_I(file, "H5Fcreate");
+
+ ret = H5Pclose(fcpl_id);
+ CHECK_I(ret, "H5Pclose");
+
+ /* Add the same large datatypes, but keep closing and re-opening the file */
+ file = size1_helper(file, FILENAME, 1);
+ ret = H5Fclose(file);
+ CHECK_I(ret, "H5Fclose");
+
+ /* Get the file size */
+ norm_final_filesize2 = h5_get_file_size(FILENAME);
+
+
+
+ /* Now do the same thing for a file with SOHMs enabled */
+ /* Create FCPL with SOHMs enabled */
+ fcpl_id = H5Pcreate(H5P_FILE_CREATE);
+ CHECK_I(fcpl_id, "H5Pcreate");
+
+ /* Tests one index holding only datatype messages */
+ ret = H5Pset_shared_mesg_nindexes(fcpl_id, num_indexes);
+ CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
+ ret = H5Pset_shared_mesg_index(fcpl_id, 1, index_flags, min_mesg_size);
+ CHECK_I(ret, "H5Pset_shared_mesg_index");
+ ret = H5Pset_shared_mesg_phase_change(fcpl_id, list_max, btree_min);
+ CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
+
+ /* Create a file */
+ file = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
+ CHECK_I(file, "H5Fcreate");
+
+ ret = H5Fclose(file);
+ CHECK_I(ret, "H5Fclose");
+
+ sohm_empty_filesize = h5_get_file_size(FILENAME);
+
+ /* Add a bunch of datatypes to this file */
+ file = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT);
+ CHECK_I(file, "H5Fopen");
+ file = size1_helper(file, FILENAME, 0);
+
+ /* Get the size of a dataset object header */
+ ret = H5Gget_objinfo(file, DSETNAME[0], 0, &statbuf);
+ CHECK_I(ret, "H5Gget_objinfo");
+ ret = H5Fclose(file);
+ CHECK_I(ret, "H5Fclose");
+ sohm_oh_size = statbuf.ohdr.size;
+
+ /* Get the new file size */
+ sohm_final_filesize = h5_get_file_size(FILENAME);
+
+ /* Use the same property list to create a new file. */
+ file = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
+ CHECK_I(file, "H5Fcreate");
+
+ ret = H5Pclose(fcpl_id);
+ CHECK_I(ret, "H5Pclose");
+
+ /* Add the same large datatypes, but keep closing and re-opening the file */
+ file = size1_helper(file, FILENAME, 1);
+ ret = H5Fclose(file);
+ CHECK_I(ret, "H5Fclose");
+
+ /* Get the file size */
+ sohm_final_filesize2 = h5_get_file_size(FILENAME);
+
+
+
+ /* Create FCPL with SOHMs enabled that uses a B-tree index */
+ fcpl_id = H5Pcreate(H5P_FILE_CREATE);
+ CHECK_I(fcpl_id, "H5Pcreate");
+
+ /* Tests one index holding only datatype messages */
+ ret = H5Pset_shared_mesg_nindexes(fcpl_id, num_indexes);
+ CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
+ ret = H5Pset_shared_mesg_index(fcpl_id, 1, index_flags, min_mesg_size);
+ CHECK_I(ret, "H5Pset_shared_mesg_index");
+ ret = H5Pset_shared_mesg_phase_change(fcpl_id, 0, 0);
+ CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
+
+ /* Create a file */
+ file = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
+ CHECK_I(file, "H5Fcreate");
+
+ ret = H5Fclose(file);
+ CHECK_I(ret, "H5Fclose");
+
+ sohm_btree_empty_filesize = h5_get_file_size(FILENAME);
+
+ /* Add a bunch of datatypes to this file */
+ file = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT);
+ CHECK_I(file, "H5Fopen");
+ file = size1_helper(file, FILENAME, 0);
+
+ /* Get the size of a dataset object header */
+ ret = H5Gget_objinfo(file, DSETNAME[0], 0, &statbuf);
+ CHECK_I(ret, "H5Gget_objinfo");
+ ret = H5Fclose(file);
+ CHECK_I(ret, "H5Fclose");
+ sohm_btree_oh_size = statbuf.ohdr.size;
+
+ /* Get the new file size */
+ sohm_btree_final_filesize = h5_get_file_size(FILENAME);
+
+ /* Use the same property list to create a new file. */
+ file = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
+ CHECK_I(file, "H5Fcreate");
+
+ ret = H5Pclose(fcpl_id);
+ CHECK_I(ret, "H5Pclose");
+
+ /* Add the same large datatypes, but keep closing and re-opening the file */
+ file = size1_helper(file, FILENAME, 1);
+ ret = H5Fclose(file);
+ CHECK_I(ret, "H5Fclose");
+
+ /* Get the file size */
+ sohm_btree_final_filesize2 = h5_get_file_size(FILENAME);
+
+
+
+ /* Check that all sizes make sense */
+ /* Object headers in SOHM files should be smaller than normal object
+ * headers. How the SOHM messages are stored shouldn't affect the
+ * size of the object header.
+ */
+ if(sohm_oh_size >= norm_oh_size)
+ VERIFY(sohm_oh_size, 1, "H5Fclose");
+ if(sohm_oh_size != sohm_btree_oh_size)
+ VERIFY(sohm_btree_oh_size, 1, "H5Fclose");
+
+ /* Both sohm files should be bigger than a normal file when empty.
+ * It's hard to say whether a B-tree with no nodes allocated should be
+ * smaller than a list with SOHM_HELPER_NUM_DTYPES elements.
+ * JAMES: The sizes here shouldn't really be 1
+ */
+ if(sohm_empty_filesize <= norm_empty_filesize)
+ VERIFY(sohm_empty_filesize, 1, "H5Fclose");
+
+ if(sohm_btree_empty_filesize <= norm_empty_filesize)
+ VERIFY(sohm_btree_empty_filesize, 1, "H5Fclose");
+
+ /* When full, the sohm btree file should be smaller than the normal file.
+ * The sohm list file should be at least as small, since it doesn't need the
+ * overhead of a B-tree.
+ */
+ if(sohm_btree_final_filesize >= norm_final_filesize)
+ VERIFY(sohm_btree_final_filesize, 1, "H5Fclose");
+ if(sohm_final_filesize > sohm_btree_final_filesize)
+ VERIFY(sohm_final_filesize, 1, "H5Fclose");
+
+ /* This shouldn't change even if we open and close the file */
+ if(sohm_btree_final_filesize2 >= norm_final_filesize2)
+ VERIFY(sohm_btree_final_filesize2, 1, "H5Fclose");
+ if(sohm_final_filesize2 > sohm_btree_final_filesize2)
+ VERIFY(sohm_final_filesize2, 1, "H5Fclose");
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: sohm_attr_helper
+ *
+ * Purpose: Given an fcpl, tests creating attributes with and without
+ * committed datatypes.
+ *
+ * Programmer: James Laird
+ * Thursday, November 30, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static void sohm_attr_helper(hid_t fcpl_id)
+{
+ hid_t file_id;
+ hid_t type_id;
+ hid_t space_id;
+ hid_t group_id;
+ hid_t attr_id;
+ hsize_t dims = 2;
+ int wdata[2] = {7, 42};
+ int rdata[2];
+ herr_t ret;
+ hsize_t x;
+
+ /* Create a file using the fcpl */
+ file_id = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
+ CHECK_I(file_id, "H5Fcreate");
+
+ /* Create a normal datatype and dataset */
+ type_id = H5Tcopy(H5T_NATIVE_INT);
+ CHECK_I(type_id, "H5Tcopy");
+ space_id = H5Screate_simple(1, &dims, &dims);
+ CHECK_I(space_id, "H5Screate_simple");
+
+ /* Create and verify an attribute on a group */
+ group_id = H5Gcreate(file_id, "group", 100);
+ CHECK_I(group_id, "H5Gcreate");
+ attr_id = H5Acreate(group_id, "attribute", type_id, space_id, H5P_DEFAULT);
+ CHECK_I(attr_id, "H5Acreate");
+ ret = H5Awrite(attr_id, H5T_NATIVE_INT, wdata);
+ CHECK_I(ret, "H5Awrite");
+
+ /* Close the datatype and group */
+ ret = H5Tclose(type_id);
+ CHECK_I(ret, "H5Tclose");
+ ret = H5Gclose(group_id);
+ CHECK_I(ret, "H5Gclose");
+
+ /* Flush the file to force data to be written */
+ ret = H5Fflush(file_id, H5F_SCOPE_GLOBAL);
+ CHECK_I(ret, "H5Fflush");
+
+ /* Verify */
+ memset(rdata, 0, sizeof(rdata));
+ ret = H5Aread(attr_id, H5T_NATIVE_INT, rdata);
+ CHECK_I(ret, "H5Aread");
+ for(x=0; x<dims; ++x) {
+ VERIFY(rdata[x], wdata[x], "H5Aread");
+ }
+
+ /* Cleanup */
+ ret = H5Aclose(attr_id);
+ CHECK_I(ret, "H5Aclose");
+
+ /* Repeat with a committed datatype */
+ type_id = H5Tcopy(H5T_NATIVE_INT);
+ CHECK_I(type_id, "H5Tcopy");
+ ret = H5Tcommit(file_id, "datatype", type_id);
+ CHECK_I(ret, "H5Tcommit");
+
+ /* Create and verify an attribute */
+ group_id = H5Gcreate(file_id, "another_group", 100);
+ CHECK_I(group_id, "H5Gcreate");
+ attr_id = H5Acreate(group_id, "attribute", type_id, space_id, H5P_DEFAULT);
+ CHECK_I(attr_id, "H5Acreate");
+ ret = H5Awrite(attr_id, H5T_NATIVE_INT, wdata);
+ CHECK_I(ret, "H5Awrite");
+
+ /* Close the datatype and group */
+ ret = H5Tclose(type_id);
+ CHECK_I(ret, "H5Tclose");
+ ret = H5Gclose(group_id);
+ CHECK_I(ret, "H5Gclose");
+
+ /* Flush the file to force data to be written */
+ ret = H5Fflush(file_id, H5F_SCOPE_GLOBAL);
+ CHECK_I(ret, "H5Fflush");
+
+ /* Verify */
+ memset(rdata, 0, sizeof(rdata));
+ ret = H5Aread(attr_id, H5T_NATIVE_INT, rdata);
+ CHECK_I(ret, "H5Aread");
+ for(x=0; x<dims; ++x) {
+ VERIFY(rdata[x], wdata[x], "H5Aread");
+ }
+
+ /* Cleanup */
+ ret = H5Aclose(attr_id);
+ CHECK_I(ret, "H5Aclose");
+ ret = H5Sclose(space_id);
+ CHECK_I(ret, "H5Sclose");
+ ret = H5Fclose(file_id);
+ CHECK_I(ret, "H5Fclose");
+}
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_sohm_attrs
+ *
+ * Purpose: Attributes can be shared and can also contain shared
+ * datatype and dataspace messages. Committed datatypes
+ * shouldn't be shared.
+ *
+ * Test permutations of this.
+ *
+ * Programmer: James Laird
+ * Thursday, November 30, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static void test_sohm_attrs()
+{
+ hid_t fcpl_id;
+ herr_t ret;
+
+ MESSAGE(5, ("Testing that shared messages work with attributes\n"));
+
+ /* Create an fcpl with no shared messages */
+ fcpl_id = H5Pcreate(H5P_FILE_CREATE);
+ CHECK_I(fcpl_id, "H5Pcreate");
+ ret = H5Pset_shared_mesg_nindexes(fcpl_id, 0);
+ CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
+
+ /* Make sure attributes can be read with these settings (they'd better!) */
+ sohm_attr_helper(fcpl_id);
+
+
+ /* Run tests with only one kind of message to be shared */
+ ret = H5Pset_shared_mesg_nindexes(fcpl_id, 1);
+ CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
+ ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_MESG_ATTR_FLAG, 2);
+ CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
+
+ /* Verify */
+ sohm_attr_helper(fcpl_id);
+
+ ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_MESG_SDSPACE_FLAG, 2);
+ CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
+
+ sohm_attr_helper(fcpl_id);
+
+ ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_MESG_DTYPE_FLAG, 2);
+ CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
+
+ sohm_attr_helper(fcpl_id);
+
+
+ /* Run with any two types shared */
+ ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_MESG_SDSPACE_FLAG | H5O_MESG_DTYPE_FLAG, 2);
+ CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
+
+ sohm_attr_helper(fcpl_id);
+
+ ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_MESG_ATTR_FLAG | H5O_MESG_DTYPE_FLAG, 2);
+ CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
+
+ sohm_attr_helper(fcpl_id);
+
+ ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_MESG_SDSPACE_FLAG | H5O_MESG_ATTR_FLAG, 2);
+ CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
+
+ sohm_attr_helper(fcpl_id);
+
+
+ /* Run test with all three kinds of message shared */
+ ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_MESG_SDSPACE_FLAG | H5O_MESG_DTYPE_FLAG | H5O_MESG_ATTR_FLAG, 2);
+ CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
+
+ sohm_attr_helper(fcpl_id);
+
+
+ /* Try using two indexes */
+ ret = H5Pset_shared_mesg_nindexes(fcpl_id, 2);
+ CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
+ ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_MESG_ATTR_FLAG | H5O_MESG_DTYPE_FLAG, 2);
+ CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
+ ret = H5Pset_shared_mesg_index(fcpl_id, 2, H5O_MESG_SDSPACE_FLAG, 2);
+ CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
+
+ sohm_attr_helper(fcpl_id);
+
+ ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_MESG_DTYPE_FLAG, 2);
+ CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
+
+ sohm_attr_helper(fcpl_id);
+
+ ret = H5Pset_shared_mesg_index(fcpl_id, 2, H5O_MESG_ATTR_FLAG, 2);
+ CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
+
+ sohm_attr_helper(fcpl_id);
+
+
+ /* One index for each kind of message */
+ ret = H5Pset_shared_mesg_nindexes(fcpl_id, 3);
+ CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
+ ret = H5Pset_shared_mesg_index(fcpl_id, 3, H5O_MESG_SDSPACE_FLAG, 2);
+ CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
+
+ sohm_attr_helper(fcpl_id);
+
+
+ /* Close the FCPL */
+ ret = H5Pclose(fcpl_id);
+ CHECK_I(ret, "H5Pclose");
+}
+
+/*-------------------------------------------------------------------------
+ * Function: size2_verify_plist1
+ *
+ * Purpose: Verify that the property list passed in is in fact the
+ * same property list used as dcpl1_id in the size2 helper
+ * function. This ensures that the filters can be read.
+ *
+ * Programmer: James Laird
+ * Wednesday, November 22, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static void size2_verify_plist1(hid_t plist)
+{
+ size_t cd_nelmts;
+ unsigned int cd_value;
+ char name[NAME_BUF_SIZE];
+ H5Z_filter_t filter;
+ hid_t dtype1_id;
+ dtype1_struct fill1;
+ dtype1_struct fill1_correct;
+ herr_t ret;
+
+ /* Hardcoded to correspond to dcpl1_id created in size2_helper */
+ /* Check filters */
+ cd_nelmts = 1;
+ filter = H5Pget_filter(plist, 0, NULL, &cd_nelmts, &cd_value, NAME_BUF_SIZE, name, NULL);
+ CHECK_I(filter, "H5Pget_filter");
+ VERIFY(filter, H5Z_FILTER_SHUFFLE, "H5Pget_filter");
+
+ cd_nelmts = 1;
+ filter = H5Pget_filter(plist, 1, NULL, &cd_nelmts, &cd_value, NAME_BUF_SIZE, name, NULL);
+ CHECK_I(filter, "H5Pget_filter");
+ VERIFY(filter, H5Z_FILTER_DEFLATE, "H5Pget_filter");
+ VERIFY(cd_value, 1, "H5Pget_filter");
+
+ cd_nelmts = 1;
+ filter = H5Pget_filter(plist, 2, NULL, &cd_nelmts, &cd_value, NAME_BUF_SIZE, name, NULL);
+ CHECK_I(filter, "H5Pget_filter");
+ VERIFY(filter, H5Z_FILTER_SHUFFLE, "H5Pget_filter");
+
+ cd_nelmts = 1;
+ filter = H5Pget_filter(plist, 3, NULL, &cd_nelmts, &cd_value, NAME_BUF_SIZE, name, NULL);
+ CHECK_I(filter, "H5Pget_filter");
+ VERIFY(filter, H5Z_FILTER_FLETCHER32, "H5Pget_filter");
+
+
+ /* Check fill value */
+ dtype1_id=make_dtype_1();
+ CHECK_I(dtype1_id, "make_dtype_1");
+ memset(&fill1_correct, '1', sizeof(fill1_correct));
+
+ ret = H5Pget_fill_value(plist, dtype1_id, &fill1);
+ CHECK_I(ret, "H5Pget_fill_value");
+
+ ret = memcmp(&fill1, &fill1_correct, sizeof(fill1_correct));
+ VERIFY(ret, 0, memcmp);
+}
+
+/*-------------------------------------------------------------------------
+ * Function: size2_verify_plist2
+ *
+ * Purpose: Verify that the property list passed in is in fact the
+ * same property list used as dcpl2_id in the size2 helper
+ * function. This ensures that the filters can be read.
+ *
+ * Programmer: James Laird
+ * Wednesday, November 22, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static void size2_verify_plist2(hid_t plist)
+{
+ size_t cd_nelmts;
+ unsigned int cd_value;
+ char name[NAME_BUF_SIZE];
+ H5Z_filter_t filter;
+ hid_t dtype2_id;
+ char fill2[DTYPE2_SIZE];
+ char fill2_correct[DTYPE2_SIZE];
+ herr_t ret;
+
+ /* Hardcoded to correspond to dcpl1_id created in size2_helper */
+ /* Check filters */
+ cd_nelmts = 1;
+ filter = H5Pget_filter(plist, 0, NULL, &cd_nelmts, &cd_value, NAME_BUF_SIZE, name, NULL);
+ CHECK_I(filter, "H5Pget_filter");
+ VERIFY(filter, H5Z_FILTER_DEFLATE, "H5Pget_filter");
+ VERIFY(cd_value, 1, "H5Pget_filter");
+
+ cd_nelmts = 1;
+ filter = H5Pget_filter(plist, 1, NULL, &cd_nelmts, &cd_value, NAME_BUF_SIZE, name, NULL);
+ CHECK_I(filter, "H5Pget_filter");
+ VERIFY(filter, H5Z_FILTER_DEFLATE, "H5Pget_filter");
+ VERIFY(cd_value, 2, "H5Pget_filter");
+
+ cd_nelmts = 1;
+ filter = H5Pget_filter(plist, 2, NULL, &cd_nelmts, &cd_value, NAME_BUF_SIZE, name, NULL);
+ CHECK_I(filter, "H5Pget_filter");
+ VERIFY(filter, H5Z_FILTER_DEFLATE, "H5Pget_filter");
+ VERIFY(cd_value, 2, "H5Pget_filter");
+
+ cd_nelmts = 1;
+ filter = H5Pget_filter(plist, 3, NULL, &cd_nelmts, &cd_value, NAME_BUF_SIZE, name, NULL);
+ CHECK_I(filter, "H5Pget_filter");
+ VERIFY(filter, H5Z_FILTER_DEFLATE, "H5Pget_filter");
+ VERIFY(cd_value, 1, "H5Pget_filter");
+
+ cd_nelmts = 1;
+ filter = H5Pget_filter(plist, 4, NULL, &cd_nelmts, &cd_value, NAME_BUF_SIZE, name, NULL);
+ CHECK_I(filter, "H5Pget_filter");
+ VERIFY(filter, H5Z_FILTER_DEFLATE, "H5Pget_filter");
+ VERIFY(cd_value, 5, "H5Pget_filter");
+
+
+ /* Check fill value */
+ dtype2_id=make_dtype_2();
+ CHECK_I(dtype2_id, "make_dtype_2");
+ memset(&fill2_correct, '2', DTYPE2_SIZE);
+
+ ret = H5Pget_fill_value(plist, dtype2_id, &fill2);
+ CHECK_I(ret, "H5Pget_fill_value");
+
+ ret = memcmp(&fill2, &fill2_correct, DTYPE2_SIZE);
+ VERIFY(ret, 0, memcmp);
+}
+
+/*-------------------------------------------------------------------------
+ * Function: size2_helper
+ *
+ * Purpose: A helper functon for test_sohm_size2.
+ *
+ * Creates a file using the given fcpl, then creates lots
+ * of different kinds of messages within the file and
+ * returns the size of the file for comparison.
+ *
+ * If test_file_closing is not zero, closes and re-opens
+ * the file after every write.
+ *
+ * Doesn't close the property list. Prints an error message
+ * if there's a failure, but doesn't alter its return value.
+ *
+ * Programmer: James Laird
+ * Friday, November 17, 2006
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static size2_helper_struct size2_helper(hid_t fcpl_id, int test_file_closing)
+{
+ hid_t file_id = -1;
+ hid_t dtype1_id=-1;
+ hid_t dtype2_id=-1;
+ hid_t dspace1_id=-1;
+ hid_t dspace2_id=-1;
+ hid_t dcpl1_id=-1;
+ hid_t dcpl2_id=-1;
+ hid_t dset_id=-1;
+ hid_t attr_type_id=-1;
+ hid_t attr_space_id=-1;
+ hid_t attr_id=-1;
+ hid_t group_id=-1;
+ size2_helper_struct ret_val; /* We'll fill in this struct as we go */
+ char attr_string1[NAME_BUF_SIZE];
+ char attr_string2[NAME_BUF_SIZE];
+ char attr_name[NAME_BUF_SIZE];
+ int x;
+ herr_t ret;
+
+ /* Constants used in this function */
+ const int rank1 = SIZE2_RANK1;
+ const int rank2 = SIZE2_RANK2;
+ const hsize_t dims[20] = SIZE2_DIMS;
+ dtype1_struct fill1;
+ char fill2[DTYPE2_SIZE];
+
+ /* Create a file and get its size */
+ /* JAMES: is fixname needed at all? */
+ file_id = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
+ CHECK_I(file_id, "H5Fcreate");
+
+ ret = H5Fclose(file_id);
+ CHECK_I(ret, "H5Fclose");
+
+ /* Get the file size */
+ ret_val.empty_size = h5_get_file_size(FILENAME);
+
+ /* Re-open the file and set up messages to write */
+ file_id = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT);
+ CHECK_I(file_id, "H5Fopen");
+
+ /* Create two large datatype messages */
+ dtype1_id=make_dtype_1();
+ CHECK_I(dtype1_id, "make_dtype_1");
+ dtype2_id=make_dtype_2(0, file_id);
+ CHECK_I(dtype2_id, "make_dtype_1");
+
+ /* Create some large dataspaces */
+ dspace1_id=H5Screate_simple(rank1, dims, dims);
+ CHECK_I(dspace1_id, "H5Screate_simple");
+ dspace2_id=H5Screate_simple(rank2, dims, dims);
+ CHECK_I(dspace2_id, "H5Screate_simple");
+
+ /* fill1 and fill2 are fill values for the two datatypes.
+ * We'll set them in the DCPL.
+ */
+ memset(&fill1, '1', sizeof(dtype1_struct));
+ memset(&fill2, '2', DTYPE2_SIZE);
+
+ dcpl1_id = H5Pcreate(H5P_DATASET_CREATE);
+ CHECK_I(dcpl1_id, "H5Pcreate");
+ H5Pset_fill_value(dcpl1_id, dtype1_id, &fill1);
+
+ dcpl2_id = H5Pcreate(H5P_DATASET_CREATE);
+ CHECK_I(dcpl2_id, "H5Pcreate");
+ H5Pset_fill_value(dcpl2_id, dtype2_id, &fill2);
+
+ /* Filter messages we'll create by setting them in a DCPL. These
+ * values don't need to make sense, they just need to take up space.
+ */
+ ret = H5Pset_chunk(dcpl1_id, rank1, dims);
+ CHECK_I(ret, "H5Pset_chunk");
+ ret = H5Pset_shuffle(dcpl1_id);
+ CHECK_I(ret, "H5Pset_shuffle");
+ ret = H5Pset_deflate(dcpl1_id, 1);
+ CHECK_I(ret, "H5Pset_deflate");
+ ret = H5Pset_shuffle(dcpl1_id);
+ CHECK_I(ret, "H5Pset_shuffle");
+ ret = H5Pset_fletcher32(dcpl1_id);
+ CHECK_I(ret, "H5Pset_fletcher32");
+ /* Make sure that this property list is what it should be */
+ size2_verify_plist1(dcpl1_id);
+
+ /* Second dcpl */
+ ret = H5Pset_chunk(dcpl2_id, rank2, dims);
+ CHECK_I(ret, "H5Pset_chunk");
+ ret = H5Pset_deflate(dcpl2_id, 1);
+ CHECK_I(ret, "H5Pset_deflate");
+ ret = H5Pset_deflate(dcpl2_id, 2);
+ CHECK_I(ret, "H5Pset_deflate");
+ ret = H5Pset_deflate(dcpl2_id, 2);
+ CHECK_I(ret, "H5Pset_deflate");
+ ret = H5Pset_deflate(dcpl2_id, 1);
+ CHECK_I(ret, "H5Pset_deflate");
+ ret = H5Pset_deflate(dcpl2_id, 5);
+ CHECK_I(ret, "H5Pset_deflate");
+ /* Make sure that this property list is what it should be */
+ size2_verify_plist2(dcpl2_id);
+
+ /* Create a dataset with a big datatype, dataspace, fill value,
+ * and filter pipeline.
+ */
+ dset_id = H5Dcreate(file_id, DSETNAME[0], dtype1_id, dspace1_id, dcpl1_id);
+ CHECK_I(dset_id, "H5Dcreate");
+
+ memset(attr_string1, 0, NAME_BUF_SIZE);
+ memset(attr_string2, 0, NAME_BUF_SIZE);
+ strcpy(attr_string1, LONG_STRING);
+ strcpy(attr_string2, LONG_STRING);
+ attr_string2[1] = '1'; /* The second string starts "01 index..." */
+
+ /* Create an attribute on this dataset with a large string value */
+ attr_type_id = H5Tcopy(H5T_C_S1);
+ CHECK_I(attr_type_id, "H5Tcopy");
+ ret = H5Tset_size(attr_type_id ,NAME_BUF_SIZE);
+ CHECK_I(ret, "H5Tset_size");
+ attr_space_id = H5Screate_simple(1, dims, dims);
+ CHECK_I(attr_space_id, "H5Screate_simple");
+
+ attr_id = H5Acreate(dset_id, "attr_name", attr_type_id, attr_space_id, H5P_DEFAULT);
+ CHECK_I(attr_id, "H5Acreate");
+ ret = H5Awrite(attr_id, attr_type_id, attr_string1);
+ CHECK_I(attr_id, "H5Awrite");
+
+ /* Close the file and everything in it. */
+ H5Aclose(attr_id);
+ CHECK_I(attr_id, "H5Aclose");
+ H5Dclose(dset_id);
+ CHECK_I(dset_id, "H5Dclose");
+ H5Fclose(file_id);
+ CHECK_I(file_id, "H5Fclose");
+
+ /* Get the file's size now */
+ ret_val.first_dset = h5_get_file_size(FILENAME);
+
+ /* Re-open the file and create the same dataset several more times. */
+ file_id = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT);
+ CHECK_I(file_id, "H5Fopen");
+
+ for(x=1; x<NUM_DATASETS; ++x)
+ {
+ dset_id = H5Dcreate(file_id, DSETNAME[x], dtype1_id, dspace1_id, dcpl1_id);
+ CHECK_I(dset_id, "H5Dcreate");
+
+ attr_id = H5Acreate(dset_id, "attr_name", attr_type_id, attr_space_id, H5P_DEFAULT);
+ CHECK_I(attr_id, "H5Acreate");
+ ret = H5Awrite(attr_id, attr_type_id, attr_string1);
+ CHECK_I(ret, "H5Awrite");
+
+ ret = H5Dclose(dset_id);
+ CHECK_I(ret, "H5Dclose");
+ ret = H5Aclose(attr_id);
+ CHECK_I(ret, "H5Aclose");
+
+ if(test_file_closing) {
+ file_id = close_reopen_file(file_id, FILENAME);
+ CHECK_I(file_id, "H5Fopen");
+ }
+ }
+
+ /* Close file and get its size now */
+ H5Fclose(file_id);
+ CHECK_I(file_id, "H5Fclose");
+ ret_val.dsets1 = h5_get_file_size(FILENAME);
+
+
+ /* Now create a new group filled with datasets that use all different messages */
+ file_id = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT);
+ CHECK_I(file_id, "H5Fopen");
+ group_id = H5Gcreate(file_id, "group", 0);
+ CHECK_I(group_id, "H5Gcreate");
+
+ /* Create NUM_DATASETS datasets in the new group */
+ for(x=0; x<NUM_DATASETS; ++x)
+ {
+ dset_id = H5Dcreate(group_id, DSETNAME[x], dtype2_id, dspace2_id, dcpl2_id);
+ CHECK_I(dset_id, "H5Dcreate");
+
+ attr_id = H5Acreate(dset_id, "attr_name", attr_type_id, attr_space_id, H5P_DEFAULT);
+ CHECK_I(attr_id, "H5Acreate");
+ ret = H5Awrite(attr_id, attr_type_id, attr_string2);
+ CHECK_I(ret, "H5Awrite");
+
+ ret = H5Dclose(dset_id);
+ CHECK_I(ret, "H5Dclose");
+ ret = H5Aclose(attr_id);
+ CHECK_I(ret, "H5Aclose");
+
+ if(test_file_closing) {
+ ret = H5Gclose(group_id);
+ CHECK_I(ret, "H5Gclose");
+ file_id = close_reopen_file(file_id, FILENAME);
+ CHECK_I(file_id, "H5Fopen");
+ group_id = H5Gopen(file_id, "group");
+ CHECK_I(group_id, "H5Gopen");
+ }
+ }
+
+ /* Close file and get its size now */
+ ret = H5Gclose(group_id);
+ CHECK_I(ret, "H5Gclose");
+ H5Fclose(file_id);
+ CHECK_I(file_id, "H5Fclose");
+ ret_val.dsets2 = h5_get_file_size(FILENAME);
+
+
+ /* Create a new group and interleave writes of datasets types 1 and 2. */
+ file_id = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT);
+ CHECK_I(file_id, "H5Fopen");
+ group_id = H5Gcreate(file_id, "interleaved group", 0);
+ CHECK_I(group_id, "H5Gcreate");
+
+ /* Create NUM_DATASETS datasets in the new group */
+ for(x=0; x<NUM_DATASETS; x+=2)
+ {
+ dset_id = H5Dcreate(group_id, DSETNAME[x], dtype1_id, dspace1_id, dcpl1_id);
+ CHECK_I(dset_id, "H5Dcreate");
+
+ attr_id = H5Acreate(dset_id, "attr_name", attr_type_id, attr_space_id, H5P_DEFAULT);
+ CHECK_I(attr_id, "H5Acreate");
+ ret = H5Awrite(attr_id, attr_type_id, attr_string1);
+ CHECK_I(ret, "H5Awrite");
+
+ ret = H5Dclose(dset_id);
+ CHECK_I(ret, "H5Dclose");
+ ret = H5Aclose(attr_id);
+ CHECK_I(ret, "H5Aclose");
+
+ dset_id = H5Dcreate(group_id, DSETNAME[x+1], dtype2_id, dspace2_id, dcpl2_id);
+ CHECK_I(dset_id, "H5Dcreate");
+
+ attr_id = H5Acreate(dset_id, "attr_name", attr_type_id, attr_space_id, H5P_DEFAULT);
+ CHECK_I(attr_id, "H5Acreate");
+ ret = H5Awrite(attr_id, attr_type_id, attr_string2);
+ CHECK_I(ret, "H5Awrite");
+
+ ret = H5Dclose(dset_id);
+ CHECK_I(ret, "H5Dclose");
+ ret = H5Aclose(attr_id);
+ CHECK_I(ret, "H5Aclose");
+
+ if(test_file_closing) {
+ ret = H5Gclose(group_id);
+ CHECK_I(ret, "H5Gclose");
+ file_id = close_reopen_file(file_id, FILENAME);
+ CHECK_I(file_id, "H5Fopen");
+ group_id = H5Gopen(file_id, "interleaved group");
+ CHECK_I(group_id, "H5Gopen");
+ }
+ }
+
+ /* Close file and get its size now */
+ ret = H5Gclose(group_id);
+ CHECK_I(ret, "H5Gclose");
+ H5Fclose(file_id);
+ CHECK_I(file_id, "H5Fclose");
+ ret_val.interleaved = h5_get_file_size(FILENAME);
+
+ /* Create lots of new attribute messages on the group
+ * (using different strings for the attribute)
+ */
+ file_id = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT);
+ CHECK_I(file_id, "H5Fopen");
+ group_id = H5Gopen(file_id, "group");
+ CHECK_I(group_id, "H5Gopen");
+
+ strcpy(attr_name, "00 index");
+
+ for(x=0; x<NUM_ATTRIBUTES; ++x)
+ {
+ /* Create a unique name and value for each attribute */
+ attr_string1[0] = attr_name[0] = (x / 10) + '0';
+ attr_string1[1] = attr_name[1] = (x % 10) + '0';
+
+ /* Create an attribute on the group */
+ attr_id = H5Acreate(group_id, attr_name, attr_type_id, attr_space_id, H5P_DEFAULT);
+ CHECK_I(attr_id, "H5Acreate");
+ ret = H5Awrite(attr_id, attr_type_id, attr_string1);
+ CHECK_I(ret, "H5Awrite");
+
+ ret = H5Aclose(attr_id);
+ CHECK_I(ret, "H5Aclose");
+
+ if(test_file_closing) {
+ ret = H5Gclose(group_id);
+ CHECK_I(ret, "H5Gclose");
+ file_id = close_reopen_file(file_id, FILENAME);
+ CHECK_I(file_id, "H5Fopen");
+ group_id = H5Gopen(file_id, "group");
+ CHECK_I(group_id, "H5Gopen");
+ }
+ }
+
+ /* Close file and get its size now */
+ ret = H5Gclose(group_id);
+ CHECK_I(ret, "H5Gclose");
+ H5Fclose(file_id);
+ CHECK_I(file_id, "H5Fclose");
+ ret_val.attrs1 = h5_get_file_size(FILENAME);
+
+
+ /* Create all of the attributes again on the other group */
+ file_id = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT);
+ CHECK_I(file_id, "H5Fopen");
+ group_id = H5Gopen(file_id, "interleaved group");
+ CHECK_I(group_id, "H5Gopen");
+
+ for(x=0; x<NUM_ATTRIBUTES; ++x)
+ {
+ /* Create the same name and value for each attribute as before */
+ attr_string1[0] = attr_name[0] = (x / 10) + '0';
+ attr_string1[1] = attr_name[1] = (x % 10) + '0';
+
+ /* Create an attribute on the group */
+ attr_id = H5Acreate(group_id, attr_name, attr_type_id, attr_space_id, H5P_DEFAULT);
+ CHECK_I(attr_id, "H5Acreate");
+ ret = H5Awrite(attr_id, attr_type_id, attr_string1);
+ CHECK_I(ret, "H5Awrite");
+
+ ret = H5Aclose(attr_id);
+ CHECK_I(ret, "H5Aclose");
+
+ if(test_file_closing) {
+ ret = H5Gclose(group_id);
+ CHECK_I(ret, "H5Gclose");
+ file_id = close_reopen_file(file_id, FILENAME);
+ CHECK_I(file_id, "H5Fopen");
+ group_id = H5Gopen(file_id, "interleaved group");
+ CHECK_I(group_id, "H5Gopen");
+ }
+ }
+ /* Close file and get its size now */
+ ret = H5Gclose(group_id);
+ CHECK_I(ret, "H5Gclose");
+ H5Fclose(file_id);
+ CHECK_I(file_id, "H5Fclose");
+ ret_val.attrs2 = h5_get_file_size(FILENAME);
+
+
+ /* Close everything */
+ ret = H5Sclose(attr_space_id);
+ CHECK_I(ret, "H5Sclose");
+ ret = H5Tclose(attr_type_id);
+ CHECK_I(ret, "H5Sclose");
+ ret = H5Tclose(dtype1_id);
+ CHECK_I(ret, "H5Tclose");
+ ret = H5Tclose(dtype2_id);
+ CHECK_I(ret, "H5Tclose");
+ ret = H5Sclose(dspace1_id);
+ CHECK_I(ret, "H5Sclose");
+ ret = H5Sclose(dspace2_id);
+ CHECK_I(ret, "H5Sclose");
+ ret = H5Pclose(dcpl1_id);
+ CHECK_I(ret, "H5Pclose");
+ ret = H5Pclose(dcpl2_id);
+ CHECK_I(ret, "H5Pclose");
+
+ return ret_val;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: size2_verify
+ *
+ * Purpose: A helper functon to verify the file created by size2_helper.
+ *
+ * Runs various tests (not exhaustive) to ensure that the
+ * file FILENAME actually has the structure that size2_helper
+ * should have created.
+ *
+ * Programmer: James Laird
+ * Friday, November 17, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static void size2_verify()
+{
+ hid_t file_id = -1;
+ hid_t dset_id=-1;
+ hid_t plist_id=-1;
+ hid_t space_id=-1;
+ hid_t group1_id, group2_id;
+ hid_t attr1_id, attr2_id;
+ hid_t attr_type_id;
+ int x, y;
+ herr_t ret;
+ char attr_string[NAME_BUF_SIZE];
+ char attr_correct_string[NAME_BUF_SIZE];
+ char attr_name[NAME_BUF_SIZE];
+ int ndims;
+ hsize_t dims[20];
+ hsize_t correct_dims[20] = SIZE2_DIMS;
+
+ file_id = H5Fopen(FILENAME, H5F_ACC_RDONLY, H5P_DEFAULT);
+ CHECK_I(file_id, "H5Fopen");
+
+
+ /* Verify property lists and dataspaces */
+
+ /* Get property lists from first batch of datasets */
+ for(x=0; x<NUM_DATASETS; ++x) {
+ dset_id = H5Dopen(file_id, DSETNAME[x]);
+ CHECK_I(dset_id, "H5Dopen");
+ plist_id = H5Dget_create_plist(dset_id);
+ CHECK_I(plist_id, "H5Dget_create_plist");
+ size2_verify_plist1(plist_id);
+ ret = H5Pclose(plist_id);
+ CHECK_I(ret, "H5Pclose");
+
+ space_id = H5Dget_space(dset_id);
+ CHECK_I(space_id, "H5Dget_space");
+ ndims = H5Sget_simple_extent_dims(space_id, dims, NULL);
+ CHECK_I(ndims, "H5Sget_simple_extent_dims");
+ VERIFY(ndims, SIZE2_RANK1, "H5Sget_simple_extent_dims");
+ for(y=0; y<ndims; ++y) {
+ VERIFY(dims[y], correct_dims[y], "H5Sget_simple_extent_dims");
+ }
+ ret = H5Sclose(space_id);
+ CHECK_I(ret, "H5Sclose");
+
+ ret = H5Dclose(dset_id);
+ CHECK_I(ret, "H5Dclose");
+ }
+ /* Get property lists from second batch of datasets */
+ group1_id = H5Gopen(file_id, "group");
+ CHECK_I(group1_id, "H5Gopen");
+ for(x=0; x<NUM_DATASETS; ++x)
+ {
+ dset_id = H5Dopen(group1_id, DSETNAME[x]);
+ CHECK_I(dset_id, "H5Dopen");
+ plist_id = H5Dget_create_plist(dset_id);
+ CHECK_I(plist_id, "H5Dget_create_plist");
+ size2_verify_plist2(plist_id);
+ ret = H5Pclose(plist_id);
+ CHECK_I(ret, "H5Pclose");
+
+ space_id = H5Dget_space(dset_id);
+ CHECK_I(space_id, "H5Dget_space");
+ ndims = H5Sget_simple_extent_dims(space_id, dims, NULL);
+ CHECK_I(ndims, "H5Sget_simple_extent_dims");
+ VERIFY(ndims, SIZE2_RANK2, "H5Sget_simple_extent_dims");
+ for(y=0; y<ndims; ++y) {
+ VERIFY(dims[y], correct_dims[y], "H5Sget_simple_extent_dims");
+ }
+ ret = H5Sclose(space_id);
+ CHECK_I(ret, "H5Sclose");
+
+ ret = H5Dclose(dset_id);
+ CHECK_I(ret, "H5Dclose");
+ }
+ ret = H5Gclose(group1_id);
+ CHECK_I(ret, "H5Gclose");
+
+ /* Get property lists from interleaved group of datasets */
+ group1_id = H5Gopen(file_id, "interleaved group");
+ CHECK_I(group1_id, "H5Gopen");
+ for(x=0; x<NUM_DATASETS; x += 2) {
+ /* First "type 1" dataset */
+ dset_id = H5Dopen(group1_id, DSETNAME[x]);
+ CHECK_I(dset_id, "H5Dopen");
+ plist_id = H5Dget_create_plist(dset_id);
+ CHECK_I(plist_id, "H5Dget_create_plist");
+ size2_verify_plist1(plist_id);
+ ret = H5Pclose(plist_id);
+ CHECK_I(ret, "H5Pclose");
+
+ space_id = H5Dget_space(dset_id);
+ CHECK_I(space_id, "H5Dget_space");
+ ndims = H5Sget_simple_extent_dims(space_id, dims, NULL);
+ CHECK_I(ndims, "H5Sget_simple_extent_dims");
+ VERIFY(ndims, SIZE2_RANK1, "H5Sget_simple_extent_dims");
+ for(y=0; y<ndims; ++y) {
+ VERIFY(dims[y], correct_dims[y], "H5Sget_simple_extent_dims");
+ }
+ ret = H5Sclose(space_id);
+ CHECK_I(ret, "H5Sclose");
+
+ ret = H5Dclose(dset_id);
+ CHECK_I(ret, "H5Dclose");
+
+ /* Second "type 2" dataset */
+ dset_id = H5Dopen(group1_id, DSETNAME[x+1]);
+ CHECK_I(dset_id, "H5Dopen");
+ plist_id = H5Dget_create_plist(dset_id);
+ CHECK_I(plist_id, "H5Dget_create_plist");
+ size2_verify_plist2(plist_id);
+ ret = H5Pclose(plist_id);
+ CHECK_I(ret, "H5Pclose");
+
+ space_id = H5Dget_space(dset_id);
+ CHECK_I(space_id, "H5Dget_space");
+ ndims = H5Sget_simple_extent_dims(space_id, dims, NULL);
+ CHECK_I(ndims, "H5Sget_simple_extent_dims");
+ VERIFY(ndims, SIZE2_RANK2, "H5Sget_simple_extent_dims");
+ for(y=0; y<ndims; ++y) {
+ VERIFY(dims[y], correct_dims[y], "H5Sget_simple_extent_dims");
+ }
+ ret = H5Sclose(space_id);
+ CHECK_I(ret, "H5Sclose");
+ ret = H5Dclose(dset_id);
+ CHECK_I(ret, "H5Dclose");
+ }
+ ret = H5Gclose(group1_id);
+ CHECK_I(ret, "H5Gclose");
+
+
+ /* Verify attributes */
+
+ /* Create attribute data type */
+ attr_type_id = H5Tcopy(H5T_C_S1);
+ CHECK_I(attr_type_id, "H5Tcopy");
+ ret = H5Tset_size(attr_type_id ,NAME_BUF_SIZE);
+ CHECK_I(ret, "H5Tset_size");
+
+ /* Read attributes on both groups and verify that they are correct */
+ group1_id = H5Gopen(file_id, "group");
+ CHECK_I(group1_id, "H5Gopen");
+ group2_id = H5Gopen(file_id, "interleaved group");
+ CHECK_I(group2_id, "H5Gopen");
+
+ memset(attr_string, 0, NAME_BUF_SIZE);
+ memset(attr_correct_string, 0, NAME_BUF_SIZE);
+ strcpy(attr_correct_string, LONG_STRING);
+ strcpy(attr_name, "00 index");
+
+ for(x=0; x<NUM_ATTRIBUTES; ++x)
+ {
+ /* Create the name and correct value for each attribute */
+ attr_correct_string[0] = attr_name[0] = (x / 10) + '0';
+ attr_correct_string[1] = attr_name[1] = (x % 10) + '0';
+
+ attr1_id = H5Aopen_name(group1_id, attr_name);
+ CHECK_I(attr1_id, "H5Aopen_name");
+ attr2_id = H5Aopen_name(group2_id, attr_name);
+ CHECK_I(attr2_id, "H5Aopen_name");
+
+ ret = H5Aread(attr1_id, attr_type_id, attr_string);
+ CHECK_I(ret, "H5Aread");
+ VERIFY_STR(attr_string, attr_correct_string, "H5Aread");
+ ret = H5Aread(attr2_id, attr_type_id, attr_string);
+ CHECK_I(ret, "H5Aread");
+ VERIFY_STR(attr_string, attr_correct_string, "H5Aread");
+
+ ret = H5Aclose(attr1_id);
+ CHECK_I(attr1_id, "H5Aclose");
+ ret = H5Aclose(attr2_id);
+ CHECK_I(attr2_id, "H5Aclose");
+ }
+
+ /* Close everything */
+ ret = H5Tclose(attr_type_id);
+ CHECK_I(ret, "H5Tclose");
+ ret = H5Gclose(group1_id);
+ CHECK_I(ret, "H5Gclose");
+ ret = H5Gclose(group2_id);
+ CHECK_I(ret, "H5Gclose");
+ ret = H5Fclose(file_id);
+ CHECK_I(ret, "H5Fclose");
+}
+/*-------------------------------------------------------------------------
+ * Function: test_sohm_size2
+ *
+ * Purpose: Tests shared object header messages using size2_helper to
+ * create different kinds of big messages.
+ *
+ * If close_reopen is set, closes and reopens the HDF5 file
+ * repeatedly while writing.
+ *
+ * This test works by first creating FCPLs with various
+ * parameters, then creating a standard file that includes
+ * every kind of message that can be shared using the helper
+ * function size2_helper. The test measures the size of the
+ * file at various points. Once all of the files have been
+ * generated, the test compares the measured sizes of the files.
+ *
+ *
+ * Programmer: James Laird
+ * Friday, November 17, 2006
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void test_sohm_size2(int close_reopen)
+{
+ hid_t fcpl_id = -1;
+ /* Sizes for file with no shared messages at all */
+ size2_helper_struct norm_sizes;
+ /* Sizes for files with all messages in one index */
+ size2_helper_struct list_index_med, list_index_big;
+ size2_helper_struct btree_index, list_index_small;
+ /* Sizes for files with messages in three different indexes */
+ size2_helper_struct mult_index_med, mult_index_btree;
+ /* Sizes for files that don't share all kinds of messages */
+ size2_helper_struct share_some_med, share_some_btree;
+ /* Sizes for files that share different sizes of messages */
+ size2_helper_struct share_some_toobig_index, share_tiny_index, type_space_index;
+ herr_t ret;
+
+ if(close_reopen == 0) {
+ MESSAGE(5, ("Testing that shared object header messages save space\n"));
+ }
+ else {
+ MESSAGE(5, ("Testing that shared messages save space when file is closed and reopened\n"));
+ }
+
+ /* Create an fcpl with SOHMs disabled */
+ fcpl_id = H5Pcreate(H5P_FILE_CREATE);
+ CHECK_I(fcpl_id, "H5Pcreate");
+
+ ret = H5Pset_shared_mesg_nindexes(fcpl_id, 0);
+ CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
+
+ /* Find out what size file this makes */
+ norm_sizes = size2_helper(fcpl_id, close_reopen);
+ /* Check that the file was created correctly */
+ size2_verify();
+
+ ret = H5Pclose(fcpl_id);
+ CHECK_I(ret, "H5Pclose");
+
+
+ /* Create an fcpl with one big index */
+ fcpl_id = H5Pcreate(H5P_FILE_CREATE);
+ CHECK_I(fcpl_id, "H5Pcreate");
+
+ ret = H5Pset_shared_mesg_nindexes(fcpl_id, 1);
+ CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
+ ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_MESG_ALL_FLAG, 20);
+ CHECK_I(ret, "H5Pset_shared_mesg_index");
+
+ /* Set the indexes to use a medium-sized list */
+ ret = H5Pset_shared_mesg_phase_change(fcpl_id, 30, 25);
+ CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
+
+ /* Find out what size file this makes */
+ list_index_med = size2_helper(fcpl_id, close_reopen);
+ /* Check that the file was created correctly */
+ size2_verify();
+
+
+ /* Try making the list really big */
+ ret = H5Pset_shared_mesg_phase_change(fcpl_id, 1000, 900);
+ CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
+
+ /* Find out what size file this makes */
+ list_index_big = size2_helper(fcpl_id, close_reopen);
+ /* Check that the file was created correctly */
+ size2_verify();
+
+
+ /* Use a B-tree instead of a list */
+ ret = H5Pset_shared_mesg_phase_change(fcpl_id, 0, 0);
+ CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
+
+ btree_index = size2_helper(fcpl_id, close_reopen);
+ /* Check that the file was created correctly */
+ size2_verify();
+
+
+ /* Use such a small list that it'll become a B-tree */
+ ret = H5Pset_shared_mesg_phase_change(fcpl_id, 10, 0);
+ CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
+
+ list_index_small = size2_helper(fcpl_id, close_reopen);
+ /* Check that the file was created correctly */
+ size2_verify();
+
+ ret = H5Pclose(fcpl_id);
+ CHECK_I(ret, "H5Pclose");
+
+
+ /* Create a new property list that puts messages in different indexes. */
+ fcpl_id = H5Pcreate(H5P_FILE_CREATE);
+ CHECK_I(fcpl_id, "H5Pcreate");
+
+ /* JAMES: should be zero-indexed? */
+ ret = H5Pset_shared_mesg_nindexes(fcpl_id, 3);
+ CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
+ ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_MESG_SDSPACE_FLAG | H5O_MESG_DTYPE_FLAG, 20);
+ CHECK_I(ret, "H5Pset_shared_mesg_index");
+ ret = H5Pset_shared_mesg_index(fcpl_id, 2, H5O_MESG_FILL_FLAG | H5O_MESG_PLINE_FLAG, 20);
+ CHECK_I(ret, "H5Pset_shared_mesg_index");
+ ret = H5Pset_shared_mesg_index(fcpl_id, 3, H5O_MESG_ATTR_FLAG, 20);
+ CHECK_I(ret, "H5Pset_shared_mesg_index");
+
+ /* Use lists that are the same size as the "medium" list on the previous
+ * run.
+ */
+ ret = H5Pset_shared_mesg_phase_change(fcpl_id, 30, 25);
+ CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
+
+ mult_index_med = size2_helper(fcpl_id, close_reopen);
+ size2_verify();
+
+
+ /* Use all B-trees */
+ ret = H5Pset_shared_mesg_phase_change(fcpl_id, 0, 0);
+ CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
+
+ mult_index_btree = size2_helper(fcpl_id, close_reopen);
+ size2_verify();
+
+
+ ret = H5Pset_shared_mesg_phase_change(fcpl_id, NUM_DATASETS, 0);
+ CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
+
+ /* Edit the same property list (this should work) and don't share all messages.
+ * Also create one index that holds no messages, to make sure this doesn't
+ * break anything.
+ */
+ ret = H5Pset_shared_mesg_nindexes(fcpl_id, 3);
+ CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
+ ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_MESG_PLINE_FLAG, 20);
+ CHECK_I(ret, "H5Pset_shared_mesg_index");
+/* JAMES ret = H5Pset_shared_mesg_index(fcpl_id, 2, H5O_MESG_NONE_FLAG, 20);
+ CHECK_I(ret, "H5Pset_shared_mesg_index");
+*/
+ ret = H5Pset_shared_mesg_index(fcpl_id, 2, H5O_MESG_DTYPE_FLAG | H5O_MESG_FILL_FLAG, 100000);
+ ret = H5Pset_shared_mesg_index(fcpl_id, 3, H5O_MESG_ATTR_FLAG | H5O_MESG_SDSPACE_FLAG, 20);
+ CHECK_I(ret, "H5Pset_shared_mesg_index");
+
+ /* Use "normal-sized" lists. */
+ ret = H5Pset_shared_mesg_phase_change(fcpl_id, 30, 25);
+ CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
+
+ share_some_med = size2_helper(fcpl_id, close_reopen);
+ size2_verify();
+
+ /* Use btrees. */
+ ret = H5Pset_shared_mesg_phase_change(fcpl_id, 0, 0);
+ CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
+
+ share_some_btree = size2_helper(fcpl_id, close_reopen);
+ size2_verify();
+
+
+ /* Change the second index to hold only gigantic messages. Result should
+ * be the same as the previous file.
+ */
+ ret = H5Pset_shared_mesg_index(fcpl_id, 2, H5O_MESG_DTYPE_FLAG | H5O_MESG_FILL_FLAG, 100000);
+ CHECK_I(ret, "H5Pset_shared_mesg_index");
+
+ share_some_toobig_index = size2_helper(fcpl_id, close_reopen);
+ size2_verify();
+
+
+ /* Share even tiny dataspace and datatype messages. This should result in
+ * attribute datatypes being shared. Make this one use "really big" lists.
+ * It turns out that attribute dataspaces are just big enough that it saves
+ * some space to share them, while sharing datatypes creates as much overhead
+ * as one gains from sharing them.
+ */
+ ret = H5Pset_shared_mesg_nindexes(fcpl_id, 1);
+ ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_MESG_DTYPE_FLAG | H5O_MESG_SDSPACE_FLAG, 1);
+ ret = H5Pset_shared_mesg_phase_change(fcpl_id, 1000, 900);
+
+ share_tiny_index = size2_helper(fcpl_id, close_reopen);
+ size2_verify();
+
+ /* Create the same file but don't share the really tiny messages */
+ ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_MESG_DTYPE_FLAG | H5O_MESG_SDSPACE_FLAG, 100);
+ ret = H5Pset_shared_mesg_phase_change(fcpl_id, 1000, 900);
+
+ type_space_index = size2_helper(fcpl_id, close_reopen);
+ size2_verify();
+
+ ret = H5Pclose(fcpl_id);
+ CHECK_I(ret, "H5Pclose");
+
+
+
+ /* Check that all sizes make sense. There is lots of room for inexact
+ * results here since so many different factors contribute to file size.
+ */
+
+
+ /* Check sizes of all files created using a single index first */
+
+ /* The empty size of each file with shared messages enabled should be the
+ * same and should be bigger than a normal file.
+ */
+ if(norm_sizes.empty_size > list_index_med.empty_size)
+ VERIFY(norm_sizes.empty_size, 1, "h5_get_file_size");
+ if(list_index_med.empty_size != list_index_big.empty_size)
+ VERIFY(list_index_med.empty_size, list_index_big.empty_size, "h5_get_file_size");
+ if(list_index_med.empty_size != btree_index.empty_size)
+ VERIFY(list_index_med.empty_size, btree_index.empty_size, "h5_get_file_size");
+ if(list_index_med.empty_size != list_index_small.empty_size)
+ VERIFY(list_index_med.empty_size, list_index_small.empty_size, "h5_get_file_size");
+ /* The files with indexes shouldn't be that much bigger than an
+ * empty file.
+ */
+ if(list_index_med.empty_size > norm_sizes.empty_size * OVERHEAD_ALLOWED)
+ VERIFY(0, 1, "h5_get_file_size");
+
+
+ /* Once one dataset has been created (with one of every kind of message),
+ * the normal file should still be smallest. The very small list
+ * btree_convert should be smaller than the B-tree since it has no
+ * extra overhead. The small list should also be smaller than the B-tree.
+ * The very large list should be much larger than anything else.
+ */
+ if(norm_sizes.first_dset >= list_index_small.first_dset)
+ VERIFY(norm_sizes.first_dset, 1, "h5_get_file_size");
+ if(list_index_small.first_dset >= btree_index.first_dset)
+ VERIFY(list_index_small.first_dset, 1, "h5_get_file_size");
+ if(list_index_med.first_dset >= btree_index.first_dset)
+ VERIFY(btree_index.first_dset, 1, "h5_get_file_size");
+ if(btree_index.first_dset >= list_index_big.first_dset)
+ VERIFY(list_index_med.first_dset, 1, "h5_get_file_size");
+
+
+ /* Once a few copies of the same dataset have been created, the
+ * very small list shouldn't have become a B-tree yet, so it should
+ * be the smallest file. A larger list should be next, followed
+ * by a B-tree, followed by a normal file, followed by a
+ * list that is too large.
+ */
+ if(list_index_small.dsets1 >= list_index_med.dsets1)
+ VERIFY(btree_index.dsets1, 1, "h5_get_file_size");
+ if(list_index_med.dsets1 >= btree_index.dsets1)
+ VERIFY(list_index_med.dsets1, 1, "h5_get_file_size");
+ if(btree_index.dsets1 >= norm_sizes.dsets1)
+ VERIFY(btree_index.dsets1, 1, "h5_get_file_size");
+ if(norm_sizes.dsets1 >= list_index_big.dsets1)
+ VERIFY(list_index_big.dsets1, 1, "h5_get_file_size");
+
+ /* The size gain should have been the same for each of the lists;
+ * their overhead is fixed. The B-tree should have gained at least
+ * as much, and the normal file more than that.
+ */
+ if((list_index_small.dsets1 - list_index_small.first_dset) !=
+ (list_index_med.dsets1 - list_index_med.first_dset))
+ VERIFY(0, 1, "h5_get_file_size");
+ if((list_index_med.dsets1 - list_index_med.first_dset) !=
+ (list_index_big.dsets1 - list_index_big.first_dset))
+ VERIFY(0, 1, "h5_get_file_size");
+ if((list_index_big.dsets1 - list_index_big.first_dset) >
+ (btree_index.dsets1 - btree_index.first_dset))
+ VERIFY(0, 1, "h5_get_file_size");
+ if((btree_index.dsets1 - btree_index.first_dset) >=
+ (norm_sizes.dsets1 - norm_sizes.first_dset))
+ VERIFY(0, 1, "h5_get_file_size");
+
+
+ /* Once another kind of each message has been written, the very small list
+ * should convert into a B-tree. Now the list should be smallest, then
+ * the B-trees (although the converted B-tree file may be a little bigger),
+ * then the normal file. The largest list may or may not be bigger than
+ * the normal file.
+ */
+ if(list_index_med.dsets2 >= btree_index.dsets2)
+ VERIFY(list_index_med.dsets2, 1, "h5_get_file_size");
+ if(btree_index.dsets2 > list_index_small.dsets2)
+ VERIFY(btree_index.dsets2, 1, "h5_get_file_size");
+ if(list_index_small.dsets2 >= norm_sizes.dsets2)
+ VERIFY(btree_index.dsets2, 1, "h5_get_file_size");
+ /* If the small list (now a B-tree) is bigger than the existing B-tree,
+ * it shouldn't be much bigger.
+ * It seems that the small lists tends to be pretty big anyway. Allow
+ * for it to have twice as much overhead.
+ */
+ if(list_index_small.dsets2 > btree_index.dsets2 * OVERHEAD_ALLOWED * OVERHEAD_ALLOWED)
+ VERIFY(0, 1, "h5_get_file_size");
+ /* The lists should have grown the least since they share messages and
+ * have no extra overhead. The normal file should have grown more than
+ * either the lists or the B-tree. The B-tree may not have grown more
+ * than the lists, depending on whether it needed to split nodes or not.
+ */
+ if((list_index_med.dsets2 - list_index_med.dsets1) !=
+ (list_index_big.dsets2 - list_index_big.dsets1))
+ VERIFY(0, 1, "h5_get_file_size");
+ if((list_index_big.dsets2 - list_index_big.dsets1) >
+ (btree_index.dsets2 - btree_index.dsets1))
+ VERIFY(0, 1, "h5_get_file_size");
+ if((btree_index.dsets2 - btree_index.dsets1) >=
+ (norm_sizes.dsets2 - norm_sizes.dsets1))
+ VERIFY(0, 1, "h5_get_file_size");
+
+
+ /* Interleaving the writes should have no effect on how the messages are
+ * shared. No new messages should be written to the indexes, so the
+ * sohm files will only get a little bit bigger.
+ */
+ if(list_index_med.interleaved >= btree_index.interleaved)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(btree_index.interleaved > list_index_small.interleaved)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(list_index_small.interleaved >= norm_sizes.interleaved)
+ VERIFY(0, 1, "h5_get_file_size");
+ /* The lists should still have grown the same amount. The converted
+ * B-tree shouldn't have grown more than the index that was originally
+ * a B-tree (although it might have grown less if there was extra free
+ * space within the file).
+ */
+ if((list_index_med.interleaved - list_index_med.dsets2) !=
+ (list_index_big.interleaved - list_index_big.dsets2))
+ VERIFY(0, 1, "h5_get_file_size");
+ if((list_index_big.interleaved - list_index_big.dsets2) >
+ (btree_index.interleaved - btree_index.dsets2))
+ VERIFY(0, 1, "h5_get_file_size");
+ if((list_index_small.interleaved - list_index_small.dsets2) >
+ (btree_index.interleaved - btree_index.dsets2))
+ VERIFY(0, 1, "h5_get_file_size");
+ if((btree_index.interleaved - btree_index.dsets2) >=
+ (norm_sizes.interleaved - norm_sizes.dsets2))
+ VERIFY(0, 1, "h5_get_file_size");
+
+ /* After many attributes have been written, both the small and medium lists
+ * should have become B-trees and be about the same size as the index
+ * that started as a B-tree.
+ * Add in OVERHEAD_ALLOWED as a fudge factor here, since the allocation
+ * of file space can be hard to predict.
+
+ */
+ if(btree_index.attrs1 > list_index_small.attrs1)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(btree_index.attrs1 > list_index_med.attrs1)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(list_index_med.attrs1 > btree_index.attrs1 * OVERHEAD_ALLOWED)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(list_index_small.attrs1 > btree_index.attrs1 * OVERHEAD_ALLOWED)
+ VERIFY(0, 1, "h5_get_file_size");
+ /* Neither of the converted lists should be too much bigger than
+ * the index that was originally a B-tree.
+ */
+ if(list_index_small.attrs1 > btree_index.attrs1 * OVERHEAD_ALLOWED)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(list_index_med.attrs1 > btree_index.attrs1 * OVERHEAD_ALLOWED)
+ VERIFY(0, 1, "h5_get_file_size");
+ /* The "normal" file should have had less overhead, so should gain less
+ * size than any of the other indexes since none of these attribute
+ * messages could be shared. The large list should have gained
+ * less overhead than the B-tree indexes.
+ */
+ if((norm_sizes.attrs1 - norm_sizes.interleaved) >=
+ (list_index_big.attrs1 - list_index_big.interleaved))
+ VERIFY(0, 1, "h5_get_file_size");
+ if((list_index_big.attrs1 - list_index_big.interleaved) >=
+ (list_index_small.attrs1 - list_index_small.interleaved))
+ VERIFY(0, 1, "h5_get_file_size");
+ if((list_index_small.attrs1 - list_index_small.interleaved) >
+ (btree_index.attrs1 - btree_index.interleaved))
+ VERIFY(0, 1, "h5_get_file_size");
+
+
+ /* Writing another copy of each attribute shouldn't change the ordering
+ * of sizes. The big list index is still too big to be smaller than a
+ * normal file. The B-tree indexes should all be about the same size.
+ */
+ if(btree_index.attrs2 > list_index_small.attrs2)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(list_index_small.attrs2 > btree_index.attrs2 * OVERHEAD_ALLOWED)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(btree_index.attrs2 > list_index_med.attrs2)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(list_index_med.attrs2 > btree_index.attrs2 * OVERHEAD_ALLOWED)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(list_index_med.attrs2 >= norm_sizes.attrs2)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(list_index_big.attrs2 >= norm_sizes.attrs2)
+ VERIFY(0, 1, "h5_get_file_size");
+ /* All of the B-tree indexes should have gained about the same amount
+ * of space; at least as much as the list index and less than a normal
+ * file.
+ */
+ if((list_index_small.attrs2 - list_index_small.attrs1) >
+ (btree_index.attrs2 - btree_index.attrs1))
+ VERIFY(0, 1, "h5_get_file_size");
+ if((list_index_med.attrs2 - list_index_med.attrs1) >
+ (btree_index.attrs2 - btree_index.attrs1))
+ VERIFY(0, 1, "h5_get_file_size");
+ if((list_index_big.attrs2 - list_index_big.attrs1) >
+ (list_index_med.attrs2 - list_index_med.attrs1))
+ VERIFY(0, 1, "h5_get_file_size");
+ if((btree_index.attrs2 - btree_index.attrs1) >=
+ (norm_sizes.attrs2 - norm_sizes.attrs1))
+ VERIFY(0, 1, "h5_get_file_size");
+
+ /* Done checking the first few files that use a single index. */
+
+
+ /* Start comparing other kinds of files with these "standard"
+ * one-index files
+ */
+
+ /* Check files with multiple indexes. */
+ /* These files should be larger when first created than one-index
+ * files.
+ */
+ if(mult_index_med.empty_size <= list_index_med.empty_size)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(mult_index_btree.empty_size != mult_index_med.empty_size)
+ VERIFY(0, 1, "h5_get_file_size");
+
+ /* When the first dataset is written, they should grow quite a bit as
+ * many different indexes must be created.
+ */
+ if(mult_index_med.first_dset - mult_index_med.empty_size <=
+ list_index_med.first_dset - list_index_med.empty_size)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(mult_index_btree.first_dset - mult_index_btree.empty_size <=
+ btree_index.first_dset - btree_index.empty_size)
+ VERIFY(0, 1, "h5_get_file_size");
+
+ /* Once that initial overhead is out of the way and the lists/btrees
+ * have been created, files with more than one index should grow at
+ * the same rate or slightly faster than files with just one index
+ * and one heap.
+ */
+ if(mult_index_med.dsets1 - mult_index_med.first_dset !=
+ list_index_med.dsets1 - list_index_med.first_dset)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(mult_index_btree.dsets1 - mult_index_btree.first_dset !=
+ btree_index.dsets1 - btree_index.first_dset)
+ VERIFY(0, 1, "h5_get_file_size");
+
+ if(mult_index_med.dsets2 - mult_index_med.dsets1 >
+ (list_index_med.dsets2 - list_index_med.dsets1) * OVERHEAD_ALLOWED)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(mult_index_med.dsets2 - mult_index_med.dsets1 <
+ list_index_med.dsets2 - list_index_med.dsets1)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(mult_index_btree.dsets2 - mult_index_btree.dsets1 >
+ (btree_index.dsets2 - btree_index.dsets1) * OVERHEAD_ALLOWED)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(mult_index_btree.dsets2 - mult_index_btree.dsets1 <
+ btree_index.dsets2 - btree_index.dsets1)
+ VERIFY(0, 1, "h5_get_file_size");
+
+ if(mult_index_med.interleaved - mult_index_med.dsets2 !=
+ list_index_med.interleaved - list_index_med.dsets2)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(mult_index_btree.interleaved - mult_index_btree.dsets2 !=
+ btree_index.interleaved - btree_index.dsets2)
+ VERIFY(0, 1, "h5_get_file_size");
+
+ /* When all the attributes are added, only the index holding attributes
+ * will become a B-tree. Skip the interleaved to attrs1 interval when
+ * this happens because it's hard to predict exactly how much space this
+ * will take.
+ */
+ if(mult_index_med.attrs2 - mult_index_med.attrs1 !=
+ list_index_med.attrs2 - list_index_med.attrs1)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(mult_index_btree.attrs2 - mult_index_btree.attrs1 !=
+ btree_index.attrs2 - btree_index.attrs1)
+ VERIFY(0, 1, "h5_get_file_size");
+
+ /* The final file size for both of the multiple index files should be
+ * smaller than a normal file but bigger than any of the one-index files.
+ */
+ if(mult_index_med.attrs2 >= norm_sizes.attrs2)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(mult_index_btree.attrs2 >= norm_sizes.attrs2)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(mult_index_med.attrs2 * OVERHEAD_ALLOWED < btree_index.attrs2)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(mult_index_btree.attrs2 * OVERHEAD_ALLOWED < btree_index.attrs2)
+ VERIFY(0, 1, "h5_get_file_size");
+
+
+ /* Check files that don't share all messages. */
+ /* These files have three indexes like the files above, so they should be
+ * the same size when created.
+ */
+ if(share_some_med.empty_size != mult_index_med.empty_size)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(share_some_med.empty_size != share_some_btree.empty_size)
+ VERIFY(0, 1, "h5_get_file_size");
+
+ /* When the first dataset is created, they should be not quite as big
+ * as equivalent files that share all messages (since shared messages
+ * have a little bit of overhead).
+ */
+ if(share_some_med.first_dset >= mult_index_med.first_dset)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(share_some_btree.first_dset >= mult_index_btree.first_dset)
+ VERIFY(0, 1, "h5_get_file_size");
+
+ /* The files that share some should have a growth rate in between
+ * files that share all messages and normal files
+ */
+ if(share_some_med.interleaved - share_some_med.first_dset <=
+ mult_index_med.interleaved - mult_index_med.first_dset)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(share_some_med.interleaved - share_some_med.first_dset >=
+ norm_sizes.interleaved - norm_sizes.first_dset)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(share_some_btree.interleaved - share_some_btree.first_dset <=
+ mult_index_btree.interleaved - mult_index_btree.first_dset)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(share_some_btree.interleaved - share_some_btree.first_dset >=
+ norm_sizes.interleaved - norm_sizes.first_dset)
+ VERIFY(0, 1, "h5_get_file_size");
+
+
+ /* Check the file that only stored gigantic messages in its second
+ * index. Since no messages were that big, it should be identical
+ * to the file with an empty index.
+ */
+ if(share_some_btree.empty_size != share_some_toobig_index.empty_size)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(share_some_btree.first_dset != share_some_toobig_index.first_dset)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(share_some_btree.dsets1 != share_some_toobig_index.dsets1)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(share_some_btree.dsets2 != share_some_toobig_index.dsets2)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(share_some_btree.interleaved != share_some_toobig_index.interleaved)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(share_some_btree.attrs1 != share_some_toobig_index.attrs1)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(share_some_btree.attrs2 != share_some_toobig_index.attrs2)
+ VERIFY(0, 1, "h5_get_file_size");
+
+
+ /* Check the file that shares even very tiny messages. Once messages
+ * are written to it, it should gain a little space from sharing the
+ * messages and lose a little space to overhead so that it's just slightly
+ * smaller than a file that doesn't share tiny messages.
+ * If the overhead increases or the size of messages decreases, these
+ * numbers may be off.
+ */
+ if(share_tiny_index.empty_size != type_space_index.empty_size)
+ VERIFY(0, 1, "h5_get_file_size");
+
+ if(share_tiny_index.first_dset >= type_space_index.first_dset)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(share_tiny_index.first_dset * OVERHEAD_ALLOWED < type_space_index.first_dset)
+ VERIFY(0, 1, "h5_get_file_size");
+
+ if(share_tiny_index.dsets1 >= type_space_index.dsets1)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(share_tiny_index.dsets1 * OVERHEAD_ALLOWED < type_space_index.dsets1)
+ VERIFY(0, 1, "h5_get_file_size");
+
+ if(share_tiny_index.dsets2 >= type_space_index.dsets2)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(share_tiny_index.dsets2 * OVERHEAD_ALLOWED < type_space_index.dsets2)
+ VERIFY(0, 1, "h5_get_file_size");
+
+ if(share_tiny_index.interleaved >= type_space_index.interleaved)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(share_tiny_index.interleaved * OVERHEAD_ALLOWED < type_space_index.interleaved)
+ VERIFY(0, 1, "h5_get_file_size");
+
+ if(share_tiny_index.attrs1 >= type_space_index.attrs1)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(share_tiny_index.attrs1 * OVERHEAD_ALLOWED < type_space_index.attrs1)
+ VERIFY(0, 1, "h5_get_file_size");
+
+ if(share_tiny_index.attrs2 >= type_space_index.attrs2)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(share_tiny_index.attrs2 * OVERHEAD_ALLOWED < type_space_index.attrs2)
+ VERIFY(0, 1, "h5_get_file_size");
+}
+
+
+
/****************************************************************
-**
+**
** test_sohm(): Main Shared Object Header Message testing routine.
**
****************************************************************/
@@ -256,7 +2442,11 @@ test_sohm(void)
MESSAGE(5, ("Testing Shared Object Header Messages\n"));
test_sohm_fcpl(); /* Test SOHMs and file creation plists */
- /* JAMES: test SOHMs and H5*copy (especially when file SOHM properties differ */
+ test_sohm_size1(); /* Tests the sizes of files with one SOHM */
+ test_sohm_attrs(); /* Tests shared messages in attributes */
+ test_sohm_size2(0); /* Tests the sizes of files with multiple SOHMs */
+ test_sohm_size2(1); /* Tests the sizes of files with multiple SOHMs */
+
} /* test_sohm() */