From b6c317f27cd150aa7bfc4e9cf275629570c9a319 Mon Sep 17 00:00:00 2001 From: James Laird Date: Mon, 13 Nov 2006 15:41:36 -0500 Subject: [svn-r12902] Checkin of Shared Object Header Message work. This feature is still in progress; Shared Object Header Messages are not complete as a feature and are not thoroughly tested. There are still "TODO" comments in the code (comments with the word "JAMES" in them, so as not to be confused with other TODO comments). Hopefully this checkin will reduce the liklihood of conflicts as I finish implementing this feature. All current tests pass on juniper, copper (parallel), heping, kagiso, and mir. --- src/H5A.c | 66 ++- src/H5AC.c | 2 + src/H5ACprivate.h | 2 + src/H5Apkg.h | 1 + src/H5B2private.h | 1 + src/H5Cpkg.h | 2 +- src/H5D.c | 16 +- src/H5Edefin.h | 15 +- src/H5Einit.h | 59 +-- src/H5Epubgen.h | 26 +- src/H5Eterm.h | 15 +- src/H5F.c | 56 ++- src/H5FDmulti.c | 7 +- src/H5FDpublic.h | 1 + src/H5Fdbg.c | 2 + src/H5Fpkg.h | 1 + src/H5Fprivate.h | 6 + src/H5Fsuper.c | 58 ++- src/H5HG.c | 7 +- src/H5O.c | 713 +++++++++++++++++++++++++------ src/H5Oattr.c | 248 +++++++++-- src/H5Ocont.c | 55 +-- src/H5Odtype.c | 76 +++- src/H5Oefl.c | 10 +- src/H5Ofill.c | 154 ++++++- src/H5Oginfo.c | 1 + src/H5Olayout.c | 10 +- src/H5Olinfo.c | 11 +- src/H5Olink.c | 11 +- src/H5Omtime.c | 2 + src/H5Oname.c | 1 + src/H5Opkg.h | 6 +- src/H5Opline.c | 109 ++++- src/H5Oprivate.h | 81 +++- src/H5Opublic.h | 3 +- src/H5Osdspace.c | 110 ++++- src/H5Oshared.c | 334 ++++++++++++--- src/H5Ostab.c | 10 +- src/H5Pfcpl.c | 353 ++++++++++++++- src/H5Plapl.c | 2 +- src/H5Ppublic.h | 8 + src/H5R.c | 1 + src/H5S.c | 14 + src/H5SM.c | 997 +++++++++++++++++++++++++++++++++++++++++++ src/H5SMbtree2.c | 351 +++++++++++++++ src/H5SMcache.c | 626 +++++++++++++++++++++++++++ src/H5SMpkg.h | 174 ++++++++ src/H5SMprivate.h | 59 +++ src/H5SMpublic.h | 42 ++ src/H5Spkg.h | 1 + src/H5T.c | 84 ++-- src/H5Tcommit.c | 71 +-- src/H5Tpkg.h | 6 +- src/H5Tprivate.h | 4 + src/H5err.txt | 1 + src/H5private.h | 4 +- src/Makefile.am | 6 +- src/Makefile.in | 24 +- src/hdf5.h | 1 + test/Makefile.am | 2 +- test/Makefile.in | 8 +- test/h5test.c | 4 +- test/objcopy.c | 100 +++-- test/tattr.c | 15 +- test/testhdf5.c | 1 + test/testhdf5.h | 3 +- test/tfile.c | 5 +- test/th5s.c | 4 + test/tmisc.c | 26 +- test/trefer.c | 2 +- tools/h5dump/h5dumpgentest.c | 2 +- 71 files changed, 4731 insertions(+), 558 deletions(-) create mode 100755 src/H5SM.c create mode 100755 src/H5SMbtree2.c create mode 100644 src/H5SMcache.c create mode 100755 src/H5SMpkg.h create mode 100755 src/H5SMprivate.h create mode 100755 src/H5SMpublic.h diff --git a/src/H5A.c b/src/H5A.c index 0fd4706..ea62fb7 100644 --- a/src/H5A.c +++ b/src/H5A.c @@ -27,6 +27,7 @@ #include "H5Iprivate.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ #include "H5Sprivate.h" /* Dataspace functions */ +#include "H5SMprivate.h" /* Shared Object Header Messages */ /* PRIVATE PROTOTYPES */ static hid_t H5A_create(const H5G_loc_t *loc, const char *name, @@ -224,7 +225,9 @@ H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type, H5A_t *attr = NULL; H5A_iter_cb1 cb; /* Iterator callback */ H5P_genplist_t *ac_plist=NULL; /* New Property list */ - hid_t ret_value = FAIL; + H5O_shared_t sh_mesg; + htri_t tri_ret; /* htri_t return value */ + hid_t ret_value = FAIL; FUNC_ENTER_NOAPI_NOINIT(H5A_create) @@ -234,6 +237,9 @@ H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type, HDassert(type); HDassert(space); + /* Reset shared message information */ + HDmemset(&sh_mesg,0,sizeof(H5O_shared_t)); + /* Iterate over the existing attributes to check for duplicates */ cb.name = name; cb.idx = (-1); @@ -287,24 +293,57 @@ H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type, if(H5G_name_copy(&(attr->path), loc->path, H5_COPY_DEEP) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to copy path") - /* Compute the size of pieces on disk */ - if(H5T_committed(attr->dt)) { - H5O_shared_t sh_mesg; + /* Check if any of the pieces should be (or are already) shared in the + * SOHM table */ + /* Data type */ + if(H5SM_try_share(attr->oloc.file, dxpl_id, H5O_DTYPE_ID, attr->dt) <0) + HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "trying to share datatype failed"); - /* Reset shared message information */ - HDmemset(&sh_mesg,0,sizeof(H5O_shared_t)); + /* Data space */ + if(H5SM_try_share(attr->oloc.file, dxpl_id, H5O_SDSPACE_ID, attr->ds) <0) + HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "trying to share dataspace failed"); - /* Get shared message information for datatype */ - if(H5O_get_share(H5O_DTYPE_ID, attr->oloc.file, type, &sh_mesg/*out*/) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to copy entry") - /* Compute shared message size for datatype */ + /* Compute the size of pieces on disk. This is either the size of the + * datatype and dataspace messages themselves, or the size of the "shared" + * messages if either or both of them are shared. + */ + if((tri_ret = H5O_is_shared(H5O_DTYPE_ID, attr->dt)) == FALSE) + { + /* Message wasn't shared after all. Use size of normal datatype + * message. */ + attr->dt_size = H5O_raw_size(H5O_DTYPE_ID, attr->oloc.file, attr->dt); + } + else if(tri_ret > 0) + { + /* Message is shared. Use size of shared message */ + if(H5O_get_share(H5O_DTYPE_ID, attr->oloc.file, attr->dt, &sh_mesg) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "couldn't get size of shared message") + attr->dt_size = H5O_raw_size(H5O_SHARED_ID, attr->oloc.file, &sh_mesg); - } /* end if */ + } else - attr->dt_size = H5O_raw_size(H5O_DTYPE_ID, attr->oloc.file, type); + HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "couldn't determine if dataspace is shared") + + /* Perform the same test for the dataspace message */ + if((tri_ret = H5O_is_shared(H5O_SDSPACE_ID, attr->ds)) == FALSE) + { + /* Message wasn't shared after all. Use size of normal dataspace + * message. */ + attr->ds_size = H5O_raw_size(H5O_SDSPACE_ID, attr->oloc.file, attr->ds); + } + else if(tri_ret > 0) + { + /* Message is shared. Use size of shared message */ + if(H5O_get_share(H5O_SDSPACE_ID, attr->oloc.file, attr->ds, &sh_mesg) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "couldn't get size of shared message") + + attr->ds_size = H5O_raw_size(H5O_SHARED_ID, attr->oloc.file, &sh_mesg); + } + else + HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "couldn't determine if datatype is shared") + HDassert(attr->dt_size > 0); - attr->ds_size = H5S_raw_size(attr->oloc.file, space); HDassert(attr->ds_size > 0); H5_ASSIGN_OVERFLOW(attr->data_size, H5S_GET_EXTENT_NPOINTS(attr->ds) * H5T_get_size(attr->dt), hssize_t, size_t); @@ -1617,6 +1656,7 @@ H5A_free(H5A_t *attr) /* Free dynamicly allocated items */ if(attr->name) H5MM_xfree(attr->name); + if(attr->dt) if(H5T_close(attr->dt) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release datatype info") diff --git a/src/H5AC.c b/src/H5AC.c index 454078f..1435cc5 100644 --- a/src/H5AC.c +++ b/src/H5AC.c @@ -488,6 +488,8 @@ static const char * H5AC_entry_type_names[H5AC_NTYPES] = "fractal heap indirect blocks", "free space headers", "free space sections", + "shared OH message master table", + "shared OH message index", "test entry" /* for testing only -- not used for actual files */ }; diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h index dab3cf2..eeccb6b 100644 --- a/src/H5ACprivate.h +++ b/src/H5ACprivate.h @@ -59,6 +59,8 @@ typedef enum { H5AC_FHEAP_IBLOCK_ID, /*fractal heap indirect block */ H5AC_FSPACE_HDR_ID, /*free space header */ H5AC_FSPACE_SINFO_ID,/*free space sections */ + H5AC_SOHM_TABLE_ID, /*shared object header message master table */ + H5AC_SOHM_LIST_ID, /*shared message index stored as a list */ H5AC_TEST_ID, /*test entry -- not used for actual files */ H5AC_NTYPES /* Number of types, must be last */ } H5AC_type_t; diff --git a/src/H5Apkg.h b/src/H5Apkg.h index cd54ac4..b8babf9 100644 --- a/src/H5Apkg.h +++ b/src/H5Apkg.h @@ -56,6 +56,7 @@ struct H5A_t { void *data; /* Attribute data (on a temporary basis) */ size_t data_size; /* Size of data on disk */ H5T_cset_t encoding; /* Character encoding of attribute */ + H5O_shared_t sh_loc; /*location of shared message */ }; /* Declare extern the free list for H5A_t's */ diff --git a/src/H5B2private.h b/src/H5B2private.h index c262056..4973dc2 100644 --- a/src/H5B2private.h +++ b/src/H5B2private.h @@ -58,6 +58,7 @@ typedef enum H5B2_subid_t { H5B2_FHEAP_HUGE_FILT_DIR_ID, /* B-tree is for fractal heap directly accessed, filtered 'huge' objects */ H5B2_GRP_DENSE_NAME_ID, /* B-tree is for indexing 'name' field for "dense" link storage in groups */ H5B2_GRP_DENSE_CORDER_ID, /* B-tree is for indexing 'creation order' field for "dense" link storage in groups */ + H5B2_SOHM_INDEX_ID, /* B-tree is an index for shared object header messages */ H5B2_NUM_BTREE_ID /* Number of B-tree IDs (must be last) */ } H5B2_subid_t; diff --git a/src/H5Cpkg.h b/src/H5Cpkg.h index 4dd3547..7a14025 100644 --- a/src/H5Cpkg.h +++ b/src/H5Cpkg.h @@ -758,7 +758,7 @@ ****************************************************************************/ #define H5C__H5C_T_MAGIC 0x005CAC0E -#define H5C__MAX_NUM_TYPE_IDS 14 +#define H5C__MAX_NUM_TYPE_IDS 16 #define H5C__PREFIX_LEN 32 struct H5C_t diff --git a/src/H5D.c b/src/H5D.c index 6eafeec..6ff85c0 100644 --- a/src/H5D.c +++ b/src/H5D.c @@ -1185,7 +1185,7 @@ H5D_update_entry_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset, H5P_genplist_t *p /* fill value variables */ H5D_fill_time_t fill_time; H5O_fill_t *fill_prop; /* Pointer to dataset's fill value information */ - H5O_fill_new_t fill = { NULL, 0, NULL, H5D_ALLOC_TIME_LATE, H5D_FILL_TIME_ALLOC, TRUE }; + H5O_fill_new_t fill; H5D_fill_value_t fill_status; struct H5O_t *oh = NULL; /* Pointer to dataset's object header */ @@ -1209,6 +1209,12 @@ H5D_update_entry_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset, H5P_genplist_t *p /* Get the file's 'use the latest version of the format' flag */ use_latest_format = H5F_USE_LATEST_FORMAT(file); + /* Initialize the fill value message */ + HDmemset(&fill,0,sizeof(H5O_fill_new_t)); + fill.alloc_time = H5D_ALLOC_TIME_LATE; + fill.fill_time = H5D_FILL_TIME_ALLOC; + fill.fill_defined = TRUE; + /* Point at dataset's copy, to cache it for later */ fill_prop = &dset->shared->fill; fill_time = dset->shared->fill_time; @@ -1845,7 +1851,7 @@ done: static herr_t H5D_open_oid(H5D_t *dataset, hid_t dxpl_id) { - H5O_fill_new_t fill = {NULL, 0, NULL, H5D_ALLOC_TIME_LATE, H5D_FILL_TIME_IFSET, TRUE}; + H5O_fill_new_t fill; unsigned alloc_time_state; /* Allocation time state */ H5O_fill_t *fill_prop; /* Pointer to dataset's fill value area */ H5O_pline_t pline; /* I/O pipeline information */ @@ -1861,6 +1867,12 @@ H5D_open_oid(H5D_t *dataset, hid_t dxpl_id) if(NULL == (dataset->shared = H5D_new(H5P_DATASET_CREATE_DEFAULT, FALSE, FALSE))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + /* Initialize the fill value message JAMES: initialize above instead? */ + HDmemset(&fill,0,sizeof(H5O_fill_new_t)); + fill.alloc_time = H5D_ALLOC_TIME_LATE; + fill.fill_time = H5D_FILL_TIME_IFSET; + fill.fill_defined = TRUE; + /* Open the dataset object */ if(H5O_open(&(dataset->oloc)) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "unable to open") diff --git a/src/H5Edefin.h b/src/H5Edefin.h index 72441c7..f54228e 100644 --- a/src/H5Edefin.h +++ b/src/H5Edefin.h @@ -24,6 +24,7 @@ hid_t H5E_DATASET_g = FAIL; /* Dataset */ hid_t H5E_FUNC_g = FAIL; /* Function entry/exit */ hid_t H5E_STORAGE_g = FAIL; /* Data storage */ hid_t H5E_FILE_g = FAIL; /* File accessability */ +hid_t H5E_SOHM_g = FAIL; /* Shared Object Header Messages */ hid_t H5E_SYM_g = FAIL; /* Symbol table */ hid_t H5E_VFL_g = FAIL; /* Virtual File Layer */ hid_t H5E_INTERNAL_g = FAIL; /* Internal error (too specific to document in detail) */ @@ -181,13 +182,6 @@ hid_t H5E_CANTNEXT_g = FAIL; /* Can't move to next iterator location hid_t H5E_BADSELECT_g = FAIL; /* Invalid selection */ hid_t H5E_CANTCOMPARE_g = FAIL; /* Can't compare objects */ -/* Argument errors */ -hid_t H5E_UNINITIALIZED_g = FAIL; /* Information is uinitialized */ -hid_t H5E_UNSUPPORTED_g = FAIL; /* Feature is unsupported */ -hid_t H5E_BADTYPE_g = FAIL; /* Inappropriate type */ -hid_t H5E_BADRANGE_g = FAIL; /* Out of range */ -hid_t H5E_BADVALUE_g = FAIL; /* Bad value */ - /* B-tree related errors */ hid_t H5E_NOTFOUND_g = FAIL; /* Object not found */ hid_t H5E_EXISTS_g = FAIL; /* Object already exists */ @@ -201,6 +195,13 @@ hid_t H5E_CANTLIST_g = FAIL; /* Unable to list node */ hid_t H5E_CANTMODIFY_g = FAIL; /* Unable to modify record */ hid_t H5E_CANTREMOVE_g = FAIL; /* Unable to remove object */ +/* Argument errors */ +hid_t H5E_UNINITIALIZED_g = FAIL; /* Information is uinitialized */ +hid_t H5E_UNSUPPORTED_g = FAIL; /* Feature is unsupported */ +hid_t H5E_BADTYPE_g = FAIL; /* Inappropriate type */ +hid_t H5E_BADRANGE_g = FAIL; /* Out of range */ +hid_t H5E_BADVALUE_g = FAIL; /* Bad value */ + /* Datatype conversion errors */ hid_t H5E_CANTCONVERT_g = FAIL; /* Can't convert datatypes */ hid_t H5E_BADSIZE_g = FAIL; /* Bad size for object */ diff --git a/src/H5Einit.h b/src/H5Einit.h index 3cd9ea1..2da01ba 100644 --- a/src/H5Einit.h +++ b/src/H5Einit.h @@ -43,6 +43,11 @@ if((msg = H5E_create_msg(cls, H5E_MAJOR, "File accessability"))==NULL) HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") if((H5E_FILE_g = H5I_register(H5I_ERROR_MSG, msg))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") +assert(H5E_SOHM_g==(-1)); +if((msg = H5E_create_msg(cls, H5E_MAJOR, "Shared Object Header Messages"))==NULL) + HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") +if((H5E_SOHM_g = H5I_register(H5I_ERROR_MSG, msg))<0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") assert(H5E_SYM_g==(-1)); if((msg = H5E_create_msg(cls, H5E_MAJOR, "Symbol table"))==NULL) HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") @@ -683,33 +688,6 @@ if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't compare objects"))==NULL) if((H5E_CANTCOMPARE_g = H5I_register(H5I_ERROR_MSG, msg))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") -/* Argument errors */ -assert(H5E_UNINITIALIZED_g==(-1)); -if((msg = H5E_create_msg(cls, H5E_MINOR, "Information is uinitialized"))==NULL) - HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") -if((H5E_UNINITIALIZED_g = H5I_register(H5I_ERROR_MSG, msg))<0) - HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") -assert(H5E_UNSUPPORTED_g==(-1)); -if((msg = H5E_create_msg(cls, H5E_MINOR, "Feature is unsupported"))==NULL) - HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") -if((H5E_UNSUPPORTED_g = H5I_register(H5I_ERROR_MSG, msg))<0) - HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") -assert(H5E_BADTYPE_g==(-1)); -if((msg = H5E_create_msg(cls, H5E_MINOR, "Inappropriate type"))==NULL) - HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") -if((H5E_BADTYPE_g = H5I_register(H5I_ERROR_MSG, msg))<0) - HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") -assert(H5E_BADRANGE_g==(-1)); -if((msg = H5E_create_msg(cls, H5E_MINOR, "Out of range"))==NULL) - HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") -if((H5E_BADRANGE_g = H5I_register(H5I_ERROR_MSG, msg))<0) - HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") -assert(H5E_BADVALUE_g==(-1)); -if((msg = H5E_create_msg(cls, H5E_MINOR, "Bad value"))==NULL) - HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") -if((H5E_BADVALUE_g = H5I_register(H5I_ERROR_MSG, msg))<0) - HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") - /* B-tree related errors */ assert(H5E_NOTFOUND_g==(-1)); if((msg = H5E_create_msg(cls, H5E_MINOR, "Object not found"))==NULL) @@ -767,6 +745,33 @@ if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to remove object"))==NULL) if((H5E_CANTREMOVE_g = H5I_register(H5I_ERROR_MSG, msg))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") +/* Argument errors */ +assert(H5E_UNINITIALIZED_g==(-1)); +if((msg = H5E_create_msg(cls, H5E_MINOR, "Information is uinitialized"))==NULL) + HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") +if((H5E_UNINITIALIZED_g = H5I_register(H5I_ERROR_MSG, msg))<0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") +assert(H5E_UNSUPPORTED_g==(-1)); +if((msg = H5E_create_msg(cls, H5E_MINOR, "Feature is unsupported"))==NULL) + HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") +if((H5E_UNSUPPORTED_g = H5I_register(H5I_ERROR_MSG, msg))<0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") +assert(H5E_BADTYPE_g==(-1)); +if((msg = H5E_create_msg(cls, H5E_MINOR, "Inappropriate type"))==NULL) + HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") +if((H5E_BADTYPE_g = H5I_register(H5I_ERROR_MSG, msg))<0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") +assert(H5E_BADRANGE_g==(-1)); +if((msg = H5E_create_msg(cls, H5E_MINOR, "Out of range"))==NULL) + HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") +if((H5E_BADRANGE_g = H5I_register(H5I_ERROR_MSG, msg))<0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") +assert(H5E_BADVALUE_g==(-1)); +if((msg = H5E_create_msg(cls, H5E_MINOR, "Bad value"))==NULL) + HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") +if((H5E_BADVALUE_g = H5I_register(H5I_ERROR_MSG, msg))<0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") + /* Datatype conversion errors */ assert(H5E_CANTCONVERT_g==(-1)); if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't convert datatypes"))==NULL) diff --git a/src/H5Epubgen.h b/src/H5Epubgen.h index 34e9340..7c517cf 100644 --- a/src/H5Epubgen.h +++ b/src/H5Epubgen.h @@ -27,6 +27,7 @@ #define H5E_FUNC (H5OPEN H5E_FUNC_g) #define H5E_STORAGE (H5OPEN H5E_STORAGE_g) #define H5E_FILE (H5OPEN H5E_FILE_g) +#define H5E_SOHM (H5OPEN H5E_SOHM_g) #define H5E_SYM (H5OPEN H5E_SYM_g) #define H5E_VFL (H5OPEN H5E_VFL_g) #define H5E_INTERNAL (H5OPEN H5E_INTERNAL_g) @@ -56,6 +57,7 @@ H5_DLLVAR hid_t H5E_DATASET_g; /* Dataset */ H5_DLLVAR hid_t H5E_FUNC_g; /* Function entry/exit */ H5_DLLVAR hid_t H5E_STORAGE_g; /* Data storage */ H5_DLLVAR hid_t H5E_FILE_g; /* File accessability */ +H5_DLLVAR hid_t H5E_SOHM_g; /* Shared Object Header Messages */ H5_DLLVAR hid_t H5E_SYM_g; /* Symbol table */ H5_DLLVAR hid_t H5E_VFL_g; /* Virtual File Layer */ H5_DLLVAR hid_t H5E_INTERNAL_g; /* Internal error (too specific to document in detail) */ @@ -310,18 +312,6 @@ H5_DLLVAR hid_t H5E_CANTNEXT_g; /* Can't move to next iterator location */ H5_DLLVAR hid_t H5E_BADSELECT_g; /* Invalid selection */ H5_DLLVAR hid_t H5E_CANTCOMPARE_g; /* Can't compare objects */ -/* Argument errors */ -#define H5E_UNINITIALIZED (H5OPEN H5E_UNINITIALIZED_g) -#define H5E_UNSUPPORTED (H5OPEN H5E_UNSUPPORTED_g) -#define H5E_BADTYPE (H5OPEN H5E_BADTYPE_g) -#define H5E_BADRANGE (H5OPEN H5E_BADRANGE_g) -#define H5E_BADVALUE (H5OPEN H5E_BADVALUE_g) -H5_DLLVAR hid_t H5E_UNINITIALIZED_g; /* Information is uinitialized */ -H5_DLLVAR hid_t H5E_UNSUPPORTED_g; /* Feature is unsupported */ -H5_DLLVAR hid_t H5E_BADTYPE_g; /* Inappropriate type */ -H5_DLLVAR hid_t H5E_BADRANGE_g; /* Out of range */ -H5_DLLVAR hid_t H5E_BADVALUE_g; /* Bad value */ - /* B-tree related errors */ #define H5E_NOTFOUND (H5OPEN H5E_NOTFOUND_g) #define H5E_EXISTS (H5OPEN H5E_EXISTS_g) @@ -346,6 +336,18 @@ H5_DLLVAR hid_t H5E_CANTLIST_g; /* Unable to list node */ H5_DLLVAR hid_t H5E_CANTMODIFY_g; /* Unable to modify record */ H5_DLLVAR hid_t H5E_CANTREMOVE_g; /* Unable to remove object */ +/* Argument errors */ +#define H5E_UNINITIALIZED (H5OPEN H5E_UNINITIALIZED_g) +#define H5E_UNSUPPORTED (H5OPEN H5E_UNSUPPORTED_g) +#define H5E_BADTYPE (H5OPEN H5E_BADTYPE_g) +#define H5E_BADRANGE (H5OPEN H5E_BADRANGE_g) +#define H5E_BADVALUE (H5OPEN H5E_BADVALUE_g) +H5_DLLVAR hid_t H5E_UNINITIALIZED_g; /* Information is uinitialized */ +H5_DLLVAR hid_t H5E_UNSUPPORTED_g; /* Feature is unsupported */ +H5_DLLVAR hid_t H5E_BADTYPE_g; /* Inappropriate type */ +H5_DLLVAR hid_t H5E_BADRANGE_g; /* Out of range */ +H5_DLLVAR hid_t H5E_BADVALUE_g; /* Bad value */ + /* Datatype conversion errors */ #define H5E_CANTCONVERT (H5OPEN H5E_CANTCONVERT_g) #define H5E_BADSIZE (H5OPEN H5E_BADSIZE_g) diff --git a/src/H5Eterm.h b/src/H5Eterm.h index 3743c08..a188ab4 100644 --- a/src/H5Eterm.h +++ b/src/H5Eterm.h @@ -25,6 +25,7 @@ H5E_DATASET_g= H5E_FUNC_g= H5E_STORAGE_g= H5E_FILE_g= +H5E_SOHM_g= H5E_SYM_g= H5E_VFL_g= H5E_INTERNAL_g= @@ -183,13 +184,6 @@ H5E_CANTNEXT_g= H5E_BADSELECT_g= H5E_CANTCOMPARE_g= -/* Argument errors */ -H5E_UNINITIALIZED_g= -H5E_UNSUPPORTED_g= -H5E_BADTYPE_g= -H5E_BADRANGE_g= -H5E_BADVALUE_g= - /* B-tree related errors */ H5E_NOTFOUND_g= H5E_EXISTS_g= @@ -203,6 +197,13 @@ H5E_CANTLIST_g= H5E_CANTMODIFY_g= H5E_CANTREMOVE_g= +/* Argument errors */ +H5E_UNINITIALIZED_g= +H5E_UNSUPPORTED_g= +H5E_BADTYPE_g= +H5E_BADRANGE_g= +H5E_BADVALUE_g= + /* Datatype conversion errors */ H5E_CANTCONVERT_g= H5E_BADSIZE_g= (-1); diff --git a/src/H5F.c b/src/H5F.c index f9dba21..01f426c 100644 --- a/src/H5F.c +++ b/src/H5F.c @@ -31,6 +31,7 @@ #include "H5MMprivate.h" /* Memory management */ #include "H5Pprivate.h" /* Property lists */ #include "H5Tprivate.h" /* Datatypes */ +#include "H5SMprivate.h" /* Shared Object Header messages */ /* Predefined file drivers */ #include "H5FDcore.h" /*temporary in-memory files */ @@ -921,6 +922,8 @@ static H5F_t * H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf) { H5F_t *f = NULL, *ret_value; + unsigned sohm_indexes; /* JAMES: necessary? */ + unsigned super_vers = HDF5_SUPERBLOCK_VERSION_DEF; H5P_genplist_t *plist; /* Property list */ FUNC_ENTER_NOAPI_NOINIT(H5F_new) @@ -940,6 +943,7 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf) f->shared->super_addr = HADDR_UNDEF; f->shared->base_addr = HADDR_UNDEF; f->shared->freespace_addr = HADDR_UNDEF; + f->shared->sohm_addr = HADDR_UNDEF; f->shared->driver_addr = HADDR_UNDEF; f->shared->lf = lf; @@ -963,18 +967,22 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "unable to get rank for btree internal nodes") /* Check for non-default indexed storage B-tree internal 'K' value - * and increment the version # of the superblock if it is a non-default + * and set the version # of the superblock to 1 if it is a non-default * value. */ if(f->shared->btree_k[H5B_ISTORE_ID]!=HDF5_BTREE_ISTORE_IK_DEF) { - unsigned super_vers=HDF5_SUPERBLOCK_VERSION_MAX; /* Super block version */ - H5P_genplist_t *c_plist; /* Property list */ + super_vers= HDF5_SUPERBLOCK_VERSION_1 ; /* Super block version 1 */ + } - if(NULL == (c_plist = H5I_object(f->shared->fcpl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not property list") - if(H5P_set(c_plist, H5F_CRT_SUPER_VERS_NAME, &super_vers) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set superblock version") - } /* end if */ + /* The shared object header message table gets created later, but if + * it is present we should use version 2 of the superblock. + */ + if(H5P_get(plist, H5F_CRT_SOHM_NINDEXES_NAME, &sohm_indexes)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get number of SOHM indexes") + + if(sohm_indexes > 0) { + super_vers= HDF5_SUPERBLOCK_VERSION_2; /* Super block version 2 */ + } if(NULL == (plist = H5I_object(fapl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not file access property list") @@ -999,6 +1007,17 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf) if(H5P_get(plist, H5F_ACS_LATEST_FORMAT_NAME, &(f->shared->latest_format)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get 'latest format' flag") + /* If a newer super block version is required, set it here */ + if(super_vers != HDF5_SUPERBLOCK_VERSION_DEF) + { + H5P_genplist_t *c_plist; /* Property list */ + + if(NULL == (c_plist = H5I_object(f->shared->fcpl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not property list") + if(H5P_set(c_plist, H5F_CRT_SUPER_VERS_NAME, &super_vers) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, NULL, "unable to set superblock version") + } + /* * Create a meta data cache with the specified number of elements. * The cache might be created with a different number of elements and @@ -1255,7 +1274,9 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t d unsigned tent_flags; /*tentative flags */ H5FD_class_t *drvr; /*file driver class info */ H5P_genplist_t *a_plist; /*file access property list */ + H5P_genplist_t *c_plist; /*file access property list */ H5F_close_degree_t fc_degree; /*file close degree */ + unsigned num_sohm_indexes; /*number of SOHM indexes */ H5F_t *ret_value; /*actual return value */ FUNC_ENTER_NOAPI(H5F_open, NULL) @@ -1385,14 +1406,29 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t d if(H5F_init_superblock(file, dxpl_id) == 0) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to allocate file superblock") + /* Create the Shared Object Header Message table and register it with the + * metadata cache */ + /* JAMES: hack. Should check f->shared directly? */ + if(NULL == (c_plist = H5P_object_verify(fcpl_id,H5P_FILE_CREATE))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, NULL, "can't find object for ID"); + + if(H5P_get(c_plist, H5F_CRT_SOHM_NINDEXES_NAME, &num_sohm_indexes)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get SOHM information") + + if(num_sohm_indexes > 0) + { + if(H5SM_init(file, c_plist, dxpl_id) <0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create SOHM table") + } + /* Create and open the root group */ /* (This must be after the space for the superblock is allocated in - * the file) + * the file and after the SOHM table has been created) */ if(H5G_mkroot(file, dxpl_id, NULL) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create/open root group") - /* Write the superblock to the file */ + /* Write the superblock to the file */ /* (This must be after the root group is created, since the root * group's symbol table entry is part of the superblock) */ diff --git a/src/H5FDmulti.c b/src/H5FDmulti.c index b4c4277..3e7e1aa 100644 --- a/src/H5FDmulti.c +++ b/src/H5FDmulti.c @@ -379,7 +379,7 @@ H5Pset_fapl_split(hid_t fapl, const char *meta_ext, hid_t meta_plist_id, * letters `s' (H5FD_MEM_SUPER), * `b' (H5FD_MEM_BTREE), `r' (H5FD_MEM_DRAW), * `g' (H5FD_MEM_GHEAP), 'l' (H5FD_MEM_LHEAP), - * `o' (H5FD_MEM_OHDR). + * `o' (H5FD_MEM_OHDR), 'h' (H5FD_MEM_SOHM). * * memb_addr: The value HADDR_UNDEF for each element. * @@ -439,7 +439,7 @@ H5Pset_fapl_multi(hid_t fapl_id, const H5FD_mem_t *memb_map, char _memb_name[H5FD_MEM_NTYPES][16]; const char *_memb_name_ptrs[H5FD_MEM_NTYPES]; haddr_t _memb_addr[H5FD_MEM_NTYPES]; - static const char *letters = "Xsbrglo"; + static const char *letters = "Xsbrglom"; static const char *func="H5FDset_fapl_multi"; /* Function Name for error reporting */ /*NO TRACE*/ @@ -776,10 +776,9 @@ H5FD_multi_sb_encode(H5FD_t *_file, char *name/*out*/, strncpy(name, "NCSAmulti", (size_t)8); name[8] = '\0'; - assert(7==H5FD_MEM_NTYPES); + assert(8==H5FD_MEM_NTYPES); for (m=H5FD_MEM_SUPER; mfa.memb_map[m]; - buf[6] = 0; buf[7] = 0; /* diff --git a/src/H5FDpublic.h b/src/H5FDpublic.h index d780da4..bab96c0 100644 --- a/src/H5FDpublic.h +++ b/src/H5FDpublic.h @@ -39,6 +39,7 @@ typedef enum H5FD_mem_t { H5FD_MEM_GHEAP = 4, H5FD_MEM_LHEAP = 5, H5FD_MEM_OHDR = 6, + H5FD_MEM_SOHM = 7, H5FD_MEM_NTYPES /*must be last*/ } H5FD_mem_t; diff --git a/src/H5Fdbg.c b/src/H5Fdbg.c index 3700067..1377c36 100644 --- a/src/H5Fdbg.c +++ b/src/H5Fdbg.c @@ -126,6 +126,8 @@ H5F_debug(H5F_t *f, hid_t dxpl_id, FILE * stream, int indent, int fwidth) "Base address:", f->shared->base_addr); HDfprintf(stream, "%*s%-*s %a (rel)\n", indent, "", fwidth, "Free list address:", f->shared->freespace_addr); + HDfprintf(stream, "%*s%-*s %a (rel)\n", indent, "", fwidth, + "Shared object header table address:", f->shared->sohm_addr); HDfprintf(stream, "%*s%-*s %a (rel)\n", indent, "", fwidth, "Address of driver information block:", f->shared->driver_addr); diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h index fa0cf64..081c970 100644 --- a/src/H5Fpkg.h +++ b/src/H5Fpkg.h @@ -92,6 +92,7 @@ typedef struct H5F_file_t { haddr_t super_addr; /* Absolute address of super block */ haddr_t base_addr; /* Absolute base address for rel.addrs. */ haddr_t freespace_addr; /* Relative address of free-space info */ + haddr_t sohm_addr; /* Relative address of shared object header message table */ haddr_t driver_addr; /* File driver information block address*/ hbool_t fam_to_sec2; /* Is h5repart changing driver from family to sec2 */ diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index 23af32f..25b8f98 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -341,6 +341,12 @@ typedef struct H5F_t H5F_t; #define H5F_CRT_FREESPACE_VERS_NAME "free_space_version" /* Free-space version number */ #define H5F_CRT_OBJ_DIR_VERS_NAME "obj_dir_version" /* Object directory version number */ #define H5F_CRT_SHARE_HEAD_VERS_NAME "share_head_version" /* Shared-header format version */ +#define H5F_CRT_SOHM_NINDEXES_NAME "num_sohm_indexes" /* Number of shared object header message indexes */ +#define H5F_CRT_INDEX_TYPES_NAME "sohm_message_types" /* Types of message in each index */ +#define H5F_CRT_SOHM_L2B_NAME "sohm_list_to_btree" /* SOHM list maximum size */ +#define H5F_CRT_SOHM_B2L_NAME "sohm_btree_to_list" /* SOHM B-tree minimum size */ + + /* ========= File Access properties ============ */ #define H5F_ACS_META_CACHE_INIT_CONFIG_NAME "mdc_initCacheCfg" /* Initial metadata cache resize configuration */ diff --git a/src/H5Fsuper.c b/src/H5Fsuper.c index b14fcb0..234c08d 100644 --- a/src/H5Fsuper.c +++ b/src/H5Fsuper.c @@ -25,6 +25,7 @@ #include "H5FDprivate.h" /* File drivers */ #include "H5Iprivate.h" /* IDs */ #include "H5Pprivate.h" /* Property lists */ +#include "H5SMprivate.h" /* Shared Object Header Messages */ /* PRIVATE PROTOTYPES */ @@ -93,6 +94,7 @@ H5F_read_superblock(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc, haddr_t addr, unsigned obj_dir_vers; /* Object header info version */ unsigned share_head_vers; /* Shared header info version */ uint8_t sbuf[H5F_SUPERBLOCK_SIZE]; /* Local buffer */ + unsigned nindexes; /* Number of shared message indexes */ H5P_genplist_t *c_plist; /* File creation property list */ herr_t ret_value = SUCCEED; @@ -140,7 +142,7 @@ H5F_read_superblock(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc, haddr_t addr, if (HDF5_FREESPACE_VERSION != freespace_vers) HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad free space version number") if (H5P_set(c_plist, H5F_CRT_FREESPACE_VERS_NAME, &freespace_vers) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to free space version") + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set free space version") /* Root group version number */ obj_dir_vers = *p++; @@ -238,6 +240,10 @@ H5F_read_superblock(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc, haddr_t addr, H5F_addr_decode(f, (const uint8_t **)&p, &shared->base_addr/*out*/); H5F_addr_decode(f, (const uint8_t **)&p, &shared->freespace_addr/*out*/); + /* If the superblock version is greater than 1, read in the shared OH message table address */ + if(super_vers > 1) { + H5F_addr_decode(f, (const uint8_t **)&p, &shared->sohm_addr/*out*/); + } H5F_addr_decode(f, (const uint8_t **)&p, &stored_eoa/*out*/); H5F_addr_decode(f, (const uint8_t **)&p, &shared->driver_addr/*out*/); if(H5G_obj_ent_decode(f, (const uint8_t **)&p, root_loc->oloc/*out*/) < 0) @@ -360,6 +366,38 @@ H5F_read_superblock(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc, haddr_t addr, if (H5FD_set_eoa(lf, stored_eoa) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to set end-of-address marker for file") + /* Decode shared object header message information and store it in the + * fcpl */ + if(shared->sohm_addr != HADDR_UNDEF) + { + unsigned index_flags[H5SM_MAX_NUM_INDEXES]; + size_t sohm_l2b; /* SOHM list-to-btree cutoff */ + size_t sohm_b2l; /* SOHM btree-to-list cutoff */ + + /* Read in the shared OH message information if there is any */ + if(H5SM_get_info(f, shared->sohm_addr, &nindexes, index_flags, &sohm_l2b, &sohm_b2l, dxpl_id) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read SOHM table information") + + HDassert(nindexes > 0 && nindexes <= H5SM_MAX_NUM_INDEXES); + + /* Set values in the property list */ + if(H5P_set(c_plist, H5F_CRT_SOHM_NINDEXES_NAME, &nindexes) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set number of SOHM indexes"); + if(H5P_set(c_plist, H5F_CRT_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_SOHM_L2B_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_SOHM_B2L_NAME, &sohm_b2l) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set SOHM cutoff in property list"); + } + else + { + /* Shared object header messages are disabled */ + nindexes = 0; + if(H5P_set(c_plist, H5F_CRT_SOHM_NINDEXES_NAME, &nindexes) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set number of SOHM indexes"); + } + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5F_read_superblock() */ @@ -421,6 +459,7 @@ H5F_init_superblock(const H5F_t *f, hid_t dxpl_id) + 16 /* Length of required fixed-size portion */ + ((super_vers>0) ? 4 : 0) /* Version specific fixed-size portion */ + 4 * H5F_sizeof_addr(f) /* Variable-sized addresses */ + + (super_vers>1 ? H5F_sizeof_addr(f) : 0) + /*SOHM table address*/ + H5G_SIZEOF_ENTRY(f); /* Size of root group symbol table entry */ /* Compute the size of the driver information block. */ @@ -429,11 +468,12 @@ H5F_init_superblock(const H5F_t *f, hid_t dxpl_id) driver_size += 16; /* Driver block header */ /* - * Allocate space for the userblock, superblock, and driver info - * block. We do it with one allocation request because the - * userblock and superblock need to be at the beginning of the - * file and only the first allocation request is required to - * return memory at format address zero. + * Allocate space for the userblock, superblock, driver info + * block, and shared object header message table. We do it with + * one allocation request because the userblock and superblock + * need to be at the beginning of the file and only the first + * allocation request is required to return memory at format + * address zero. */ H5_CHECK_OVERFLOW(f->shared->base_addr, haddr_t, hsize_t); @@ -469,7 +509,8 @@ done: * Purpose: Writes (and optionally allocates) the superblock for the file. * If BUF is non-NULL, then write the serialized superblock * information into it. It should be a buffer of size - * H5F_SUPERBLOCK_SIZE + H5F_DRVINFOBLOCK_SIZE or larger. + * H5F_SUPERBLOCK_SIZE + H5F_DRVINFOBLOCK_SIZE + * or larger. * * Return: Success: SUCCEED * Failure: FAIL @@ -544,6 +585,9 @@ H5F_write_superblock(H5F_t *f, hid_t dxpl_id) H5F_addr_encode(f, &p, f->shared->base_addr); H5F_addr_encode(f, &p, f->shared->freespace_addr); + if(super_vers > 1) { + H5F_addr_encode(f, &p, f->shared->sohm_addr); + } H5F_addr_encode(f, &p, H5FD_get_eoa(f->shared->lf)); H5F_addr_encode(f, &p, f->shared->driver_addr); if(H5G_obj_ent_encode(f, &p, H5G_oloc(f->shared->root_grp))<0) diff --git a/src/H5HG.c b/src/H5HG.c index b15077f..6c6b610 100644 --- a/src/H5HG.c +++ b/src/H5HG.c @@ -578,8 +578,11 @@ H5HG_dest (H5F_t *f, H5HG_heap_t *heap) break; } } - heap->chunk = H5FL_BLK_FREE(heap_chunk,heap->chunk); - heap->obj = H5FL_SEQ_FREE(H5HG_obj_t,heap->obj); + + if(heap->chunk) + heap->chunk = H5FL_BLK_FREE(heap_chunk,heap->chunk); + if(heap->obj) + heap->obj = H5FL_SEQ_FREE(H5HG_obj_t,heap->obj); H5FL_FREE (H5HG_heap_t,heap); FUNC_LEAVE_NOAPI(SUCCEED); diff --git a/src/H5O.c b/src/H5O.c index 23fee02..89194b5 100644 --- a/src/H5O.c +++ b/src/H5O.c @@ -41,6 +41,8 @@ #include "H5MFprivate.h" /* File memory management */ #include "H5MMprivate.h" /* Memory management */ #include "H5Opkg.h" /* Object headers */ +#include "H5Tprivate.h" +#include "H5SMprivate.h" /* Shared object header messages */ #ifdef H5_HAVE_GETTIMEOFDAY #include @@ -70,6 +72,7 @@ HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, ERR, "unable to decode message") \ } /* end if */ +/* Private typedefs */ /******************/ /* Local Typedefs */ @@ -170,8 +173,6 @@ static herr_t H5O_iterate_real(const H5O_loc_t *loc, const H5O_msg_class_t *type static const H5O_obj_class_t *H5O_obj_class(H5O_loc_t *loc, hid_t dxpl_id); static H5G_obj_t H5O_obj_type_real(H5O_t *oh); static const H5O_obj_class_t *H5O_obj_class_real(H5O_t *oh); -static void * H5O_copy_mesg_file(const H5O_msg_class_t *type, H5F_t *file_src, void *mesg_src, - H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, void *udata); static herr_t H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, hid_t dxpl_id, H5O_copy_t *cpy_info); static herr_t H5O_copy_free_addrmap_cb(void *item, void *key, void *op_data); @@ -249,7 +250,6 @@ H5FL_EXTERN(H5O_cont_t); /* Declare a free list to manage the H5O_addr_map_t struct */ H5FL_EXTERN(H5O_addr_map_t); - /*------------------------------------------------------------------------- * Function: H5Oopen @@ -1607,11 +1607,14 @@ done: * *------------------------------------------------------------------------- */ +/* JAMES: this will probably get put through its paces when extending shared + * dataspaces */ int H5O_modify(H5O_loc_t *loc, unsigned type_id, int overwrite, - unsigned flags, unsigned update_flags, const void *mesg, hid_t dxpl_id) + unsigned flags, unsigned update_flags, void *mesg, hid_t dxpl_id) { const H5O_msg_class_t *type; /* Actual H5O class type for the ID */ + htri_t shared_mess; int ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5O_modify, FAIL) @@ -1626,6 +1629,15 @@ H5O_modify(H5O_loc_t *loc, unsigned type_id, int overwrite, HDassert(mesg); HDassert(0 == (flags & ~H5O_FLAG_BITS)); + /* Should this message be written as a SOHM? */ + if((shared_mess = H5SM_try_share(loc->file, dxpl_id, type_id, mesg)) >0) + { + /* Mark the message as shared */ + flags |= H5O_FLAG_SHARED; + + } else if(shared_mess < 0) + HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "error while trying to share message"); + /* Call the "real" modify routine */ if((ret_value = H5O_modify_real(loc, type, overwrite, flags, update_flags, mesg, dxpl_id)) < 0) HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header message") @@ -1679,6 +1691,8 @@ H5O_modify_real(H5O_loc_t *loc, const H5O_msg_class_t *type, int overwrite, unsigned idx; /* Index of message to modify */ H5O_mesg_t *idx_msg; /* Pointer to message to modify */ H5O_shared_t sh_mesg; + const H5O_msg_class_t *write_type = type; /* Type of message to be written */ + const void *write_mesg = mesg; /* Actual message being written */ int ret_value; FUNC_ENTER_NOAPI_NOINIT(H5O_modify_real) @@ -1709,7 +1723,7 @@ H5O_modify_real(H5O_loc_t *loc, const H5O_msg_class_t *type, int overwrite, /* Was the right message found? */ if(overwrite >= 0 && (idx >= oh->nmesgs || sequence != overwrite)) { - /* But can we insert a new one with this sequence number? */ + /* No, but can we insert a new one with this sequence number? */ if(overwrite == sequence + 1) overwrite = -1; else @@ -1719,6 +1733,7 @@ H5O_modify_real(H5O_loc_t *loc, const H5O_msg_class_t *type, int overwrite, /* Check for creating new message */ 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, &flags, type, mesg, &sh_mesg, &type, &mesg, dxpl_id, &oh_flags)) == UFAIL) HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to create new message") @@ -1728,11 +1743,41 @@ H5O_modify_real(H5O_loc_t *loc, const H5O_msg_class_t *type, int overwrite, } else if(oh->mesg[idx].flags & H5O_FLAG_CONSTANT) { HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to modify constant message") } else if(oh->mesg[idx].flags & H5O_FLAG_SHARED) { - HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to modify shared (constant) message") + /* This message is shared, but it's being modified. This is valid if + * it's shared in the heap . + * First, make sure it's not a committed message; these can't ever + * be modified. + */ + if(((H5O_shared_t*) oh->mesg[idx].native)->flags & H5O_COMMITTED_FLAG) + HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to modify committed message") + + /* Remove the old message from the SOHM index */ + if(H5SM_try_delete(loc->file, dxpl_id, oh->mesg[idx].type->id, oh->mesg[idx].native) < 0) + HGOTO_ERROR (H5E_OHDR, H5E_CANTFREE, FAIL, "unable to delete message from SOHM table") + + /* Now this message is no longer shared and we can safely overwrite + * it. + * We need to make sure that the message we're writing is shared, + * though, and that the library doesn't try to reset the current + * message like it would in a normal overwrite (this message is + * realy a shared pointer, not a real + * message). + * JAMES: will this break if a shared message is overwritten with a larger + * non-shared message? + */ + HDassert(H5O_is_shared(type->id, mesg) > 0); /* JAMES: this should work with + * replacement messages that aren't shared, too. */ + + if(H5O_get_share(type->id, loc->file, mesg, &sh_mesg)<0) + HGOTO_ERROR (H5E_OHDR, H5E_BADMESG, FAIL, "can't get shared message") + + /* Instead of writing the original message, write a shared message */ + write_type = H5O_msg_class_g[H5O_SHARED_ID]; + write_mesg = &sh_mesg; } /* Write the information to the message */ - if(H5O_write_mesg(oh, idx, type, mesg, flags, update_flags, &oh_flags) < 0) + if(H5O_write_mesg(oh, idx, write_type, write_mesg, flags, update_flags, &oh_flags) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to write message") /* Update the modification time message if any */ @@ -1854,9 +1899,10 @@ done: */ int H5O_append(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned type_id, unsigned flags, - const void *mesg, unsigned * oh_flags_ptr) + void *mesg, unsigned * oh_flags_ptr) { - const H5O_msg_class_t *type; /* Actual H5O class type for the ID */ + const H5O_msg_class_t *type; /* Actual H5O class type for the ID */ + htri_t shared_mess; /* Should this message be stored in the Shared Message table? */ int ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5O_append, FAIL) @@ -1871,7 +1917,15 @@ H5O_append(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned type_id, unsigned flags, HDassert(mesg); HDassert(oh_flags_ptr); - /* Call the "real" append routine */ + /* Should this message be written as a SOHM? */ + if((shared_mess = H5SM_try_share(f, dxpl_id, type_id, mesg)) >0) + { + /* Mark the message as shared */ + flags |= H5O_FLAG_SHARED; + } + else if(shared_mess < 0) + HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "error determining if message should be shared"); + if((ret_value = H5O_append_real( f, dxpl_id, oh, type, flags, mesg, oh_flags_ptr)) < 0) HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to append to object header") @@ -1953,6 +2007,7 @@ H5O_new_mesg(H5F_t *f, H5O_t *oh, unsigned *flags, const H5O_msg_class_t *orig_t const void **new_mesg, hid_t dxpl_id, unsigned * oh_flags_ptr) { size_t size; /* Size of space allocated for object header */ + htri_t is_shared; /* Is this a shared message? */ unsigned ret_value = UFAIL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_new_mesg) @@ -1972,20 +2027,25 @@ H5O_new_mesg(H5F_t *f, H5O_t *oh, unsigned *flags, const H5O_msg_class_t *orig_t if(*flags & H5O_FLAG_SHARED) { HDmemset(sh_mesg, 0, sizeof(H5O_shared_t)); - if(NULL == orig_type->get_share) - HGOTO_ERROR(H5E_OHDR, H5E_UNSUPPORTED, UFAIL, "message class is not sharable") - if((orig_type->get_share)(f, orig_mesg, sh_mesg/*out*/) < 0) { + if ((NULL == orig_type->is_shared) || (NULL == orig_type->get_share)) + HGOTO_ERROR(H5E_OHDR, H5E_UNSUPPORTED, UFAIL, "message class is not sharable"); + if ((is_shared = (orig_type->is_shared)(orig_mesg)) == FALSE) { /* * If the message isn't shared then turn off the shared bit * and treat it as an unshared message. */ - H5E_clear_stack(NULL); *flags &= ~H5O_FLAG_SHARED; - } else { - /* Change type & message to use shared information */ + } else if(is_shared > 0) { + /* Message is shared. Get shared message, change message type, + * and use shared information */ + if ((orig_type->get_share)(f, orig_mesg, sh_mesg/*out*/) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, UFAIL, "can't get shared message") + *new_type = H5O_MSG_SHARED; *new_mesg = sh_mesg; - } /* end else */ + } else { + HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, UFAIL, "can't determine if message is shared") + }/* end else */ } /* end if */ else { *new_type = orig_type; @@ -1996,7 +2056,7 @@ H5O_new_mesg(H5F_t *f, H5O_t *oh, unsigned *flags, const H5O_msg_class_t *orig_t if((size = ((*new_type)->raw_size)(f, *new_mesg)) >= H5O_MESG_MAX_SIZE) HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, UFAIL, "object header message is too large") - /* Allocate space in the object headed for the message */ + /* Allocate space in the object header for the message */ if((ret_value = H5O_alloc(f, dxpl_id, oh, orig_type, size, oh_flags_ptr)) == UFAIL) HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, UFAIL, "unable to allocate space for message") @@ -3455,9 +3515,11 @@ H5O_alloc_new_chunk(H5F_t *f, * that could be moved to make room for the continuation message. * * Don't ever move continuation message from one chunk to another. + * Prioritize link messages moving to later chunks, instead of + * more "important" messages. + * Avoid moving attributes when possible to preserve their + * ordering (although ordering is *not* guaranteed!). * - * Prioritize moving attribute and link messages to later chunks, - * instead of more "important" messages. */ cont_size = H5O_ALIGN_OH(oh, H5F_SIZEOF_ADDR(f) + H5F_SIZEOF_SIZE(f)); for(u = 0; u < oh->nmesgs; u++) { @@ -3498,15 +3560,17 @@ H5O_alloc_new_chunk(H5F_t *f, * message, then make sure the new chunk has enough room for that * other message. * - * Move attributes first, then link messages, then other messages. + * Move link messages first, then other messages, and attributes + * only as a last resort. * */ if(found_null < 0) { - if(found_attr >= 0) - found_other = found_attr; - else if(found_link >= 0) + if(found_link >= 0) found_other = found_link; + if(found_other < 0) + found_other = found_attr; + HDassert(found_other >= 0); size += H5O_SIZEOF_MSGHDR_OH(oh) + oh->mesg[found_other].raw_size; } /* end if */ @@ -4030,7 +4094,7 @@ H5O_get_share(unsigned type_id, H5F_t *f, const void *mesg, H5O_shared_t *share) HDassert(mesg); HDassert(share); - /* Compute the raw data size for the mesg */ + /* Get shared data for the mesg */ if((ret_value = (type->get_share)(f, mesg, share)) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to retrieve shared message information") @@ -4039,6 +4103,143 @@ done: } /* end H5O_get_share() */ + +/*------------------------------------------------------------------------- + * Function: H5O_is_shared + * + * Purpose: Call the 'is_shared' method for a + * particular class of object header. + * + * Return: Object is shared: TRUE + * Object is not shared: FALSE + * + * Programmer: James Laird + * jlaird@ncsa.uiuc.edu + * April 5 2006 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +htri_t +H5O_is_shared(unsigned type_id, const void *mesg) +{ + const H5O_msg_class_t *type; /* Actual H5O class type for the ID */ + htri_t ret_value; + + FUNC_ENTER_NOAPI_NOFUNC(H5O_is_shared) + + /* Check args */ + HDassert(type_id < NELMTS(H5O_msg_class_g)); + type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */ + HDassert(type); + HDassert(mesg); + + HDassert(type_id != H5O_SHARED_ID); /* JAMES: check for this mistake elsewhere, too */ + + /* If there is no is_shared function, then obviously it's not a shared message! */ + if( !(type->is_shared)) + ret_value = FALSE; + else + ret_value = (type->is_shared)(mesg); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_is_shared() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_set_share + * + * Purpose: Set the shared information for an object header message. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: James Laird + * jlaird@hdfgroup.org + * November 1 2006 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_set_share(H5F_t *f, hid_t dxpl_id, H5O_shared_t *share, + unsigned type_id, void *mesg) +{ + const H5O_msg_class_t *type; /* Actual H5O class type for the ID */ + herr_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_set_share,FAIL) + + /* Check args */ + HDassert(f); + HDassert(share); + HDassert(type_id < NELMTS(H5O_msg_class_g)); + type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */ + HDassert(type); + HDassert(type->set_share); + HDassert(mesg); + HDassert(share->flags != H5O_NOT_SHARED); + + /* Set this message as the shared message for the message, wiping out + * any information that was there before + */ + if((ret_value = (type->set_share)(f, mesg, share)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "unable to set shared message information") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_set_share() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_reset_share + * + * Purpose: Reset the shared information for an object header message. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: James Laird + * jlaird@hdfgroup.org + * Oct 17 2006 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_reset_share(H5F_t *f, unsigned type_id, void *mesg) +{ + const H5O_msg_class_t *type; /* Actual H5O class type for the ID */ + H5O_shared_t sh_mesg; /* Shared message */ + herr_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_reset_share,FAIL) + + /* Check args */ + HDassert(type_id < NELMTS(H5O_msg_class_g)); + type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */ + HDassert(type); + HDassert(type->set_share); + HDassert(mesg); + + /* Initialize the shared message to zero. */ + HDmemset(&sh_mesg, 0, sizeof(H5O_shared_t)); + + /* Set this message as the shared message for the message, wiping out + * any information that was there before + */ + if((ret_value = (type->set_share)(f, mesg, &sh_mesg)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "unable to reset shared message information") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_reset_share() */ + + + /*------------------------------------------------------------------------- * Function: H5O_delete * @@ -4160,7 +4361,9 @@ H5O_delete_mesg(H5F_t *f, hid_t dxpl_id, H5O_mesg_t *mesg, hbool_t adj_link) /* Get the message to free's type */ if(mesg->flags & H5O_FLAG_SHARED) + { type = H5O_MSG_SHARED; + } else type = mesg->type; @@ -4176,6 +4379,22 @@ H5O_delete_mesg(H5F_t *f, hid_t dxpl_id, H5O_mesg_t *mesg, hbool_t adj_link) HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "unable to decode message") } /* end if */ + /* Check if this message needs to be removed from the SOHM table */ + /* JAMES: there should be a callback, maybe in H5O_shared_delete, to fiddle w/ the ref. count. + * 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") + + 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) HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete file space for object header message") } /* end if */ @@ -4444,12 +4663,23 @@ 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. */ LOAD_NATIVE(loc->file, dxpl_id, idx_msg, FAIL) + /* JAMES: test */ + if(idx_msg->flags & H5O_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 */ @@ -4458,10 +4688,19 @@ H5O_iterate_real(const H5O_loc_t *loc, const H5O_msg_class_t *type, H5AC_protect } /* end if */ else { /* Call the iterator callback */ - if((ret_value = (op.app_op)(idx_msg->native, sequence, op_data)) != 0) +/* JAMES if((ret_value = (op.app_op)(idx_msg->native, 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_FLAG_SHARED) + { + H5O_free_real(idx_msg->type, unshared_mesg); + } + /* Check for error from iterator */ if(ret_value < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "iterator function failed") @@ -4820,8 +5059,8 @@ done: * *------------------------------------------------------------------------- */ -static void * -H5O_copy_mesg_file(const H5O_msg_class_t *type, H5F_t *file_src, void *native_src, +void * +H5O_copy_mesg_file(const H5O_msg_class_t *copy_type, const H5O_msg_class_t *mesg_type, H5F_t *file_src, void *native_src, H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, void *udata) { void *ret_value; @@ -4829,14 +5068,15 @@ H5O_copy_mesg_file(const H5O_msg_class_t *type, H5F_t *file_src, void *native_sr FUNC_ENTER_NOAPI_NOINIT(H5O_copy_mesg_file) /* check args */ - HDassert(type); - HDassert(type->copy_file); + HDassert(copy_type); + HDassert(mesg_type); + HDassert(copy_type->copy_file); HDassert(file_src); HDassert(native_src); HDassert(file_dst); HDassert(cpy_info); - if(NULL == (ret_value = (type->copy_file)(file_src, native_src, file_dst, dxpl_id, cpy_info, udata))) + if(NULL == (ret_value = (copy_type->copy_file)(file_src, mesg_type, native_src, file_dst, dxpl_id, cpy_info, udata))) HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to copy object header message to file") done: @@ -4847,7 +5087,15 @@ done: /*------------------------------------------------------------------------- * Function: H5O_copy_header_real * - * Purpose: copy header object from one location to another. + * Purpose: Copy header object from one location to another using + * pre-copy, copy, and post-copy callbacks for each message + * type. + * + * The source header object is compressed into a single chunk + * (since we know how big it is) and any continuation messages + * are converted into NULL messages. + * + * By default, NULL messages are not copied. * * Return: Non-negative on success/Negative on failure * @@ -4865,11 +5113,17 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, H5O_t *oh_dst = NULL; /* Object header for destination object */ unsigned chunkno = 0, mesgno = 0; haddr_t addr_new = HADDR_UNDEF; + hbool_t *deleted = NULL; /* Array of flags indicating whether messages should be copied */ + size_t null_msgs; /* Number of NULL messages found in each loop */ H5O_mesg_t *mesg_src; /* Message in source object header */ H5O_mesg_t *mesg_dst; /* Message in source object header */ const H5O_msg_class_t *copy_type; /* Type of message to use for copying */ const H5O_obj_class_t *obj_class = NULL; /* Type of object we are copying */ - void *udata = NULL; /* User data for passing to message callbacks */ + void *udata = NULL; /* User data for passing to message + callbacks */ + size_t dst_oh_size; /* Total size of the destination OH */ + uint8_t *current_pos; /* Current position in destination image */ + size_t msghdr_size; herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI_NOINIT(H5O_copy_header_real) @@ -4905,57 +5159,27 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, oh_dst->version = oh_src->version; oh_dst->nlink = 0; - /* Initialize size of chunk array */ - oh_dst->alloc_nchunks = oh_dst->nchunks = oh_src->nchunks; + /* Initialize size of chunk array. The destination always has only one + * chunk. + */ + oh_dst->alloc_nchunks = oh_dst->nchunks = 1; /* Allocate memory for the chunk array */ if(NULL == (oh_dst->chunk = H5FL_SEQ_MALLOC(H5O_chunk_t, oh_dst->alloc_nchunks))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") - /* need to allocate all the chunks for the destination before copy the chunk message - because continuation chunk message will need to know the chunk address of address of - continuation block. + /* Allocate memory for "deleted" array. This array marks the message in + * the source that shouldn't be copied to the destination. */ - for(chunkno = 0; chunkno < oh_src->nchunks; chunkno++) { - size_t chunk_size = oh_src->chunk[chunkno].size; - - /* Allocate space for chunk in destination file */ - if(HADDR_UNDEF == (oh_dst->chunk[chunkno].addr = H5MF_alloc(oloc_dst->file, H5FD_MEM_OHDR, dxpl_id, (hsize_t)chunk_size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for object header") - if(chunkno == 0) - addr_new = oh_dst->chunk[chunkno].addr; - - /* Create memory image for the new chunk */ - if(NULL == (oh_dst->chunk[chunkno].image = H5FL_BLK_MALLOC(chunk_image, chunk_size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") - - /* Copy the chunk image from source to destination in memory */ - /* (This copies over all the messages which don't require special - * callbacks to fix them up.) - */ - HDmemcpy(oh_dst->chunk[chunkno].image, oh_src->chunk[chunkno].image, chunk_size); - - /* Set dest. chunk information */ - oh_dst->chunk[chunkno].dirty = TRUE; - oh_dst->chunk[chunkno].size = chunk_size; - oh_dst->chunk[chunkno].gap = oh_src->chunk[chunkno].gap; - } /* end for */ - - - /* Initialize size of message list */ - oh_dst->alloc_nmesgs = oh_dst->nmesgs = oh_src->nmesgs; - - /* Allocate memory for message array */ - if(NULL == (oh_dst->mesg = H5FL_SEQ_CALLOC(H5O_mesg_t, oh_dst->alloc_nmesgs))) + if(NULL == (deleted = HDmalloc(sizeof(hbool_t) * oh_src->nmesgs))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + HDmemset(deleted, FALSE, sizeof(hbool_t) * oh_src->nmesgs); - /* Copy basic information about messages */ - HDmemcpy(oh_dst->mesg, oh_src->mesg, oh_dst->alloc_nmesgs * sizeof(H5O_mesg_t)); - - /* Set up destination message raw image pointer information */ - /* (must be done before "pre copy" pass, so that if a message is deleted, - * the raw message information in a chunk can be moved around safely) + /* "pre copy" pass over messages, to gather information for actual message copy operation + * (for messages which depend on information from other messages) + * Keep track of how many NULL or deleted messages we find (or create) */ + null_msgs = 0; for(mesgno = 0; mesgno < oh_src->nmesgs; mesgno++) { /* Set up convenience variables */ mesg_src = &(oh_src->mesg[mesgno]); @@ -4964,28 +5188,23 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, /* Sanity check */ HDassert(!mesg_src->dirty); /* Should be cleared by earlier call to flush messages */ - /* Fix up destination message pointers */ - mesg_dst->raw = oh_dst->chunk[mesg_dst->chunkno].image + (mesg_src->raw - oh_src->chunk[mesg_src->chunkno].image); - mesg_dst->native = NULL; - } /* end for */ - - /* "pre copy" pass over messages, to gather information for actual message copy operation */ - /* (for messages which depend on information from other messages) */ - for(mesgno = 0; mesgno < oh_src->nmesgs; mesgno++) { - /* Set up convenience variables */ - mesg_src = &(oh_src->mesg[mesgno]); - mesg_dst = &(oh_dst->mesg[mesgno]); - /* Check for shared message to operate on */ if(mesg_src->flags & H5O_FLAG_SHARED) copy_type = H5O_MSG_SHARED; else copy_type = mesg_src->type; - HDassert(copy_type); - if(copy_type->pre_copy_file) { - hbool_t deleted = FALSE; /* Flag to indicate that the message should be deleted from the destination */ + /* Check for continuation message; these are converted to NULL + * messages because the destination OH will have only one chunk + */ + if(H5O_CONT_ID == mesg_src->type->id || H5O_NULL_ID == mesg_src->type->id) { + deleted[mesgno] = TRUE; + ++null_msgs; + copy_type = H5O_MSG_NULL; + } + HDassert(copy_type); + if(copy_type->pre_copy_file ) { /* * Decode the message if necessary. If the message is shared then do * a shared message, ignoring the message type. @@ -4998,28 +5217,68 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, } /* end if (NULL == mesg_src->native) */ /* Perform "pre copy" operation on message */ - if((copy_type->pre_copy_file)(oloc_src->file, mesg_src->type, mesg_src->native, &deleted, cpy_info, udata) < 0) + if((copy_type->pre_copy_file)(oloc_src->file, mesg_src->type, mesg_src->native, &(deleted[mesgno]), cpy_info, udata) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to perform 'pre copy' operation on message") /* Check if the message should be deleted in the destination */ - if(deleted) { - /* Convert message into a null message */ - if(H5O_release_mesg(oloc_dst->file, dxpl_id, oh_dst, mesg_dst, FALSE, FALSE) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to convert into null message") - } /* end if */ - } /* end if */ + if(deleted[mesgno]) { + /* Mark message as deleted */ + ++null_msgs; + } /* end if(deleted) */ + } /* end if(copy_type->pre_copy_file) */ } /* end for */ + /* Initialize size of message list. It may or may not include the NULL messages + * detected above. + */ + if(cpy_info->preserve_null) + oh_dst->alloc_nmesgs = oh_dst->nmesgs = oh_src->nmesgs; + else + oh_dst->alloc_nmesgs = oh_dst->nmesgs = (oh_src->nmesgs - null_msgs); + + /* Allocate memory for destination message array */ + if(oh_dst->alloc_nmesgs > 0) { + if(NULL == (oh_dst->mesg = H5FL_SEQ_CALLOC(H5O_mesg_t, oh_dst->alloc_nmesgs))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + } + /* "copy" pass over messages, to perform main message copying */ - for(mesgno = 0; mesgno < oh_src->nmesgs; mesgno++) { + null_msgs = 0; + for(mesgno = 0; mesgno < oh_dst->nmesgs; mesgno++) { + /* Skip any deleted or NULL messages in the source unless the + * preserve_null flag is set + */ + if(FALSE == cpy_info->preserve_null) { + while(deleted[mesgno + null_msgs]) { + ++null_msgs; + HDassert(mesgno + null_msgs < oh_src->nmesgs); + } + } + /* Set up convenience variables */ - mesg_src = &(oh_src->mesg[mesgno]); + mesg_src = &(oh_src->mesg[mesgno + null_msgs]); mesg_dst = &(oh_dst->mesg[mesgno]); + /* Initialize on destination message */ + mesg_dst->chunkno = 0; + mesg_dst->dirty = FALSE; + mesg_dst->flags = mesg_src->flags; + mesg_dst->native = NULL; + mesg_dst->raw = NULL; + mesg_dst->raw_size = mesg_src->raw_size; + mesg_dst->type = mesg_src->type; + + /* If we're preserving deleted messages, set their types to 'NULL' + * in the destination. + */ + if(cpy_info->preserve_null && deleted[mesgno]) { + mesg_dst->type = H5O_MSG_NULL; + } + /* Check for shared message to operate on */ /* (Use destination message, in case the message has been removed (i.e - * converted to a nil message) in the destination -QAK) - */ + * converted to a nil message) in the destination -QAK) + */ if(mesg_dst->flags & H5O_FLAG_SHARED) copy_type = H5O_MSG_SHARED; else @@ -5029,9 +5288,9 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, /* copy this message into destination file */ if(copy_type->copy_file) { /* - * Decode the message if necessary. If the message is shared then do - * a shared message, ignoring the message type. - */ + * Decode the message if necessary. If the message is shared then do + * a shared message, ignoring the message type. + */ if(NULL == mesg_src->native) { /* Decode the message if necessary */ HDassert(copy_type->decode); @@ -5040,16 +5299,10 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, } /* end if (NULL == mesg_src->native) */ /* Copy the source message */ - if(H5O_CONT_ID == mesg_src->type->id) { - if((mesg_dst->native = H5O_copy_mesg_file(copy_type, oloc_src->file, mesg_src->native, - oloc_dst->file, dxpl_id, cpy_info, oh_dst->chunk)) == NULL) - HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object header message") - } /* end if */ - else { - if((mesg_dst->native = H5O_copy_mesg_file(copy_type, oloc_src->file, mesg_src->native, - oloc_dst->file, dxpl_id, cpy_info, udata)) == NULL) - HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object header message") - } /* end else */ + if((mesg_dst->native = H5O_copy_mesg_file(copy_type, mesg_dst->type, + oloc_src->file, mesg_src->native, oloc_dst->file, dxpl_id, + cpy_info, udata)) == NULL) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object header message") /* Mark the message in the destination as dirty, so it'll get encoded when the object header is flushed */ mesg_dst->dirty = TRUE; @@ -5057,6 +5310,86 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, } /* end of mesgno loop */ + /* Allocate the destination header and copy any messages that didn't have + * copy callbacks. They get copied directly from the source image to the + * destination image. + */ + + /* Calculate how big the destination object header will be on disk. + * This isn't necessarily the same size as the original. + */ + dst_oh_size = H5O_SIZEOF_HDR_OH(oh_dst); + + /* Add space for messages. */ + for(mesgno = 0; mesgno < oh_dst->nmesgs; mesgno++) { + dst_oh_size += H5O_SIZEOF_MSGHDR_OH(oh_dst); + dst_oh_size += H5O_ALIGN_OH(oh_dst, oh_dst->mesg[mesgno].raw_size); + } + + /* Allocate space for chunk in destination file */ + if(HADDR_UNDEF == (oh_dst->chunk[0].addr = H5MF_alloc(oloc_dst->file, H5FD_MEM_OHDR, dxpl_id, (hsize_t)dst_oh_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for object header") + addr_new = oh_dst->chunk[0].addr; + + /* Create memory image for the new chunk */ + if(NULL == (oh_dst->chunk[0].image = H5FL_BLK_MALLOC(chunk_image, dst_oh_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Set dest. chunk information */ + oh_dst->chunk[0].dirty = TRUE; + oh_dst->chunk[0].size = dst_oh_size; + oh_dst->chunk[0].gap = 0; + + /* Set up raw pointers and copy messages that didn't need special + * treatment. This has to happen after the destination header has been + * allocated. + */ + HDassert(H5O_SIZEOF_HDR_OH(oh_src) == H5O_SIZEOF_HDR_OH(oh_dst)); + HDassert(H5O_SIZEOF_MSGHDR_OH(oh_src) == H5O_SIZEOF_MSGHDR_OH(oh_dst)); + msghdr_size = H5O_SIZEOF_MSGHDR_OH(oh_src); + + current_pos = oh_dst->chunk[0].image; + + /* Copy the message header. Most of this will be overwritten when + * the header is flushed to disk, but later versions have a + * magic number that isn't. + */ + HDmemcpy(current_pos, oh_src->chunk[0].image, + H5O_SIZEOF_HDR_OH(oh_dst) - H5O_SIZEOF_CHKSUM_OH(oh_dst)); + current_pos += H5O_SIZEOF_HDR_OH(oh_dst) - H5O_SIZEOF_CHKSUM_OH(oh_dst); + + /* JAMES: include this in loop above? Doesn't take deleted messages + * into account + */ + /* Copy each message that wasn't dirtied above */ + null_msgs = 0; + for(mesgno = 0; mesgno < oh_dst->nmesgs; mesgno++) { + /* Skip any deleted or NULL messages in the source unless the + * preserve_null flag is set + */ + if(FALSE == cpy_info->preserve_null) { + while(deleted[mesgno + null_msgs]) { + ++null_msgs; + HDassert(mesgno + null_msgs < oh_src->nmesgs); + } + } + + /* Set up convenience variables */ + mesg_src = &(oh_src->mesg[mesgno + null_msgs]); + mesg_dst = &(oh_dst->mesg[mesgno]); + + if(! mesg_dst->dirty) { + /* Copy the message header plus the message's raw data. */ + HDmemcpy(current_pos, mesg_src->raw - msghdr_size, + msghdr_size + mesg_src->raw_size); + } + mesg_dst->raw = current_pos + msghdr_size; + current_pos += mesg_dst->raw_size + msghdr_size; + } + + /* Make sure we filled the chunk, except for room at the end for a checksum */ + HDassert(current_pos + H5O_SIZEOF_CHKSUM_OH(oh_dst) == dst_oh_size + oh_dst->chunk[0].image); + /* Set the dest. object location to the first chunk address */ HDassert(H5F_addr_defined(addr_new)); oloc_dst->addr = addr_new; @@ -5078,9 +5411,20 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, /* "post copy" loop over messages, to fix up any messages which require a complete * object header for destination object */ - for(mesgno = 0; mesgno < oh_src->nmesgs; mesgno++) { + null_msgs = 0; + for(mesgno = 0; mesgno < oh_dst->nmesgs; mesgno++) { + /* Skip any deleted or NULL messages in the source unless the + * preserve_null flag is set + */ + if(FALSE == cpy_info->preserve_null) { + while(deleted[mesgno + null_msgs]) { + ++null_msgs; + HDassert(mesgno + null_msgs < oh_src->nmesgs); + } + } + /* Set up convenience variables */ - mesg_src = &(oh_src->mesg[mesgno]); + mesg_src = &(oh_src->mesg[mesgno + null_msgs]); mesg_dst = &(oh_dst->mesg[mesgno]); /* Check for shared message to operate on */ @@ -5119,7 +5463,12 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to cache object header") done: - /* Release pointer to source object header and it's derived objects */ + /* Free deleted array */ + if(deleted) { + HDfree(deleted); + } + + /* Release pointer to source object header and its derived objects */ if(oh_src != NULL) { /* Unprotect the source object header */ if(H5AC_unprotect(oloc_src->file, dxpl_id, H5AC_OHDR, oloc_src->addr, oh_src, H5AC__NO_FLAGS_SET) < 0) @@ -5180,7 +5529,7 @@ H5O_copy_header_map(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, /* Copy object for the first time */ /* Check for incrementing the depth of copy */ - /* (Can't do this for all copies, since shared datatypes should always be copied) */ + /* (Can't do this for all copies, since committed datatypes should always be copied) */ if(inc_depth) cpy_info->curr_depth++; @@ -5199,7 +5548,7 @@ H5O_copy_header_map(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, ret_value++; } /* end if */ else { - /* Object has already been copied, set it's address in destination file */ + /* Object has already been copied, set its address in destination file */ oloc_dst->addr = addr_map->dst_addr; /* If the object is locked currently (because we are copying a group @@ -5301,6 +5650,8 @@ H5O_copy_header(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */, cpy_info.expand_ref = TRUE; if((cpy_option & H5O_COPY_WITHOUT_ATTR_FLAG) > 0) cpy_info.copy_without_attr = TRUE; + if((cpy_option & H5O_COPY_PRESERVE_NULL_FLAG) > 0) + cpy_info.preserve_null = TRUE; /* Create a skip list to keep track of which objects are copied */ if((cpy_info.map_list = H5SL_create(H5SL_TYPE_HADDR, 0.5, (size_t)16)) == NULL) @@ -5317,6 +5668,128 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_copy_header() */ + +/*------------------------------------------------------------------------- + * Function: H5O_mesg_hash + * + * Purpose: Returns a hash value for an object header message. + * + * Return: Non-H5O_HASH_UNDEF hash value on success + * H5O_HASH_UNDEF on failure + * + * Programmer: James Laird + * April 13 2006 + * + *------------------------------------------------------------------------- + */ +uint32_t +H5O_mesg_hash(unsigned type_id, H5F_t *f, const void *mesg) +{ + size_t buf_size; + unsigned char * buf = NULL; /* Buffer to be hashed */ + uint32_t hash; + uint32_t ret_value; + + FUNC_ENTER_NOAPI(H5O_mesg_hash, FAIL) + + /* Check args */ + HDassert(type_id < NELMTS(H5O_msg_class_g)); + HDassert(mesg); + HDassert(f); + + /* Find out the size of buffer needed */ + if((buf_size = H5O_raw_size(type_id, f, mesg)) <= 0) + HGOTO_ERROR(H5E_OHDR, H5E_BADSIZE, FAIL, "can't find message size"); + + /* JAMES: revisit this! Some messages don't use as much space as they say + * they need. Quincey may have fixed this. + */ + if((buf = HDmalloc(buf_size)) == NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate buffer for message"); + HDmemset(buf, 0, buf_size); + + if(H5O_encode(f, buf, mesg, type_id) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "can't encode OH message"); + + /* + * Compute the hash value for this message. type_id is used here to + * initialize the hash algorithm, and affects the resulting value. + */ + hash = H5_checksum_lookup3(buf, buf_size, type_id); + + /* JAMES: this is a pretty good hash function. Do we need to version it? + * If so, we'd do so here. */ + + /* A hash value of H5O_HASH_UNDEF indicates failure. If we naturally + * generated this value, reset it to some valid value. */ + if(hash == H5O_HASH_UNDEF) + hash = (uint32_t) 1; + + ret_value = hash; +done: + if(buf) + HDfree(buf); + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_mesg_hash() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_copy_obj_by_ref + * + * Purpose: Copy the object pointed by _src_ref. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Peter Cao + * Aug 7 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_copy_obj_by_ref(H5O_loc_t *src_oloc, hid_t dxpl_id, H5O_loc_t *dst_oloc, + H5G_loc_t *dst_root_loc, H5O_copy_t *cpy_info) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(H5O_copy_obj_by_ref, FAIL) + + HDassert(src_oloc); + HDassert(dst_oloc); + + /* Perform the copy, or look up existing copy */ + if((ret_value = H5O_copy_header_map(src_oloc, dst_oloc, dxpl_id, cpy_info, FALSE)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object") + + /* Check if a new valid object is copied to the destination */ + if(H5F_addr_defined(dst_oloc->addr) && (ret_value > SUCCEED)) { + char tmp_obj_name[80]; + H5G_name_t new_path; + H5O_loc_t new_oloc; + H5G_loc_t new_loc; + + /* Set up group location for new object */ + new_loc.oloc = &new_oloc; + new_loc.path = &new_path; + H5G_loc_reset(&new_loc); + new_oloc.file = dst_oloc->file; + new_oloc.addr = dst_oloc->addr; + + /* Pick a default name for the new object */ + sprintf(tmp_obj_name, "~obj_pointed_by_%llu", (unsigned long_long)dst_oloc->addr); + + /* Create a link to the newly copied object */ + if(H5L_link(dst_root_loc, tmp_obj_name, &new_loc, H5P_DEFAULT, H5P_DEFAULT, dxpl_id) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to insert link") + + H5G_loc_free(&new_loc); + } /* if (H5F_addr_defined(dst_oloc.addr)) */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_copy_obj_by_ref() */ + + + #ifdef H5O_DEBUG /*------------------------------------------------------------------------- @@ -5603,7 +6076,7 @@ H5O_debug_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, haddr_t addr, FILE *stream, i H5O_shared_t *shared = (H5O_shared_t*)(oh->mesg[i].native); void *mesg; - mesg = H5O_read_real(&(shared->oloc), oh->mesg[i].type, 0, NULL, dxpl_id); + mesg = H5O_shared_read(f, dxpl_id, shared, oh->mesg[i].type, NULL); if(oh->mesg[i].type->debug) (oh->mesg[i].type->debug)(f, dxpl_id, mesg, stream, indent + 3, MAX (0, fwidth - 3)); H5O_free_real(oh->mesg[i].type, mesg); diff --git a/src/H5Oattr.c b/src/H5Oattr.c index b939ba4..81690e0 100644 --- a/src/H5Oattr.c +++ b/src/H5Oattr.c @@ -27,6 +27,7 @@ #include "H5MMprivate.h" /* Memory management */ #include "H5Opkg.h" /* Object headers */ #include "H5Spkg.h" /* Dataspaces */ +#include "H5SMprivate.h" /* Shared Object Header Messages */ /* PRIVATE PROTOTYPES */ static herr_t H5O_attr_encode(H5F_t *f, uint8_t *p, const void *mesg); @@ -39,8 +40,14 @@ static herr_t H5O_attr_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_ static herr_t H5O_attr_link(H5F_t *f, hid_t dxpl_id, const void *_mesg); static herr_t H5O_attr_pre_copy_file(H5F_t *file_src, const H5O_msg_class_t *type, void *mesg_src, hbool_t *deleted, const H5O_copy_t *cpy_info, void *udata); -static void *H5O_attr_copy_file(H5F_t *file_src, void *native_src, - H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, void *udata); +static void *H5O_attr_copy_file(H5F_t *file_src, const H5O_msg_class_t *mesg_type, + void *native_src, H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, + void *udata); +static herr_t H5O_attr_get_share(H5F_t *f, const void *_mesg, + H5O_shared_t *sh); +static herr_t H5O_attr_set_share(H5F_t *f, void *_mesg, + const H5O_shared_t *sh); +static htri_t H5O_attr_is_shared(const void *_mesg); static herr_t H5O_attr_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); @@ -57,8 +64,9 @@ const H5O_msg_class_t H5O_MSG_ATTR[1] = {{ H5O_attr_free, /* free method */ H5O_attr_delete, /* file delete method */ H5O_attr_link, /* link method */ - NULL, /* get share method */ - NULL, /* set share method */ + H5O_attr_get_share, /* get share method */ + H5O_attr_set_share, /* set share method */ + H5O_attr_is_shared, /*is shared method */ H5O_attr_pre_copy_file, /* pre copy native value to file */ H5O_attr_copy_file, /* copy native value to file */ NULL, /* post copy native value to file */ @@ -74,12 +82,16 @@ const H5O_msg_class_t H5O_MSG_ATTR[1] = {{ /* Add support for different character encodings of attribute names */ #define H5O_ATTR_VERSION_3 3 +/* Add support for shared dataspaces */ +#define H5O_ATTR_VERSION_4 4 + /* The latest version of the format. Look through the 'encode' * and 'size' callback for places to change when updating this. */ -#define H5O_ATTR_VERSION_LATEST H5O_ATTR_VERSION_3 +#define H5O_ATTR_VERSION_LATEST H5O_ATTR_VERSION_4 /* Flags for attribute flag encoding */ #define H5O_ATTR_FLAG_TYPE_SHARED 0x01 +#define H5O_ATTR_FLAG_SPACE_SHARED 0x02 /* Declare external the free list for H5S_t's */ H5FL_EXTERN(H5S_t); @@ -141,7 +153,7 @@ H5O_attr_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p) /* Version number */ version = *p++; - if(version < H5O_ATTR_VERSION_1 || version > H5O_ATTR_VERSION_3) + if(version < H5O_ATTR_VERSION_1 || version > H5O_ATTR_VERSION_4) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for attribute message") /* Get the flags byte if we have a later version of the attribute */ @@ -197,14 +209,32 @@ H5O_attr_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p) else p += attr->dt_size; - /* decode the attribute dataspace */ + /* decode the attribute dataspace. It can be shared in versions >= 4 + * What's actually shared, though, is only the extent. + */ if(NULL == (attr->ds = H5FL_CALLOC(H5S_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - if((extent = (H5O_MSG_SDSPACE->decode)(f, dxpl_id, p)) == NULL) - HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, NULL, "can't decode attribute dataspace") + if (flags & H5O_ATTR_FLAG_SPACE_SHARED) { + H5O_shared_t *shared; /* Shared information */ + + /* Get the shared information */ + if (NULL == (shared = (H5O_MSG_SHARED->decode) (f, dxpl_id, p))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, NULL, "unable to decode shared message") - /* Copy the extent information */ + /* Get the actual datatype information */ + if((extent= H5O_shared_read(f, dxpl_id, shared, H5O_MSG_SDSPACE, NULL))==NULL) + HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, NULL, "can't decode attribute dataspace") + + /* Free the shared information */ + H5O_free_real(H5O_MSG_SHARED, shared); + } /* end if */ + else { + if((extent = (H5O_MSG_SDSPACE->decode)(f, dxpl_id, p)) == NULL) + HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, NULL, "can't decode attribute dataspace") + } /* end else */ + + /* Copy the extent information to the dataspace */ HDmemcpy(&(attr->ds->extent), extent, sizeof(H5S_extent_t)); /* Release temporary extent information */ @@ -276,9 +306,13 @@ H5O_attr_encode(H5F_t *f, uint8_t *p, const void *mesg) { const H5A_t *attr = (const H5A_t *) mesg; size_t name_len; /* Attribute name length */ + htri_t is_shared_ret; /* Return value from H5O_is_shared */ unsigned version; /* Attribute version */ hbool_t type_shared; /* Flag to indicate that a shared datatype is used for this attribute */ + hbool_t space_shared; /* Flag to indicate that a shared dataspace is used for this attribute */ + H5O_shared_t sh_mesg; /* Shared message location */ hbool_t use_latest_format; /* Flag indicating the newest file format should be used */ + unsigned flags=0; /* Attribute flags */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_attr_encode) @@ -291,15 +325,26 @@ H5O_attr_encode(H5F_t *f, uint8_t *p, const void *mesg) /* Get the file's 'use the latest version of the format' flag */ use_latest_format = H5F_USE_LATEST_FORMAT(f); - /* Check whether datatype is shared */ - if(H5T_committed(attr->dt)) + /* Check whether datatype and dataspace are shared */ + if((is_shared_ret = H5O_is_shared(H5O_DTYPE_ID, attr->dt)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "can't determine if datatype is shared") + else if(is_shared_ret) type_shared = TRUE; else type_shared = FALSE; + if((is_shared_ret = H5O_is_shared(H5O_SDSPACE_ID, attr->ds)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "can't determine if dataspace is shared") + else if(is_shared_ret) + space_shared = TRUE; + else + space_shared = FALSE; + /* Check which version to write out */ if(use_latest_format) version = H5O_ATTR_VERSION_LATEST; /* Write out latest version of format */ + else if(space_shared) + version = H5O_ATTR_VERSION_4; /* Write version with shared dataspaces */ else if(attr->encoding != H5T_CSET_ASCII) version = H5O_ATTR_VERSION_3; /* Write version which includes the character encoding */ else if(type_shared) @@ -312,7 +357,11 @@ H5O_attr_encode(H5F_t *f, uint8_t *p, const void *mesg) /* Set attribute flags if version >1 */ if(version > H5O_ATTR_VERSION_1) - *p++ = (type_shared ? H5O_ATTR_FLAG_TYPE_SHARED : 0 ); /* Set flags for attribute */ + { + flags = (type_shared ? H5O_ATTR_FLAG_TYPE_SHARED : 0 ); + flags |= (space_shared ? H5O_ATTR_FLAG_SPACE_SHARED : 0); + *p++ = flags; /* Set flags for attribute */ + } else *p++ = 0; /* Reserved, for version <2 */ @@ -330,6 +379,7 @@ H5O_attr_encode(H5F_t *f, uint8_t *p, const void *mesg) * Encode the character encoding used for the attribute's name * Also add several "reserved" fields to pad to 16 bytes. */ + /* JAMES: only do this if flag says to? */ if(version >= H5O_ATTR_VERSION_3) *p++ = attr->encoding; @@ -345,8 +395,6 @@ H5O_attr_encode(H5F_t *f, uint8_t *p, const void *mesg) /* encode the attribute datatype */ if(type_shared) { - H5O_shared_t sh_mesg; - /* Reset shared message information */ HDmemset(&sh_mesg, 0, sizeof(H5O_shared_t)); @@ -363,6 +411,7 @@ H5O_attr_encode(H5F_t *f, uint8_t *p, const void *mesg) if((H5O_MSG_DTYPE->encode)(f, p, attr->dt) < 0) HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "can't encode attribute datatype") } /* end else */ + if(version < H5O_ATTR_VERSION_2) { HDmemset(p + attr->dt_size, 0, H5O_ALIGN_OLD(attr->dt_size) - attr->dt_size); p += H5O_ALIGN_OLD(attr->dt_size); @@ -371,8 +420,24 @@ H5O_attr_encode(H5F_t *f, uint8_t *p, const void *mesg) p += attr->dt_size; /* encode the attribute dataspace */ - if((H5O_MSG_SDSPACE->encode)(f, p, &(attr->ds->extent)) < 0) - HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "can't encode attribute dataspace") + if(space_shared) { + /* Reset shared message information */ + HDmemset(&sh_mesg, 0, sizeof(H5O_shared_t)); + + /* Get shared message information from dataspace */ + if((H5O_MSG_SDSPACE->get_share)(f, attr->ds, &sh_mesg/*out*/) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "can't encode shared attribute dataspace") + + /* Encode shared message information for dataspace */ + if((H5O_MSG_SHARED->encode)(f, p, &sh_mesg) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "can't encode shared attribute dataspace") + } /* end if */ + else { + /* Encode non-shared dataspace information */ + if((H5O_MSG_SDSPACE->encode)(f, p, &(attr->ds->extent)) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "can't encode attribute dataspace") + } /* end else */ + if(version < H5O_ATTR_VERSION_2) { HDmemset(p + attr->ds_size, 0, H5O_ALIGN_OLD(attr->ds_size) - attr->ds_size); p += H5O_ALIGN_OLD(attr->ds_size); @@ -451,8 +516,8 @@ H5O_attr_size(const H5F_t *f, const void *_mesg) { const H5A_t *attr = (const H5A_t *)_mesg; size_t name_len; - unsigned version; /* Attribute version */ - hbool_t type_shared; /* Flag to indicate that a shared datatype is used for this attribute */ + unsigned version; /* Attribute version */ + hbool_t type_shared, space_shared; /* Flags to indicate that shared messages are used for this attribute */ hbool_t use_latest_format; /* Flag indicating the newest file format should be used */ size_t ret_value = 0; @@ -465,15 +530,22 @@ H5O_attr_size(const H5F_t *f, const void *_mesg) /* Get the file's 'use the latest version of the format' flag */ use_latest_format = H5F_USE_LATEST_FORMAT(f); - /* Check whether datatype is shared */ - if(H5T_committed(attr->dt)) + /* Check whether datatype and dataspace are shared */ + if(H5O_is_shared(H5O_DTYPE_ID, attr->dt) > 0) type_shared = TRUE; else type_shared = FALSE; + if(H5O_is_shared(H5O_SDSPACE_ID, attr->ds) > 0) + space_shared = TRUE; + else + space_shared = FALSE; + /* Check which version to write out */ if(use_latest_format) version = H5O_ATTR_VERSION_LATEST; /* Write out latest version of format */ + else if(space_shared) + version = H5O_ATTR_VERSION_4; /* Write version with shared dataspaces */ else if(attr->encoding != H5T_CSET_ASCII) version = H5O_ATTR_VERSION_3; /* Write version which includes the character encoding */ else if(type_shared) @@ -499,12 +571,14 @@ H5O_attr_size(const H5F_t *f, const void *_mesg) attr->dt_size + /*data type */ attr->ds_size + /*data space */ attr->data_size; /*the data itself */ - else if(version == H5O_ATTR_VERSION_3) + else if(version == H5O_ATTR_VERSION_3 || version == H5O_ATTR_VERSION_4) ret_value += 1 + /*character encoding */ name_len + /*attribute name */ attr->dt_size + /*data type */ attr->ds_size + /*data space */ attr->data_size; /*the data itself */ + else + HDassert(0 && "Bad attribute version"); FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_attr_size() */ @@ -581,9 +655,11 @@ H5O_attr_free(void *mesg) *------------------------------------------------------------------------- */ static herr_t -H5O_attr_delete(H5F_t UNUSED *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link) +H5O_attr_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link) { const H5A_t *attr = (const H5A_t *) _mesg; + htri_t tri_ret; + H5O_shared_t sh_mesg; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_attr_delete) @@ -592,6 +668,29 @@ H5O_attr_delete(H5F_t UNUSED *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_l HDassert(f); HDassert(attr); + /* Remove both the datatype and dataspace from the SOHM heap if they're + * shared there. + */ + if((tri_ret = H5O_is_shared(H5O_DTYPE_ID, attr->dt)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "can't tell if datatype is shared") + if(tri_ret > 0) + { + if(H5O_get_share(H5O_DTYPE_ID, f, attr->dt, &sh_mesg) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "can't get shared message from datatype") + if(H5SM_try_delete(f, H5AC_dxpl_id, H5O_DTYPE_ID, &sh_mesg) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_CANTREMOVE, FAIL, "can't remove datatype from SOHM heap") + } + + if((tri_ret =H5O_is_shared(H5O_SDSPACE_ID, attr->ds)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "can't tell if dataspace is shared") + if(tri_ret > 0) + { + if(H5O_get_share(H5O_SDSPACE_ID, f, attr->ds, &sh_mesg) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "can't get shared message from dataspace") + if(H5SM_try_delete(f, H5AC_dxpl_id, H5O_SDSPACE_ID, &sh_mesg) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_SOHM, FAIL, "can't remove dataspace from SOHM heap") + } + /* Check whether datatype is shared */ if(H5T_committed(attr->dt)) { /* Decrement the reference count on the shared datatype, if requested */ @@ -700,8 +799,9 @@ H5O_attr_pre_copy_file(H5F_t UNUSED *file_src, const H5O_msg_class_t UNUSED *typ *------------------------------------------------------------------------- */ static void * -H5O_attr_copy_file(H5F_t *file_src, void *native_src, H5F_t *file_dst, - hid_t dxpl_id, H5O_copy_t *cpy_info, void UNUSED *udata) +H5O_attr_copy_file(H5F_t *file_src, const H5O_msg_class_t UNUSED *mesg_type, + void *native_src, H5F_t *file_dst, hid_t dxpl_id, + H5O_copy_t *cpy_info, void UNUSED *udata) { H5A_t *attr_src = (H5A_t *)native_src; H5A_t *attr_dst = NULL; @@ -946,6 +1046,104 @@ done: } /* H5O_attr_copy_file() */ +/*------------------------------------------------------------------------- + * Function: H5O_attr_get_share + * + * Purpose: Gets sharing information from the message + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * Tuesday, October 17, 2006 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_attr_get_share(H5F_t UNUSED *f, const void *_mesg, + H5O_shared_t *sh /*out*/) +{ + H5A_t *mesg = (H5A_t *)_mesg; + herr_t ret_value = SUCCEED; + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_attr_get_share); + + HDassert (mesg); + HDassert (sh); + + if(NULL == H5O_copy(H5O_SHARED_ID, &(mesg->sh_loc), sh)) + ret_value = FAIL; + + FUNC_LEAVE_NOAPI(ret_value); +} + +/*------------------------------------------------------------------------- + * Function: H5O_attr_set_share + * + * Purpose: Sets sharing information for the message + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * Tuesday, October 10, 2006 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_attr_set_share(H5F_t UNUSED *f, void *_mesg/*in,out*/, + const H5O_shared_t *sh) +{ + H5A_t *mesg = (H5A_t *)_mesg; + herr_t ret_value = SUCCEED; + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_attr_set_share); + + HDassert (mesg); + HDassert (sh); + + if(NULL == H5O_copy(H5O_SHARED_ID, sh, &(mesg->sh_loc))) + ret_value = FAIL; + + FUNC_LEAVE_NOAPI(ret_value); +} + +/*------------------------------------------------------------------------- + * Function: H5O_attr_is_shared + * + * Purpose: Determines if this attribute is shared (committed or a SOHM) + * or not. + * + * Return: TRUE if attribute is shared + * FALSE if attribute is not shared + * Negative on failure + * + * Programmer: James Laird + * Tuesday, October 17, 2006 + * + *------------------------------------------------------------------------- + */ +static htri_t +H5O_attr_is_shared(const void *_mesg) +{ + H5A_t *mesg = (H5A_t *)_mesg; + htri_t ret_value; + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_attr_is_shared) + + HDassert(mesg); + + /* Attributes can't currently be committed, but this should let the + * library read a "committed attribute" if we ever create one in + * the future. + */ + if(mesg->sh_loc.flags & (H5O_COMMITTED_FLAG | H5O_SHARED_IN_HEAP_FLAG)) + ret_value = TRUE; + else + ret_value = FALSE; + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_attr_is_shared */ + /*-------------------------------------------------------------------------- NAME H5O_attr_debug diff --git a/src/H5Ocont.c b/src/H5Ocont.c index b0966d3..eab8749 100644 --- a/src/H5Ocont.c +++ b/src/H5Ocont.c @@ -41,8 +41,6 @@ static herr_t H5O_cont_encode(H5F_t *f, uint8_t *p, const void *_mesg); static size_t H5O_cont_size(const H5F_t *f, const void *_mesg); static herr_t H5O_cont_free(void *mesg); static herr_t H5O_cont_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link); -static void *H5O_cont_copy_file(H5F_t *file_src, void *mesg_src, H5F_t *file_dst, - hid_t dxpl_id, H5O_copy_t *cpy_info, void *udata); static herr_t H5O_cont_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); @@ -61,8 +59,9 @@ const H5O_msg_class_t H5O_MSG_CONT[1] = {{ NULL, /* link method */ NULL, /*get share method */ NULL, /*set share method */ + NULL, /*is shared method */ NULL, /* pre copy native value to file */ - H5O_cont_copy_file, /* copy native value to file */ + NULL, /* copy native value to file */ NULL, /* post copy native value to file */ H5O_cont_debug /*debugging */ }}; @@ -249,56 +248,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5O_cont_copy_file - * - * Purpose: Copies a continuation block message from _MESG to _DEST in file - * - * Return: Success: Ptr to _DEST - * - * Failure: NULL - * - * Programmer: Peter Cao - * September 22, 2005 - * - *------------------------------------------------------------------------- - */ -static void * -H5O_cont_copy_file(H5F_t UNUSED *file_src, void *mesg_src, H5F_t UNUSED *file_dst, - hid_t UNUSED dxpl_id, H5O_copy_t UNUSED *cpy_info, void *udata) -{ - H5O_cont_t *cont_src = (H5O_cont_t *)mesg_src; - H5O_chunk_t *chunk = (H5O_chunk_t *)udata; - H5O_cont_t *cont_dst = NULL; - void *ret_value; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5O_cont_copy_file) - - /* check args */ - HDassert(cont_src); - - /* Allocate space for the destination cont */ - if(NULL == (cont_dst = H5FL_MALLOC(H5O_cont_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - - /* Shallow copy all the fields */ - *cont_dst = *cont_src; - - /* Update the destination address to point to correct address in dest. file */ - cont_dst->addr = chunk[cont_src->chunkno].addr; - - /* Set return value */ - ret_value = cont_dst; - -done: - if(!ret_value) - if(cont_dst) - H5FL_FREE(H5O_cont_t, cont_dst); - - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5O_cont_copy_file() */ - - -/*------------------------------------------------------------------------- * Function: H5O_cont_debug * * Purpose: Prints debugging info. diff --git a/src/H5Odtype.c b/src/H5Odtype.c index 6314dfe..27a8d2f 100644 --- a/src/H5Odtype.c +++ b/src/H5Odtype.c @@ -37,6 +37,7 @@ static herr_t H5O_dtype_get_share(H5F_t *f, const void *_mesg, H5O_shared_t *sh); static herr_t H5O_dtype_set_share(H5F_t *f, void *_mesg, const H5O_shared_t *sh); +static herr_t H5O_dtype_is_shared (const void *_mesg); static herr_t H5O_dtype_pre_copy_file(H5F_t *file_src, const H5O_msg_class_t *type, void *mesg_src, hbool_t *deleted, const H5O_copy_t *cpy_info, void *_udata); static herr_t H5O_dtype_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, @@ -57,6 +58,7 @@ const H5O_msg_class_t H5O_MSG_DTYPE[1] = {{ NULL, /* link method */ H5O_dtype_get_share, /* get share method */ H5O_dtype_set_share, /* set share method */ + H5O_dtype_is_shared, /* is shared method */ H5O_dtype_pre_copy_file, /* pre copy native value to file */ NULL, /* copy native value to file */ NULL, /* post copy native value to file */ @@ -1280,15 +1282,19 @@ H5O_dtype_get_share(H5F_t UNUSED *f, const void *_mesg, HDassert(dt); HDassert(sh); - /* Check for object location address defined */ - if(!H5F_addr_defined(dt->oloc.addr)) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "datatype is not sharable") + /* Make sure the datatype is shared */ + HDassert(dt->sh_loc.flags & (H5O_SHARED_IN_HEAP_FLAG | H5O_COMMITTED_FLAG)); - /* If the address is defined, this had better be a named datatype */ - HDassert(H5T_STATE_NAMED == dt->shared->state || H5T_STATE_OPEN == dt->shared->state); + /* Make sure datatype state is correct: committed datatypes must have + * state NAMED or OPEN and datatypes in the heap cannot be NAMED or OPEN. */ + if(dt->sh_loc.flags & H5O_SHARED_IN_HEAP_FLAG) + HDassert(! (H5T_STATE_NAMED == dt->shared->state || H5T_STATE_OPEN == dt->shared->state)); + else + HDassert(H5T_STATE_NAMED == dt->shared->state || H5T_STATE_OPEN == dt->shared->state); - /* Copy object location info */ - H5O_loc_copy(&(sh->oloc), &(dt->oloc), H5_COPY_DEEP); + /* Do actual copy of shared information */ + if(NULL == H5O_copy(H5O_SHARED_ID, &(dt->sh_loc), sh)) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to get shared information") done: FUNC_LEAVE_NOAPI(ret_value) @@ -1312,23 +1318,69 @@ H5O_dtype_set_share(H5F_t UNUSED *f, void *_mesg/*in,out*/, const H5O_shared_t *sh) { H5T_t *dt = (H5T_t *)_mesg; + herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_dtype_set_share) HDassert(dt); HDassert(sh); - /* Retrieve object location information */ - H5O_loc_copy(&(dt->oloc), &(sh->oloc), H5_COPY_DEEP); + /* Make sure the shared message location is initialized*/ + HDassert(sh->flags & (H5O_SHARED_IN_HEAP_FLAG | H5O_COMMITTED_FLAG)); - /* Note that the datatype is a named datatype */ - dt->shared->state = H5T_STATE_NAMED; + /* Make sure we're not sharing a committed type in the heap */ + HDassert(sh->flags & H5O_COMMITTED_FLAG || + (dt->shared->state != H5T_STATE_OPEN && dt->shared->state != H5T_STATE_NAMED)); - FUNC_LEAVE_NOAPI(SUCCEED) + /* Copy the shared information */ + if(NULL == H5O_copy(H5O_SHARED_ID, sh, &(dt->sh_loc))) + ret_value = FAIL; + + /* If this is now a committed datatype, set its state properly. */ + if(sh->flags & H5O_COMMITTED_FLAG) + { + dt->shared->state = H5T_STATE_NAMED; + } + + FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_dtype_set_share() */ /*------------------------------------------------------------------------- + * Function: H5O_dtype_is_shared + * + * Purpose: Determines if this datatype is shared (committed or a SOHM) + * or not. + * + * Return: TRUE if datatype is shared + * FALSE if datatype is not shared + * Negative on failure + * + * Programmer: James Laird + * Monday, October 16, 2006 + * + *------------------------------------------------------------------------- + */ +static htri_t +H5O_dtype_is_shared (const void *_mesg) +{ + H5T_t *dt = (H5T_t *)_mesg; + htri_t ret_value; + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_dtype_is_shared) + + HDassert(dt); + + if(dt->sh_loc.flags & (H5O_COMMITTED_FLAG | H5O_SHARED_IN_HEAP_FLAG)) + ret_value = TRUE; + else + ret_value = FALSE; + + FUNC_LEAVE_NOAPI(ret_value) + +} /* end H5O_dtype_is_shared */ + + +/*------------------------------------------------------------------------- * Function: H5O_dtype_pre_copy_file * * Purpose: Perform any necessary actions before copying message between diff --git a/src/H5Oefl.c b/src/H5Oefl.c index 1d201db..d222dde 100644 --- a/src/H5Oefl.c +++ b/src/H5Oefl.c @@ -33,8 +33,8 @@ static herr_t H5O_efl_encode(H5F_t *f, uint8_t *p, const void *_mesg); static void *H5O_efl_copy(const void *_mesg, void *_dest, unsigned update_flags); static size_t H5O_efl_size(const H5F_t *f, const void *_mesg); static herr_t H5O_efl_reset(void *_mesg); -static void *H5O_efl_copy_file(H5F_t *file_src, void *mesg_src, H5F_t *file_dst, - hid_t dxpl_id, H5O_copy_t *cpy_info, void *udata); +static void *H5O_efl_copy_file(H5F_t *file_src, const H5O_msg_class_t *mesg_type, + void *mesg_src, H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, void *udata); static herr_t H5O_efl_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); @@ -53,6 +53,7 @@ const H5O_msg_class_t H5O_MSG_EFL[1] = {{ NULL, /* link method */ NULL, /*get share method */ NULL, /*set share method */ + NULL, /*is shared method */ NULL, /* pre copy native value to file */ H5O_efl_copy_file, /* copy native value to file */ NULL, /* post copy native value to file */ @@ -435,8 +436,9 @@ done: *------------------------------------------------------------------------- */ static void * -H5O_efl_copy_file(H5F_t UNUSED *file_src, void *mesg_src, H5F_t *file_dst, - hid_t dxpl_id, H5O_copy_t UNUSED *cpy_info, void UNUSED *_udata) +H5O_efl_copy_file(H5F_t UNUSED *file_src, const H5O_msg_class_t UNUSED *mesg_type, + void *mesg_src, H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t UNUSED *cpy_info, + void UNUSED *_udata) { H5O_efl_t *efl_src = (H5O_efl_t *) mesg_src; H5O_efl_t *efl_dst = NULL; diff --git a/src/H5Ofill.c b/src/H5Ofill.c index eb36e4b..22e0ae1 100644 --- a/src/H5Ofill.c +++ b/src/H5Ofill.c @@ -45,6 +45,11 @@ static void *H5O_fill_copy(const void *_mesg, void *_dest, unsigned update_flag static size_t H5O_fill_size(const H5F_t *f, const void *_mesg); static herr_t H5O_fill_reset(void *_mesg); static herr_t H5O_fill_free(void *_mesg); +static herr_t H5O_fill_new_get_share (H5F_t *f, const void *_mesg, + H5O_shared_t *sh); +static herr_t H5O_fill_new_set_share (H5F_t *f, void *_mesg, + const H5O_shared_t *sh); +static htri_t H5O_fill_new_is_shared(const void *_mesg); static herr_t H5O_fill_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE *stream, int indent, int fwidth); @@ -56,17 +61,18 @@ const H5O_msg_class_t H5O_MSG_FILL[1] = {{ H5O_fill_decode, /*decode message */ H5O_fill_encode, /*encode message */ H5O_fill_copy, /*copy the native value */ - H5O_fill_size, /*raw message size */ - H5O_fill_reset, /*free internal memory */ - H5O_fill_free, /* free method */ - NULL, /* file delete method */ - NULL, /* link method */ - NULL, /*get share method */ - NULL, /*set share method */ - NULL, /* pre copy native value to file */ - NULL, /* copy native value to file */ - NULL, /* post copy native value to file */ - H5O_fill_debug /*debug the message */ + H5O_fill_size, /*raw message size */ + H5O_fill_reset, /*free internal memory */ + H5O_fill_free, /* free method */ + NULL, /* file delete method */ + NULL, /* link method */ + H5O_fill_new_get_share, /* get share method */ + H5O_fill_new_set_share, /* set share method */ + H5O_fill_new_is_shared, /* is shared method */ + NULL, /* pre copy native value to file */ + NULL, /* copy native value to file */ + NULL, /* post copy native value to file */ + H5O_fill_debug /*debug the message */ }}; /* This message derives from H5O message class, for new fill value after version 1.4 */ @@ -79,14 +85,15 @@ const H5O_msg_class_t H5O_MSG_FILL_NEW[1] = {{ H5O_fill_new_copy, /*copy the native value */ H5O_fill_new_size, /*raw message size */ H5O_fill_new_reset, /*free internal memory */ - H5O_fill_new_free, /* free method */ - NULL, /* file delete method */ - NULL, /* link method */ - NULL, /*get share method */ - NULL, /*set share method */ - NULL, /* pre copy native value to file */ - NULL, /* copy native value to file */ - NULL, /* post copy native value to file */ + H5O_fill_new_free, /* free method */ + NULL, /* file delete method */ + NULL, /* link method */ + H5O_fill_new_get_share, /* get share method */ + H5O_fill_new_set_share, /* set share method */ + H5O_fill_new_is_shared, /* is shared method */ + NULL, /* pre copy native value to file */ + NULL, /* copy native value to file */ + NULL, /* post copy native value to file */ H5O_fill_new_debug /*debug the message */ }}; @@ -349,6 +356,10 @@ H5O_fill_new_copy(const void *_mesg, void *_dest, unsigned UNUSED update_flags) if(!dest && NULL == (dest = H5FL_MALLOC(H5O_fill_new_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill message") + /* Copy shared message information */ + if(NULL == H5O_copy(H5O_SHARED_ID, &(mesg->sh_loc), &(dest->sh_loc))) + HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, NULL, "unable to copy fill value shared info"); + /* Copy data type of fill value */ if(mesg->type) { if(NULL == (dest->type = H5T_copy(mesg->type, H5T_COPY_TRANSIENT))) @@ -607,7 +618,7 @@ H5O_fill_reset(void *_mesg) /*------------------------------------------------------------------------- * Function: H5O_fill_new_free * - * Purpose: Free's the message + * Purpose: Frees the message * * Return: Non-negative on success/Negative on failure * @@ -625,6 +636,7 @@ H5O_fill_new_free (void *mesg) HDassert(mesg); + /* JAMES: should this free the O_loc? */ H5FL_FREE(H5O_fill_new_t, mesg); FUNC_LEAVE_NOAPI(SUCCEED) @@ -634,7 +646,7 @@ H5O_fill_new_free (void *mesg) /*------------------------------------------------------------------------- * Function: H5O_fill_free * - * Purpose: Free's the message + * Purpose: Frees the message * * Return: Non-negative on success/Negative on failure * @@ -659,6 +671,106 @@ H5O_fill_free (void *mesg) /*------------------------------------------------------------------------- + * Function: H5O_fill_new_get_share + * + * Purpose: Gets sharing information from the message + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * Tuesday, October 10, 2006 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_fill_new_get_share(H5F_t UNUSED *f, const void *_mesg, + H5O_shared_t *sh /*out*/) +{ + H5O_fill_new_t *mesg = (H5O_fill_new_t *)_mesg; + herr_t ret_value = SUCCEED; + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_fill_new_get_share); + + HDassert (mesg); + HDassert (sh); + + if(NULL == H5O_copy(H5O_SHARED_ID, &(mesg->sh_loc), sh)) + ret_value = FAIL; + + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5O_fill_new_get_share() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_fill_new_set_share + * + * Purpose: Sets sharing information for the message + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * Tuesday, October 10, 2006 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_fill_new_set_share(H5F_t UNUSED *f, void *_mesg/*in,out*/, + const H5O_shared_t *sh) +{ + H5O_fill_new_t *mesg = (H5O_fill_new_t *)_mesg; + herr_t ret_value = SUCCEED; + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_fill_new_set_share); + + HDassert (mesg); + HDassert (sh); + + if(NULL == H5O_copy(H5O_SHARED_ID, sh, &(mesg->sh_loc))) + ret_value = FAIL; + + FUNC_LEAVE_NOAPI(ret_value); +} + +/*------------------------------------------------------------------------- + * Function: H5O_fill_new_is_shared + * + * Purpose: Determines if this fill value is shared (committed or a SOHM) + * or not. + * + * Return: TRUE if fill value is shared + * FALSE if fill value is not shared + * Negative on failure + * + * Programmer: James Laird + * Monday, October 16, 2006 + * + *------------------------------------------------------------------------- + */ +static htri_t +H5O_fill_new_is_shared(const void *_mesg) +{ + H5O_fill_new_t *mesg = (H5O_fill_new_t *)_mesg; + htri_t ret_value; + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_fill_new_is_shared) + + HDassert(mesg); + + /* Fill values can't currently be committed, but this should let the + * library read a "committed fill value" if we ever create one in + * the future. + */ + if(mesg->sh_loc.flags & (H5O_COMMITTED_FLAG | H5O_SHARED_IN_HEAP_FLAG)) + ret_value = TRUE; + else + ret_value = FALSE; + + FUNC_LEAVE_NOAPI(ret_value) + +} /* end H5O_fill_new_is_shared */ + +/*------------------------------------------------------------------------- * Function: H5O_fill_new_debug * * Purpose: Prints debugging info for the message. diff --git a/src/H5Oginfo.c b/src/H5Oginfo.c index ae8aaef..f7c834f 100644 --- a/src/H5Oginfo.c +++ b/src/H5Oginfo.c @@ -57,6 +57,7 @@ const H5O_msg_class_t H5O_MSG_GINFO[1] = {{ NULL, /* link method */ NULL, /*get share method */ NULL, /*set share method */ + NULL, /*is shared method */ NULL, /* pre copy native value to file */ NULL, /* copy native value to file */ NULL, /* post copy native value to file */ diff --git a/src/H5Olayout.c b/src/H5Olayout.c index 6414c37..a420301 100644 --- a/src/H5Olayout.c +++ b/src/H5Olayout.c @@ -39,8 +39,8 @@ static size_t H5O_layout_size(const H5F_t *f, const void *_mesg); static herr_t H5O_layout_reset(void *_mesg); static herr_t H5O_layout_free(void *_mesg); static herr_t H5O_layout_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link); -static void *H5O_layout_copy_file(H5F_t *file_src, void *mesg_src, H5F_t *file_dst, - hid_t dxpl_id, H5O_copy_t *cpy_info, void *udata); +static void *H5O_layout_copy_file(H5F_t *file_src, const H5O_msg_class_t *mesg_type, + void *mesg_src, H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, void *udata); static herr_t H5O_layout_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); @@ -59,6 +59,7 @@ const H5O_msg_class_t H5O_MSG_LAYOUT[1] = {{ NULL, /* link method */ NULL, /*get share method */ NULL, /*set share method */ + NULL, /*is shared method */ NULL, /* pre copy native value to file */ H5O_layout_copy_file, /* copy native value to file */ NULL, /* post copy native value to file */ @@ -621,8 +622,9 @@ done: *------------------------------------------------------------------------- */ static void * -H5O_layout_copy_file(H5F_t *file_src, void *mesg_src, H5F_t *file_dst, hid_t dxpl_id, - H5O_copy_t *cpy_info, void *_udata) +H5O_layout_copy_file(H5F_t *file_src, const H5O_msg_class_t UNUSED *mesg_type, + void *mesg_src, H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, + void *_udata) { H5D_copy_file_ud_t *udata = (H5D_copy_file_ud_t *)_udata; /* Dataset copying user data */ H5O_layout_t *layout_src = (H5O_layout_t *) mesg_src; diff --git a/src/H5Olinfo.c b/src/H5Olinfo.c index 12cf38f..668ea30 100644 --- a/src/H5Olinfo.c +++ b/src/H5Olinfo.c @@ -42,8 +42,9 @@ static void *H5O_linfo_copy(const void *_mesg, void *_dest, unsigned update_flag static size_t H5O_linfo_size(const H5F_t *f, const void *_mesg); static herr_t H5O_linfo_free(void *_mesg); static herr_t H5O_linfo_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link); -static void *H5O_linfo_copy_file(H5F_t *file_src, void *native_src, - H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, void *udata); +static void *H5O_linfo_copy_file(H5F_t *file_src, const H5O_msg_class_t *mesg_type, + void *native_src, H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, + void *udata); static herr_t H5O_linfo_post_copy_file(const H5O_loc_t *parent_src_oloc, const void *mesg_src, H5O_loc_t *dst_oloc, void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info); static herr_t H5O_linfo_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, @@ -64,6 +65,7 @@ const H5O_msg_class_t H5O_MSG_LINFO[1] = {{ NULL, /* link method */ NULL, /*get share method */ NULL, /*set share method */ + NULL, /*is shared method */ NULL, /* pre copy native value to file */ H5O_linfo_copy_file, /* copy native value to file */ H5O_linfo_post_copy_file, /* post copy native value to file */ @@ -374,8 +376,9 @@ done: *------------------------------------------------------------------------- */ static void * -H5O_linfo_copy_file(H5F_t UNUSED *file_src, void *native_src, H5F_t *file_dst, - hid_t dxpl_id, H5O_copy_t *cpy_info, void UNUSED *udata) +H5O_linfo_copy_file(H5F_t UNUSED *file_src, const H5O_msg_class_t UNUSED *mesg_type, + void *native_src, H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, + void UNUSED *udata) { H5O_linfo_t *linfo_src = (H5O_linfo_t *) native_src; H5O_linfo_t *linfo_dst = NULL; diff --git a/src/H5Olink.c b/src/H5Olink.c index 7d2b694..9331019 100644 --- a/src/H5Olink.c +++ b/src/H5Olink.c @@ -44,8 +44,9 @@ static herr_t H5O_link_free(void *_mesg); static herr_t H5O_link_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link); static herr_t H5O_link_pre_copy_file(H5F_t *file_src, const H5O_msg_class_t *type, void *mesg_src, hbool_t *deleted, const H5O_copy_t *cpy_info, void *udata); -static void *H5O_link_copy_file(H5F_t *file_src, void *native_src, - H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, void *udata); +static void *H5O_link_copy_file(H5F_t *file_src, const H5O_msg_class_t *mesg_type, + void *native_src, H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, + void *udata); static herr_t H5O_link_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, H5O_loc_t *dst_oloc, void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info); static herr_t H5O_link_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, @@ -66,6 +67,7 @@ const H5O_msg_class_t H5O_MSG_LINK[1] = {{ NULL, /* link method */ NULL, /*get share method */ NULL, /*set share method */ + NULL, /*is shared method */ H5O_link_pre_copy_file, /* pre copy native value to file */ H5O_link_copy_file, /* copy native value to file */ H5O_link_post_copy_file, /* post copy native value to file */ @@ -572,8 +574,9 @@ H5O_link_pre_copy_file(H5F_t UNUSED *file_src, const H5O_msg_class_t UNUSED *typ *------------------------------------------------------------------------- */ static void * -H5O_link_copy_file(H5F_t UNUSED *file_src, void *native_src, H5F_t UNUSED *file_dst, - hid_t UNUSED dxpl_id, H5O_copy_t UNUSED *cpy_info, void UNUSED *udata) +H5O_link_copy_file(H5F_t UNUSED *file_src, const H5O_msg_class_t UNUSED *mesg_type, + void *native_src, H5F_t UNUSED *file_dst, hid_t UNUSED dxpl_id, + H5O_copy_t UNUSED *cpy_info, void UNUSED *udata) { H5O_link_t *link_src = (H5O_link_t *)native_src; H5O_link_t *link_dst = NULL; diff --git a/src/H5Omtime.c b/src/H5Omtime.c index 8673d32..b526162 100644 --- a/src/H5Omtime.c +++ b/src/H5Omtime.c @@ -60,6 +60,7 @@ const H5O_msg_class_t H5O_MSG_MTIME[1] = {{ NULL, /* link method */ NULL, /*get share method */ NULL, /*set share method */ + NULL, /*is shared method */ NULL, /* pre copy native value to file */ NULL, /* copy native value to file */ NULL, /* post copy native value to file */ @@ -82,6 +83,7 @@ const H5O_msg_class_t H5O_MSG_MTIME_NEW[1] = {{ NULL, /* link method */ NULL, /*get share method */ NULL, /*set share method */ + NULL, /*is shared method */ NULL, /* pre copy native value to file */ NULL, /* copy native value to file */ NULL, /* post copy native value to file */ diff --git a/src/H5Oname.c b/src/H5Oname.c index 7b43b6c..146ef8a 100644 --- a/src/H5Oname.c +++ b/src/H5Oname.c @@ -57,6 +57,7 @@ const H5O_msg_class_t H5O_MSG_NAME[1] = {{ NULL, /* link method */ NULL, /*get share method */ NULL, /*set share method */ + NULL, /*is shared method */ NULL, /* pre copy native value to file */ NULL, /* copy native value to file */ NULL, /* post copy native value to file */ diff --git a/src/H5Opkg.h b/src/H5Opkg.h index 30b55c7..a0812c9 100644 --- a/src/H5Opkg.h +++ b/src/H5Opkg.h @@ -155,8 +155,9 @@ struct H5O_msg_class_t { herr_t (*link)(H5F_t *, hid_t, const void *); /* Increment any links in file reference by this message */ herr_t (*get_share)(H5F_t*, const void*, struct H5O_shared_t*); /* Get shared information */ herr_t (*set_share)(H5F_t*, void*, const struct H5O_shared_t*); /* Set shared information */ + htri_t (*is_shared)(const void*); /* Is message shared? */ herr_t (*pre_copy_file)(H5F_t *, const H5O_msg_class_t *, void *, hbool_t *, const H5O_copy_t *, void *); /*"pre copy" action when copying native value to file */ - void *(*copy_file)(H5F_t *, void *, H5F_t *, hid_t, H5O_copy_t *, void *); /*copy native value to file */ + void *(*copy_file)(H5F_t *, const H5O_msg_class_t *, void *, H5F_t *, hid_t, H5O_copy_t *, void *); /*copy native value to file */ herr_t (*post_copy_file)(const H5O_loc_t *, const void *, H5O_loc_t *, void *, hid_t, H5O_copy_t *); /*"post copy" action when copying native value to file */ herr_t (*debug)(H5F_t*, hid_t, const void*, FILE*, int, int); }; @@ -346,6 +347,9 @@ H5_DLL void * H5O_free_real(const H5O_msg_class_t *type, void *mesg); H5_DLL herr_t H5O_assert(const H5O_t *oh); #endif /* H5O_DEBUG */ H5_DLL herr_t H5O_debug_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, haddr_t addr, FILE *stream, int indent, int fwidth); +H5_DLL void * H5O_copy_mesg_file(const H5O_msg_class_t *copy_type, + const H5O_msg_class_t *mesg_type, H5F_t *file_src, void *mesg_src, + H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, void *udata); /* Shared object operators */ H5_DLL void * H5O_shared_read(H5F_t *f, hid_t dxpl_id, H5O_shared_t *shared, diff --git a/src/H5Opline.c b/src/H5Opline.c index fefaa78..fae31fb 100644 --- a/src/H5Opline.c +++ b/src/H5Opline.c @@ -35,6 +35,11 @@ static void *H5O_pline_copy(const void *_mesg, void *_dest, unsigned update_flag static size_t H5O_pline_size(const H5F_t *f, const void *_mesg); static herr_t H5O_pline_reset(void *_mesg); static herr_t H5O_pline_free(void *_mesg); +static herr_t H5O_pline_get_share (H5F_t *f, const void *_mesg, + H5O_shared_t *sh); +static herr_t H5O_pline_set_share (H5F_t *f, void *_mesg, + const H5O_shared_t *sh); +static htri_t H5O_pline_is_shared(const void *_mesg); static herr_t H5O_pline_pre_copy_file(H5F_t *file_src, const H5O_msg_class_t *type, void *mesg_src, hbool_t *deleted, const H5O_copy_t *cpy_info, void *_udata); static herr_t H5O_pline_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, @@ -53,8 +58,9 @@ const H5O_msg_class_t H5O_MSG_PLINE[1] = {{ H5O_pline_free, /* free method */ NULL, /* file delete method */ NULL, /* link method */ - NULL, /* get share method */ - NULL, /* set share method */ + H5O_pline_get_share, /* get share method */ + H5O_pline_set_share, /* set share method */ + H5O_pline_is_shared, /* is shared method */ H5O_pline_pre_copy_file, /* pre copy native value to file */ NULL, /* copy native value to file */ NULL, /* post copy native value to file */ @@ -591,6 +597,105 @@ done: /*------------------------------------------------------------------------- + * Function: H5O_pline_get_share + * + * Purpose: Gets sharing information from the message + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * Tuesday, October 10, 2006 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_pline_get_share(H5F_t UNUSED *f, const void *_mesg, + H5O_shared_t *sh /*out*/) +{ + H5O_pline_t *mesg = (H5O_pline_t *)_mesg; + herr_t ret_value = SUCCEED; + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_pline_get_share); + + HDassert (mesg); + HDassert (sh); + + if(NULL == H5O_copy(H5O_SHARED_ID, &(mesg->sh_loc), sh)) + ret_value = FAIL; + + FUNC_LEAVE_NOAPI(ret_value); +} + +/*------------------------------------------------------------------------- + * Function: H5O_pline_set_share + * + * Purpose: Sets sharing information for the message + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * Tuesday, October 10, 2006 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_pline_set_share(H5F_t UNUSED *f, void *_mesg/*in,out*/, + const H5O_shared_t *sh) +{ + H5O_pline_t *mesg = (H5O_pline_t *)_mesg; + herr_t ret_value = SUCCEED; + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_pline_set_share); + + HDassert (mesg); + HDassert (sh); + + if(NULL == H5O_copy(H5O_SHARED_ID, sh, &(mesg->sh_loc))) + ret_value = FAIL; + + FUNC_LEAVE_NOAPI(ret_value); +} + +/*------------------------------------------------------------------------- + * Function: H5O_pline_is_shared + * + * Purpose: Determines if this fill value is shared (committed or a SOHM) + * or not. + * + * Return: TRUE if fill value is shared + * FALSE if fill value is not shared + * Negative on failure + * + * Programmer: James Laird + * Monday, October 16, 2006 + * + *------------------------------------------------------------------------- + */ +static htri_t +H5O_pline_is_shared(const void *_mesg) +{ + H5O_pline_t *mesg = (H5O_pline_t *)_mesg; + htri_t ret_value; + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_pline_is_shared) + + HDassert(mesg); + + /* Fill values can't currently be committed, but this should let the + * library read a "committed fill value" if we ever create one in + * the future. + */ + if(mesg->sh_loc.flags & (H5O_COMMITTED_FLAG | H5O_SHARED_IN_HEAP_FLAG)) + ret_value = TRUE; + else + ret_value = FALSE; + + FUNC_LEAVE_NOAPI(ret_value) + +} /* end H5O_pline_is_shared */ + +/*------------------------------------------------------------------------- * Function: H5O_pline_debug * * Purpose: Prints debugging information for filter pipeline message MESG diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h index 434e805..5aa7c87 100644 --- a/src/H5Oprivate.h +++ b/src/H5Oprivate.h @@ -1,4 +1,4 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +/* * * * * * * * * * * * * * * * * * * * * * *fs * * * * * * * * * * * * * * * * * Copyright by the Board of Trustees of the University of Illinois. * * All rights reserved. * * * @@ -34,6 +34,7 @@ #include "H5Dpublic.h" /* Dataset functions */ #include "H5Lpublic.h" /* Link functions */ #include "H5Spublic.h" /* Dataspace functions */ +#include "H5Lpublic.h" /* Link functions */ /* Private headers needed by this file */ #include "H5Fprivate.h" /* File access */ @@ -45,21 +46,44 @@ typedef struct H5O_msg_class_t H5O_msg_class_t; typedef struct H5O_t H5O_t; +/* JAMES: should these be in H5SM_private? or renamed? */ +/* JAMES: causes errors encoding/decoding if this is wrong. Can't be constant. */ +#define H5SM_FHEAP_ID_LEN 6 + +/* JAMES: not great? */ +typedef uint64_t H5SM_fheap_id_t; + + +/* JAMES for debugging */ +#define PRINT_BUF(buf, size) \ + if(1) { size_t x; \ + for(x=0; xsh_loc), sh)) + ret_value = FAIL; + + FUNC_LEAVE_NOAPI(ret_value); +} + +/*------------------------------------------------------------------------- + * Function: H5O_sdspace_set_share + * + * Purpose: Sets sharing information for the message + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * Tuesday, October 10, 2006 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_sdspace_set_share(H5F_t UNUSED *f, void *_mesg/*in,out*/, + const H5O_shared_t *sh) +{ + H5S_extent_t *mesg = (H5S_extent_t *)_mesg; + herr_t ret_value = SUCCEED; + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_sdspace_set_share); + + HDassert (mesg); + HDassert (sh); + + if(NULL == H5O_copy(H5O_SHARED_ID, sh, &(mesg->sh_loc))) + ret_value = FAIL; + + FUNC_LEAVE_NOAPI(ret_value); +} + +/*------------------------------------------------------------------------- + * Function: H5O_sdspace_is_shared + * + * Purpose: Determines if this dataspace is shared (committed or a SOHM) + * or not. + * + * Return: TRUE if dataspace is shared + * FALSE if dataspace is not shared + * Negative on failure + * + * Programmer: James Laird + * Monday, October 16, 2006 + * + *------------------------------------------------------------------------- + */ +static htri_t +H5O_sdspace_is_shared (const void *_mesg) +{ + H5S_extent_t *mesg = (H5S_extent_t *)_mesg; + htri_t ret_value; + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_sdspace_is_shared) + + HDassert(mesg); + + /* Dataspaces can't currently be committed, but this should let the + * library read a "committed dataspace" if we ever create one in + * the future. + */ + if(mesg->sh_loc.flags & (H5O_COMMITTED_FLAG | H5O_SHARED_IN_HEAP_FLAG)) + ret_value = TRUE; + else + ret_value = FALSE; + + FUNC_LEAVE_NOAPI(ret_value) + +} /* end H5O_sdspace_is_shared */ + /*-------------------------------------------------------------------------- NAME H5O_sdspace_debug diff --git a/src/H5Oshared.c b/src/H5Oshared.c index 367e001..7c69ab9 100644 --- a/src/H5Oshared.c +++ b/src/H5Oshared.c @@ -35,6 +35,8 @@ #include "H5Gprivate.h" /* Groups */ #include "H5MMprivate.h" /* Memory management */ #include "H5Opkg.h" /* Object headers */ +#include "H5HFprivate.h" /* Fractal heap */ +#include "H5SMprivate.h" /*JAMES: for H5SM_get_fheap_addr. Change this? */ static void *H5O_shared_decode (H5F_t*, hid_t dxpl_id, const uint8_t*); static herr_t H5O_shared_encode (H5F_t*, uint8_t*, const void*); @@ -44,8 +46,8 @@ static herr_t H5O_shared_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hboo static herr_t H5O_shared_link(H5F_t *f, hid_t dxpl_id, const void *_mesg); static herr_t H5O_shared_pre_copy_file(H5F_t *file_src, const H5O_msg_class_t *type, void *mesg_src, hbool_t *deleted, const H5O_copy_t *cpy_info, void *_udata); -static void *H5O_shared_copy_file(H5F_t *file_src, void *native_src, - H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, void *udata); +static void *H5O_shared_copy_file(H5F_t *file_src, const H5O_msg_class_t *mesg_type, + void *native_src, H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, void *udata); static herr_t H5O_shared_debug (H5F_t*, hid_t dxpl_id, const void*, FILE*, int, int); /* This message derives from H5O message class */ @@ -63,17 +65,22 @@ const H5O_msg_class_t H5O_MSG_SHARED[1] = {{ H5O_shared_link, /*link method */ NULL, /*get share method */ NULL, /*set share method */ + NULL, /*is shared method */ H5O_shared_pre_copy_file, /* pre copy native value to file */ H5O_shared_copy_file, /* copy native value to file */ NULL, /* post copy native value to file */ H5O_shared_debug /*debug method */ }}; -/* Old version, with full symbol table entry as link for object header sharing */ +/* First version, with full symbol table entry as link for object header sharing */ #define H5O_SHARED_VERSION_1 1 -/* New version, with just address of object as link for object header sharing */ -#define H5O_SHARED_VERSION 2 +/* Older version, with just address of object as link for object header sharing */ +#define H5O_SHARED_VERSION_2 2 + +/* Newest version, which recognizes messages that are stored in the heap */ +#define H5O_SHARED_VERSION_3 3 +#define H5O_SHARED_VERSION H5O_SHARED_VERSION_3 /*------------------------------------------------------------------------- @@ -100,6 +107,10 @@ const H5O_msg_class_t H5O_MSG_SHARED[1] = {{ void * H5O_shared_read(H5F_t *f, hid_t dxpl_id, H5O_shared_t *shared, const H5O_msg_class_t *type, void *mesg) { + haddr_t fheap_addr; + 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 *ret_value = NULL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_shared_read) @@ -109,12 +120,65 @@ H5O_shared_read(H5F_t *f, hid_t dxpl_id, H5O_shared_t *shared, const H5O_msg_cla HDassert(shared); HDassert(type); - /* Get the shared message */ - ret_value = H5O_read_real(&(shared->oloc), type, 0, mesg, dxpl_id); + /* This message could have a heap ID (SOHM) or the address of an object + * header on disk (named datatype) + */ + HDassert(shared->flags != H5O_NOT_SHARED); + + if(shared->flags & H5O_SHARED_IN_HEAP_FLAG ) + { + size_t buf_size; + + if((fheap_addr = H5SM_get_fheap_addr(f, type->id, dxpl_id)) == HADDR_UNDEF) + HGOTO_ERROR(H5E_SOHM, H5E_CANTGET, NULL, "can't get fheap address for shared messages") + + if(NULL == (fheap =H5HF_open(f, dxpl_id, fheap_addr))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, NULL, "unable to open fractal heap") + + if(H5HF_get_obj_len(fheap, dxpl_id, &(shared->u.heap_id), &buf_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, NULL, "can't get message size from fractal heap.") + + /* Allocate buffer */ + if(NULL == (buf = HDmalloc(buf_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + if(H5HF_read(fheap, dxpl_id, &(shared->u.heap_id), buf) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "can't read message from fractal heap.") + + /* Decode the message */ + 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 */ + assert(type->set_share); + if(((type->set_share)(f, native_mesg, shared)) < 0) + HGOTO_ERROR (H5E_OHDR, H5E_CANTINIT, NULL, "unable to set sharing information") + + ret_value = H5O_copy(type->id, native_mesg, mesg); + } + else + { + HDassert(shared->flags & H5O_COMMITTED_FLAG); + /* Get the shared message from an object header*/ + if(NULL == (ret_value = H5O_read_real(&(shared->u.oloc), type, 0, mesg, dxpl_id))) + HGOTO_ERROR (H5E_OHDR, H5E_READERROR, NULL, "unable to read message") + } + + /* Mark the message as shared */ if(type->set_share && (type->set_share)(f, ret_value, shared) < 0) HGOTO_ERROR (H5E_OHDR, H5E_CANTINIT, NULL, "unable to set sharing information") done: + if(buf) + HDfree(buf); + + if(native_mesg) + H5O_free(type->id, native_mesg); + + if(fheap) + if(H5HF_close(fheap, dxpl_id) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, NULL, "can't close fractal heap") + FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_shared_read() */ @@ -147,6 +211,9 @@ H5O_shared_link_adj(H5F_t *f, hid_t dxpl_id, const H5O_shared_t *shared, int adj /* check args */ HDassert(f); HDassert(shared); + /* JAMES + * NEW THOUGHT: I should increment SOHM ref count here (or in a parallel function) + */ /* * The shared message is stored in some other object header. @@ -154,10 +221,18 @@ H5O_shared_link_adj(H5F_t *f, hid_t dxpl_id, const H5O_shared_t *shared, int adj * new object header. Adjust the reference count on that * object header. */ - if(shared->oloc.file->shared != f->shared) - HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "interfile hard links are not allowed") - if((ret_value = H5O_link(&(shared->oloc), adjust, dxpl_id)) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared object link count") + if(shared->flags & H5O_COMMITTED_FLAG) + { + if(shared->u.oloc.file->shared != f->shared) + HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "interfile hard links are not allowed") + if((ret_value = H5O_link(&(shared->u.oloc), adjust, dxpl_id)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared object link count") + } + else + { + HDassert(shared->flags & H5O_SHARED_IN_HEAP_FLAG); + ret_value = 1; /* JAMES temp refcount*/ + } done: FUNC_LEAVE_NOAPI(ret_value) @@ -185,7 +260,7 @@ static void * H5O_shared_decode(H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *buf) { H5O_shared_t *mesg = NULL; - unsigned flags, version; + unsigned version; void *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_shared_decode) @@ -200,11 +275,21 @@ H5O_shared_decode(H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *buf) /* Version */ version = *buf++; - if(version != H5O_SHARED_VERSION_1 && version != H5O_SHARED_VERSION) - HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for shared object message") - - /* Get the shared information flags */ - flags = *buf++; /* Unused currently */ + if(version < H5O_SHARED_VERSION_1 || version > H5O_SHARED_VERSION) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for shared object message") + + /* Get the shared information flags + * Flags are unused before version 3. + */ /* JAMES: double-check that this is endian-portable */ + if(version >= H5O_SHARED_VERSION_2) + { + mesg->flags = *buf++; + } + else + { + mesg->flags = H5O_COMMITTED_FLAG; + buf++; + } /* Skip reserved bytes (for version 1) */ if(version == H5O_SHARED_VERSION_1) @@ -212,12 +297,33 @@ H5O_shared_decode(H5F_t *f, hid_t UNUSED dxpl_id, const uint8_t *buf) /* Body */ if(version == H5O_SHARED_VERSION_1) - H5G_obj_ent_decode(f, &buf, &(mesg->oloc)); - else { - HDassert(version == H5O_SHARED_VERSION); - H5F_addr_decode(f, &buf, &(mesg->oloc.addr)); - mesg->oloc.file = f; - } /* end else */ + { + H5G_obj_ent_decode(f, &buf, &(mesg->u.oloc)); + } + else if (version >= H5O_SHARED_VERSION_2) + { + /* If this message is in the heap, copy a heap ID. + * Otherwise, it is a named datatype, so copy an H5O_loc_t. + */ + if(mesg->flags & H5O_SHARED_IN_HEAP_FLAG) + { + HDassert(version >= H5O_SHARED_VERSION_3 ); + HDmemcpy(&(mesg->u.heap_id), buf, (size_t) H5SM_FHEAP_ID_LEN); + } + else + { + /* The H5O_COMMITTED_FLAG should be set if this message + * is from an older version before the flag existed. + */ + if(version < H5O_SHARED_VERSION_3) + mesg->flags = H5O_COMMITTED_FLAG; + + HDassert(mesg->flags & H5O_COMMITTED_FLAG); + + H5F_addr_decode(f, &buf, &(mesg->u.oloc.addr)); + mesg->u.oloc.file = f; + } + } /* Set return value */ ret_value = mesg; @@ -252,6 +358,7 @@ static herr_t H5O_shared_encode (H5F_t *f, uint8_t *buf/*out*/, const void *_mesg) { const H5O_shared_t *mesg = (const H5O_shared_t *)_mesg; + unsigned version; FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_shared_encode) @@ -260,10 +367,36 @@ H5O_shared_encode (H5F_t *f, uint8_t *buf/*out*/, const void *_mesg) HDassert(buf); HDassert(mesg); + /* JAMES: shouldn't be necessary. */ + HDmemset(buf, 0, sizeof( H5O_shared_size(f, mesg))); + /* Encode */ - *buf++ = H5O_SHARED_VERSION; - *buf++ = 0; /* No flags currently */ - H5F_addr_encode(f, &buf, mesg->oloc.addr); + /* If this message is shared in the heap, we need to use version 3 of the + * encoding and encode the SHARED_IN_HEAP flag. + */ + /* JAMES: also use "use latest version" flag here */ + if(mesg->flags & H5O_SHARED_IN_HEAP_FLAG) { + version = H5O_SHARED_VERSION; + } + else { + HDassert(mesg->flags & H5O_COMMITTED_FLAG); + version = H5O_SHARED_VERSION_2; /* version 1 is no longer used */ + } + + *buf++ = version; + *buf++ = (unsigned) mesg->flags; + + /* Encode either the heap ID of the message or the address of the + * object header that holds it. + */ + if(mesg->flags & H5O_SHARED_IN_HEAP_FLAG) + { + HDmemcpy(buf, &(mesg->u.heap_id), (size_t) H5SM_FHEAP_ID_LEN); + } + else + { + H5F_addr_encode(f, &buf, mesg->u.oloc.addr); + } FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5O_shared_encode() */ @@ -302,7 +435,19 @@ H5O_shared_copy(const void *_mesg, void *_dest, unsigned UNUSED update_flags) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); /* copy */ - *dest = *mesg; + dest->flags = mesg->flags; + if(mesg->flags & H5O_COMMITTED_FLAG) + { + H5O_loc_copy(&(dest->u.oloc), &(mesg->u.oloc), H5_COPY_DEEP); + } + else if(mesg->flags & H5O_SHARED_IN_HEAP_FLAG) + { + dest->u.heap_id= mesg->u.heap_id; + } else + { + /* This message's sharing information is being reset */ + HDassert(mesg->flags == H5O_NOT_SHARED); + } /* Set return value */ ret_value=dest; @@ -327,15 +472,26 @@ done: *------------------------------------------------------------------------- */ static size_t -H5O_shared_size (const H5F_t *f, const void UNUSED *_mesg) +H5O_shared_size (const H5F_t *f, const void *_mesg) { + const H5O_shared_t *shared = (const H5O_shared_t *) _mesg; size_t ret_value; FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_shared_size); - ret_value = 1 + /*version */ - 1 + /*the flags field */ - H5F_SIZEOF_ADDR(f); /*sharing by another obj hdr */ + if(shared->flags & H5O_COMMITTED_FLAG) + { + ret_value = 1 + /*version */ + 1 + /*the flags field */ + H5F_SIZEOF_ADDR(f); /*sharing by another obj hdr */ + } + else + { + HDassert(shared->flags & H5O_SHARED_IN_HEAP_FLAG); + ret_value = 1 + /*version */ + 1 + /*the flags field */ + H5SM_FHEAP_ID_LEN; /* Shared in the heap */ + } FUNC_LEAVE_NOAPI(ret_value); } @@ -367,11 +523,24 @@ H5O_shared_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link) assert(f); assert(shared); + /* + * Committed datatypes increment the OH of the original message when they + * are written (in H5O_shared_link) and decrement it here. + * SOHMs in the heap behave differently; their refcount is incremented + * during H5SM_share when they are going to be written (in H5O_append + * or H5O_modify). Their refcount in the SOHM indexes still needs to + * be decremented when they're deleted (in H5O_shared_link_adj). + */ + /* Decrement the reference count on the shared object, if requested */ if(adj_link) if(H5O_shared_link_adj(f, dxpl_id, shared, -1)<0) HGOTO_ERROR (H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared object link count") + /* JAMES */ +/* JAMES if((shared->flags & H5O_SHARED_IN_HEAP_FLAG) > 0) + H5O_loc_free(&(shared->oloc)); +*/ done: FUNC_LEAVE_NOAPI(ret_value); } /* end H5O_shared_delete() */ @@ -392,6 +561,7 @@ done: * *------------------------------------------------------------------------- */ +/* JAMES: this is where shared messages increment their links */ static herr_t H5O_shared_link(H5F_t *f, hid_t dxpl_id, const void *_mesg) { @@ -404,7 +574,11 @@ H5O_shared_link(H5F_t *f, hid_t dxpl_id, const void *_mesg) assert(f); assert(shared); - /* Decrement the reference count on the shared object */ + /* JAMES_HEAP: see comment in link_adj. Unneccessary except for shared attributes, I think, + * and they may yet take care of themselves. + */ + + /* Increment the reference count on the shared object */ if(H5O_shared_link_adj(f,dxpl_id,shared,1)<0) HGOTO_ERROR (H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared object link count"); @@ -428,11 +602,15 @@ done: *------------------------------------------------------------------------- */ static void * -H5O_shared_copy_file(H5F_t UNUSED *file_src, void *native_src, H5F_t *file_dst, - hid_t dxpl_id, H5O_copy_t *cpy_info, void UNUSED *udata) +H5O_shared_copy_file(H5F_t *file_src, const H5O_msg_class_t *mesg_type, + void *native_src, H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, + void *udata) { H5O_shared_t *shared_src = (H5O_shared_t *)native_src; - H5O_shared_t *shared_dst = NULL; + H5O_shared_t *shared_dst = NULL; /* The destination message if + * it is a shared message */ + void *dst_mesg = NULL; /* The destination message if + * it's an unshared message */ void *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_shared_copy_file) @@ -442,25 +620,57 @@ H5O_shared_copy_file(H5F_t UNUSED *file_src, void *native_src, H5F_t *file_dst, HDassert(file_dst); HDassert(cpy_info); - /* Allocate space for the destination message */ - if(NULL == (shared_dst = H5MM_malloc(sizeof(H5O_shared_t)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - - /* Reset group entry for new object */ - H5O_loc_reset(&(shared_dst->oloc)); - shared_dst->oloc.file = file_dst; - /* Copy the shared object from source to destination */ - if(H5O_copy_header_map(&(shared_src->oloc), &(shared_dst->oloc), dxpl_id, cpy_info, FALSE) < 0) - HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy object") - - /* Set return value */ - ret_value = shared_dst; + /* Committed shared messages create a shared message at the destination + * and also copy the committed object that they point to. + * SOHMs actually write a non-shared message at the destination. + */ + if(shared_src->flags & H5O_COMMITTED_FLAG) + { + /* Allocate space for the destination message */ + if(NULL == (shared_dst = H5MM_malloc(sizeof(H5O_shared_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* Reset group entry for new object */ + H5O_loc_reset(&(shared_dst->u.oloc)); + shared_dst->u.oloc.file = file_dst; + + /* Set flags for new shared object */ + shared_dst->flags = shared_src->flags; + + /* Copy the shared object from source to destination */ + if(H5O_copy_header_map(&(shared_src->u.oloc), &(shared_dst->u.oloc), dxpl_id, cpy_info, FALSE) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy object") + + /* Set return value */ + ret_value = shared_dst; + } + else + { + HDassert(shared_src->flags & H5O_SHARED_IN_HEAP_FLAG); + + /* Read the shared message to get the original message */ + if(NULL == (dst_mesg = H5O_shared_read(file_src, dxpl_id, shared_src, mesg_type, NULL))) + HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, NULL, "unable to read shared message") + + if(mesg_type->copy_file) { + /* Copy the original, un-shared message and return it */ + ret_value = H5O_copy_mesg_file(mesg_type, mesg_type, file_src, dst_mesg, file_dst, dxpl_id, cpy_info, udata); + H5MM_xfree(dst_mesg); + } + else { + ret_value = dst_mesg; + } + } done: if(!ret_value) + { if(shared_dst) H5MM_xfree(shared_dst); + if(dst_mesg) + H5MM_xfree(dst_mesg); + } FUNC_LEAVE_NOAPI(ret_value) } /* H5O_shared_copy_file() */ @@ -498,7 +708,7 @@ H5O_shared_pre_copy_file(H5F_t *file_src, const H5O_msg_class_t *type, if(type->pre_copy_file) { /* Go get the actual shared message */ - if((mesg_native = H5O_read_real(&(shared_src->oloc), type, 0, NULL, H5AC_dxpl_id)) == NULL) + if(NULL == (mesg_native = H5O_shared_read(file_src, H5AC_dxpl_id, shared_src, type, NULL))) HGOTO_ERROR(H5E_OHDR, H5E_READERROR, FAIL, "unable to load object header") /* Perform "pre copy" operation on messge */ @@ -536,6 +746,8 @@ H5O_shared_debug (H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const void *_mesg, FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_shared_debug) + /* JAMES_HEAP: this oughta change, too, of course. */ + /* Check args */ HDassert(f); HDassert(mesg); @@ -543,12 +755,24 @@ H5O_shared_debug (H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const void *_mesg, HDassert(indent >= 0); HDassert(fwidth >= 0); - HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, - "Sharing method", - "Obj Hdr"); - HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth, - "Object address:", - mesg->oloc.addr); + if(mesg->flags & H5O_COMMITTED_FLAG) + { + HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, + "Sharing method", + "Obj Hdr"); + HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth, + "Object address:", + mesg->u.oloc.addr); + } + else + { + HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, + "Sharing method", + "SOHM Heap"); + HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth, + "Heap ID:", + mesg->u.heap_id); + } FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5O_shared_debug() */ diff --git a/src/H5Ostab.c b/src/H5Ostab.c index 85f7493..3582620 100644 --- a/src/H5Ostab.c +++ b/src/H5Ostab.c @@ -43,8 +43,8 @@ static void *H5O_stab_copy(const void *_mesg, void *_dest, unsigned update_flags static size_t H5O_stab_size(const H5F_t *f, const void *_mesg); static herr_t H5O_stab_free(void *_mesg); static herr_t H5O_stab_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link); -static void *H5O_stab_copy_file(H5F_t *file_src, void *native_src, - H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, void *udata); +static void *H5O_stab_copy_file(H5F_t *file_src, const H5O_msg_class_t *mesg_type, + void *native_src, H5F_t *file_dst, hid_t dxpl_id, H5O_copy_t *cpy_info, void *udata); static herr_t H5O_stab_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, H5O_loc_t *dst_oloc, void *mesg_dst, hid_t dxpl_id, H5O_copy_t *cpy_info); static herr_t H5O_stab_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, @@ -65,6 +65,7 @@ const H5O_msg_class_t H5O_MSG_STAB[1] = {{ NULL, /* link method */ NULL, /*get share method */ NULL, /*set share method */ + NULL, /*is shared method */ NULL, /* pre copy native value to file */ H5O_stab_copy_file, /* copy native value to file */ H5O_stab_post_copy_file, /* post copy native value to file */ @@ -309,8 +310,9 @@ done: *------------------------------------------------------------------------- */ static void * -H5O_stab_copy_file(H5F_t *file_src, void *native_src, H5F_t *file_dst, - hid_t dxpl_id, H5O_copy_t UNUSED *cpy_info, void UNUSED *udata) +H5O_stab_copy_file(H5F_t *file_src, const H5O_msg_class_t *mesg_type, + void *native_src, H5F_t *file_dst, hid_t dxpl_id, + H5O_copy_t UNUSED *cpy_info, void UNUSED *udata) { H5O_stab_t *stab_src = (H5O_stab_t *) native_src; H5O_stab_t *stab_dst = NULL; diff --git a/src/H5Pfcpl.c b/src/H5Pfcpl.c index 994b6be..7c7012b 100644 --- a/src/H5Pfcpl.c +++ b/src/H5Pfcpl.c @@ -33,10 +33,11 @@ /* Headers */ /***********/ #include "H5private.h" /* Generic Functions */ -#include "H5Bprivate.h" /* B-tree subclass names */ -#include "H5Eprivate.h" /* Error handling */ -#include "H5Fprivate.h" /* Files */ -#include "H5Ppkg.h" /* Property lists */ +#include "H5Bprivate.h" /* B-tree subclass names */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Fprivate.h" /* Files */ +#include "H5SMprivate.h" /* Shared object header messages */ +#include "H5Ppkg.h" /* Property lists */ /****************/ @@ -71,6 +72,17 @@ /* Definitions for shared-header format version */ #define H5F_CRT_SHARE_HEAD_VERS_SIZE sizeof(unsigned) #define H5F_CRT_SHARE_HEAD_VERS_DEF HDF5_SHAREDHEADER_VERSION +/* Definitions for shared object header messages */ +#define H5F_CRT_SOHM_NINDEXES_SIZE sizeof(unsigned) +#define H5F_CRT_SOHM_NINDEXES_DEF (0) +#define H5F_CRT_INDEX_TYPES_SIZE sizeof(unsigned[H5SM_MAX_NUM_INDEXES]) +#define H5F_CRT_INDEX_TYPES_DEF { 0,0,0,0,0,0} +/*#define H5SM_INDEX_TYPES_DEF { H5SM_FILL_FLAG |H5SM_SDSPACE_FLAG,H5SM_ATTR_FLAG, 0, H5SM_DTYPE_FLAG,0,H5SM_PLINE_FLAG} JAMES */ +/* Definitions for shared object header list/btree cutoffs */ +#define H5F_CRT_SOHM_L2B_SIZE sizeof(size_t) +#define H5F_CRT_SOHM_L2B_DEF (50) /* JAMES */ +#define H5F_CRT_SOHM_B2L_SIZE sizeof(size_t) +#define H5F_CRT_SOHM_B2L_DEF (40) /* JAMES */ /******************/ @@ -144,6 +156,10 @@ 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_SOHM_NINDEXES_DEF; + unsigned sohm_index_flags[H5SM_MAX_NUM_INDEXES] = H5F_CRT_INDEX_TYPES_DEF; + size_t sohm_list_to_btree = H5F_CRT_SOHM_L2B_DEF; + size_t sohm_btree_to_list = H5F_CRT_SOHM_B2L_DEF; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5P_fcrt_reg_prop) @@ -184,6 +200,18 @@ H5P_fcrt_reg_prop(H5P_genclass_t *pclass) if(H5P_register(pclass, H5F_CRT_SHARE_HEAD_VERS_NAME, H5F_CRT_SHARE_HEAD_VERS_SIZE, &sharedheader_ver, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + /* Register the shared OH message information */ + if(H5P_register(pclass,H5F_CRT_SOHM_NINDEXES_NAME, H5F_CRT_SOHM_NINDEXES_SIZE, &num_sohm_indexes,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + if(H5P_register(pclass,H5F_CRT_INDEX_TYPES_NAME, H5F_CRT_INDEX_TYPES_SIZE, &sohm_index_flags,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + + /* Register the shared OH cutoff size information */ + if(H5P_register(pclass,H5F_CRT_SOHM_L2B_NAME, H5F_CRT_SOHM_L2B_SIZE, &sohm_list_to_btree,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + if(H5P_register(pclass,H5F_CRT_SOHM_B2L_NAME, H5F_CRT_SOHM_B2L_SIZE, &sohm_btree_to_list,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5P_fcrt_reg_prop() */ @@ -649,3 +677,320 @@ done: FUNC_LEAVE_API(ret_value); } + +/*------------------------------------------------------------------------- + * Function: H5Pset_shared_mesgs + * + * Purpose: Configure implicity shared object header message settings + * for this file. + * + * NINDEXES is the number of indexes for this file; it should + * be between 0 and H5SM_MAX_NUM_INDEXES. If nindexes is 0, + * SOHMs will be disabled for this file. + * + * MESG_TYPE_FLAGS is an array of message type flags (using + * the values defined in H5SMpublic.h) with NINDEXES entries. + * These flags determine which types of message are stored in + * which index. Any types of message that are not assigned + * to an index will not be shared in this file. Each message + * type should be assigned to only one index, though each + * index can store more than one type of message. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * Wednesday, April 5, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pset_shared_mesgs(hid_t plist_id, unsigned nindexes, const unsigned mesg_type_flags[]) +{ + unsigned i; + unsigned type_flags[H5SM_MAX_NUM_INDEXES]; /* Full-sized array */ + H5P_genplist_t *plist; /* Property list pointer */ + unsigned flags_used; /* type flags already specified. + * Used to make sure a flag isn't used twice. + */ + herr_t ret_value=SUCCEED; /* return value */ + + FUNC_ENTER_API(H5Pset_shared_mesgs, FAIL); + H5TRACE3("e","iIu*Iu",plist_id,nindexes,mesg_type_flags); + + /* Check arguments */ + if (nindexes > H5SM_MAX_NUM_INDEXES) + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "number of indexes is too large"); + if (nindexes > 0 && !mesg_type_flags) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no type flags specified"); + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(plist_id,H5P_FILE_CREATE))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + + flags_used = H5SM_NONE_FLAG; + + for (i=0; iselect.sel_info.hslab=NULL; + + /* Reset "shared" info on extent */ + ret_value->extent.sh_loc.flags = 0; } /* end if */ done: @@ -639,6 +642,10 @@ H5S_extent_copy(H5S_extent_t *dst, const H5S_extent_t *src) break; } + /* Copy the shared object info */ + if(NULL == H5O_copy(H5O_SHARED_ID, &(src->sh_loc), &(dst->sh_loc))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy shared information"); + done: FUNC_LEAVE_NOAPI(ret_value); } @@ -1530,6 +1537,13 @@ H5S_extend (H5S_t *space, const hsize_t *size) if(H5S_GET_SELECT_TYPE(space)==H5S_SEL_ALL) if(H5S_select_all(space, FALSE)<0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection"); + + /* Mark the dataspace as no longer shared if it was before */ + /* JAMES: passes in NULL for the file because the file has nothing to do with it. + * can I eliminate the file completely from sharing? + */ + if(H5O_reset_share(NULL, H5O_SDSPACE_ID, space) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRESET, FAIL, "can't stop sharing dataspace") } done: diff --git a/src/H5SM.c b/src/H5SM.c new file mode 100755 index 0000000..c17dd16 --- /dev/null +++ b/src/H5SM.c @@ -0,0 +1,997 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5SM_PACKAGE /*suppress error about including H5SMpkg */ +#define H5F_PACKAGE /*suppress error about including H5Fpkg */ + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5ACprivate.h" /* Metadata cache */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5FLprivate.h" /* Free Lists */ +#include "H5MFprivate.h" /* File memory management */ +#include "H5MMprivate.h" /* Memory management */ + +#include "H5Fpkg.h" /* File access */ +#include "H5SMpkg.h" /* Shared object header messages */ + +/****************/ +/* Local Macros */ +/****************/ +/* Values used to create the SOHM heaps */ +#define H5SM_FHEAP_MAN_WIDTH 4 +#define H5SM_FHEAP_MAN_START_BLOCK_SIZE 1024 +#define H5SM_FHEAP_MAN_MAX_DIRECT_SIZE (64 * 1024) +#define H5SM_FHEAP_MAN_MAX_INDEX 20 +#define H5SM_FHEAP_MAN_START_ROOT_ROWS 1 +#define H5SM_FHEAP_CHECKSUM_DBLOCKS TRUE +#define H5SM_FHEAP_MAX_MAN_SIZE (4 * 1024) + +/******************/ +/* Local Typedefs */ +/******************/ + +/********************/ +/* Local Prototypes */ +/********************/ +static herr_t H5SM_create_index(H5F_t *f, H5SM_index_header_t *header, hid_t dxpl_id); +/* JAMES +static herr_t H5SM_write_index(H5F_t *f, haddr_t index_addr, hsize_t sohm_hash, haddr_t sohm_addr, hid_t dxpl_id); +*/ +static haddr_t H5SM_create_list(H5F_t *f, H5SM_index_header_t *header, hid_t dxpl_id); +static herr_t H5SM_write_mesg(H5F_t *f, hid_t dxpl_id, H5SM_index_header_t *header, + unsigned type_id, void *mesg, unsigned *cache_flags_ptr); +static herr_t H5SM_delete_from_index(H5F_t *f, hid_t dxpl_id, + H5SM_index_header_t *header, unsigned type_id, const H5O_shared_t * mesg, + unsigned *cache_flags); +static hsize_t H5SM_find_in_list(H5F_t *f, H5SM_list_t *list, const H5SM_mesg_key_t *key); +static ssize_t H5SM_get_index(const H5SM_master_table_t *table, unsigned type_id); + + +/*********************/ +/* Package Variables */ +/*********************/ + +H5FL_DEFINE(H5SM_master_table_t); +H5FL_ARR_DEFINE(H5SM_index_header_t, H5SM_MAX_INDEXES); +H5FL_DEFINE(H5SM_list_t); +H5FL_ARR_DEFINE(H5SM_sohm_t, H5SM_MAX_LIST_ELEMS); + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + +/*******************/ +/* Local Variables */ +/*******************/ + + +/*------------------------------------------------------------------------- + * Function: H5SM_init + * + * Purpose: Initializes the Shared Message interface. + * + * Creates a master SOHM table in the file and in the cache. + * This function should not be called for files that have + * SOHMs disabled in the FCPL. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * Tuesday, May 2, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5SM_init(H5F_t *f, H5P_genplist_t * fc_plist, hid_t dxpl_id) +{ + H5SM_master_table_t *table = NULL; + haddr_t table_addr = HADDR_UNDEF; + unsigned num_indexes; + size_t list_to_btree, btree_to_list; + unsigned index_type_flags[H5SM_MAX_NUM_INDEXES]; + ssize_t x; + hsize_t table_size; + herr_t ret_value=SUCCEED; + + FUNC_ENTER_NOAPI(H5SM_init, NULL) + + HDassert(f); + /* File should not already have a SOHM table */ + HDassert(f->shared->sohm_addr == HADDR_UNDEF); + + /* Initialize master table */ + if(NULL == (table = H5FL_MALLOC(H5SM_master_table_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for SOHM table") + + /* Get information from fcpl */ + if(H5P_get(fc_plist, H5F_CRT_SOHM_NINDEXES_NAME, &num_indexes)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get SOHM information") + if(H5P_get(fc_plist, H5F_CRT_INDEX_TYPES_NAME, &index_type_flags)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get SOHM information") + if(H5P_get(fc_plist, H5F_CRT_SOHM_L2B_NAME, &list_to_btree)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get SOHM information") + if(H5P_get(fc_plist, H5F_CRT_SOHM_B2L_NAME, &btree_to_list)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get SOHM information") + + /* Right now we just use one byte to hold the number of indexes */ + HDassert(num_indexes < 256); + table->num_indexes = num_indexes; + + /* Check that list and btree cutoffs make sense. There can't be any + * values greater than the list max but less than the btree min; the + * list max has to be greater than or equal to one less than the btree + * min. + */ + if(list_to_btree + 1 < btree_to_list) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "SOHM list max is less than btree min") + + HDassert(table->num_indexes > 0 && table->num_indexes <= H5SM_MAX_NUM_INDEXES); + + /* Allocate the SOHM indexes as an array. */ + if(NULL == (table->indexes = H5FL_ARR_MALLOC(H5SM_index_header_t, table->num_indexes))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for SOHM indexes") + + /* 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; xnum_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].index_addr = HADDR_UNDEF; + table->indexes[x].heap_addr = HADDR_UNDEF; + table->indexes[x].num_messages = 0; + /* Indexes start as lists unless the list-to-btree threshold is zero */ + if(table->indexes[x].list_to_btree > 0) { + table->indexes[x].index_type = H5SM_LIST; + } else { + table->indexes[x].index_type = H5SM_BTREE; + } + } /* end for */ + + /* Allocate space for the table on disk */ + table_size = (hsize_t) H5SM_TABLE_SIZE(f) + (hsize_t) (table->num_indexes * H5SM_INDEX_HEADER_SIZE(f)); + if(HADDR_UNDEF == (table_addr = H5MF_alloc(f, H5FD_MEM_SOHM, dxpl_id, table_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for SOHM table") + + /* Cache the new table */ + if(H5AC_set(f, dxpl_id, H5AC_SOHM_TABLE, table_addr, table, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTLOAD, FAIL, "can't add SOHM table to cache") + + /* Record the address of the master table in the file */ + f->shared->sohm_addr = table_addr; + +done: + if(ret_value < 0) + { + if(table_addr != HADDR_UNDEF) + H5MF_xfree(f, H5FD_MEM_SOHM, dxpl_id, table_addr, (hsize_t)H5SM_TABLE_SIZE(f)); + if(table != NULL) + H5FL_FREE(H5SM_master_table_t, table); + } + + FUNC_LEAVE_NOAPI(ret_value) +} + + +/*------------------------------------------------------------------------- + * Function: H5SM_get_index + * + * Purpose: Get the index number for a given message type. + * + * Returns the number of the index in the supplied table + * that holds messages of type type_id, or negative if + * there is no index for this message type. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * Tuesday, October 10, 2006 + * + *------------------------------------------------------------------------- + */ +static ssize_t +H5SM_get_index(const H5SM_master_table_t *table, unsigned type_id) +{ + ssize_t x; + unsigned type_flag; + hbool_t found = FALSE; + ssize_t ret_value = FAIL; + + FUNC_ENTER_NOAPI(H5SM_get_index, FAIL) + + /* Translate the H5O type_id into an H5SM type flag */ + switch(type_id) + { + case H5O_SDSPACE_ID: + type_flag = H5SM_SDSPACE_FLAG; + break; + case H5O_DTYPE_ID: + type_flag = H5SM_DTYPE_FLAG; + break; + case H5O_FILL_NEW_ID: + type_flag = H5SM_FILL_FLAG; + break; + case H5O_PLINE_ID: + type_flag = H5SM_PLINE_FLAG; + break; + case H5O_ATTR_ID: + type_flag = H5SM_ATTR_FLAG; + break; + default: + HGOTO_ERROR(H5E_OHDR, H5E_BADTYPE, FAIL, "unknown message type ID") + } + + /* Search the indexes until we find one that matches this flag or we've + * searched them all. + */ + for(x=0; xnum_indexes && !found; ++x) + { + if(table->indexes[x].mesg_types & type_flag) + { + found = TRUE; + ret_value = x; + } + } + + /* At this point, ret_value is either the location of the correct + * index or it's still FAIL because we didn't find an index. + */ +done: + FUNC_LEAVE_NOAPI(ret_value) +} + +/*------------------------------------------------------------------------- + * Function: H5SM_get_fheap_addr + * + * Purpose: Gets the address of the fractal heap used to store + * messages of type type_id. + * + * Return: Non-negative on success/negative on failure + * + * Programmer: James Laird + * Tuesday, October 3, 2006 + * + *------------------------------------------------------------------------- + */ +haddr_t +H5SM_get_fheap_addr(H5F_t *f, unsigned type_id, hid_t dxpl_id) +{ + H5SM_master_table_t *table = NULL; + ssize_t index_num; /* Which index */ + haddr_t ret_value; + FUNC_ENTER_NOAPI(H5SM_get_fheap_addr, FAIL) + + /* Look up the master SOHM table */ + if (NULL == (table = H5AC_protect(f, dxpl_id, H5AC_SOHM_TABLE, f->shared->sohm_addr, NULL, NULL, H5AC_WRITE))) + HGOTO_ERROR(H5E_CACHE, H5E_CANTPROTECT, HADDR_UNDEF, "unable to load SOHM master table") + + /* JAMES! */ + if((index_num = H5SM_get_index(table, type_id)) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, HADDR_UNDEF, "unable to find correct SOHM index") + + ret_value = table->indexes[index_num].heap_addr; + +done: + /* Release the master SOHM table */ + if (table && H5AC_unprotect(f, dxpl_id, H5AC_SOHM_TABLE, f->shared->sohm_addr, table, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, HADDR_UNDEF, "unable to close SOHM master table") + + FUNC_LEAVE_NOAPI(ret_value) +} + + +/*------------------------------------------------------------------------- + * Function: H5SM_create_index + * + * Purpose: Allocates storage for an index. + * + * Return: Non-negative on success/negative on failure + * + * Programmer: James Laird + * Tuesday, May 2, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5SM_create_index(H5F_t *f, H5SM_index_header_t *header, hid_t dxpl_id) +{ + haddr_t list_addr=HADDR_UNDEF; /* Address of SOHM list */ + haddr_t tree_addr=HADDR_UNDEF; /* Address of SOHM B-tree */ + H5HF_create_t fheap_cparam; /* Fractal heap creation parameters */ + H5HF_t *fheap = NULL; + size_t fheap_id_len; /* Size of a fractal heap ID */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(H5SM_create_index, FAIL) + + HDassert(header); + HDassert(header->index_addr == HADDR_UNDEF); + HDassert(header->btree_to_list <= header->list_to_btree); + + /* In most cases, the index starts as a list */ + if(header->list_to_btree > 0) + { + header->index_type = H5SM_LIST; + + if((list_addr = H5SM_create_list(f, header, dxpl_id)) == HADDR_UNDEF) /* JAMES: only allocate part of the list? */ + HGOTO_ERROR(H5E_SOHM, H5E_CANTCREATE, FAIL, "list creation failed for SOHM index") + + header->index_addr = list_addr; + } + else /* index is a B-tree */ + { + header->index_type = H5SM_BTREE; + + if(H5B2_create(f, dxpl_id, H5SM_INDEX, H5SM_B2_NODE_SIZE, + H5SM_SOHM_ENTRY_SIZE(f), H5SM_B2_SPLIT_PERCENT, + H5SM_B2_MERGE_PERCENT, &tree_addr) <0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTCREATE, FAIL, "B-tree creation failed for SOHM index") + + header->index_addr = tree_addr; + } + + /* Create a heap to hold the shared messages that the list or B-tree will index */ + /* JAMES: this should happen first, so that the list/btree size can scale depending + * on how big a heap pointer is. + */ + HDmemset(&fheap_cparam, 0, sizeof(fheap_cparam)); + fheap_cparam.managed.width = H5SM_FHEAP_MAN_WIDTH; + fheap_cparam.managed.start_block_size = H5SM_FHEAP_MAN_START_BLOCK_SIZE; + fheap_cparam.managed.max_direct_size = H5SM_FHEAP_MAN_MAX_DIRECT_SIZE; + fheap_cparam.managed.max_index = H5SM_FHEAP_MAN_MAX_INDEX; + fheap_cparam.managed.start_root_rows = H5SM_FHEAP_MAN_START_ROOT_ROWS; + fheap_cparam.checksum_dblocks = H5SM_FHEAP_CHECKSUM_DBLOCKS; + fheap_cparam.id_len = 0; + fheap_cparam.max_man_size = H5SM_FHEAP_MAX_MAN_SIZE; + if(NULL == (fheap = H5HF_create(f, dxpl_id, &fheap_cparam))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to create fractal heap") + + if(H5HF_get_heap_addr(fheap, &(header->heap_addr )) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGETSIZE, FAIL, "can't get fractal heap address") + + if(H5HF_get_id_len(fheap, &fheap_id_len) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGETSIZE, FAIL, "can't get fractal heap ID length") + +done: + /* Close the fractal heap if one has been created */ + if(fheap) + if(H5HF_close(fheap, dxpl_id) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CLOSEERROR, FAIL, "can't close fractal heap") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5SM_create_index */ + + +/*------------------------------------------------------------------------- + * Function: H5SM_create_list + * + * Purpose: Creates a list of SOHM messages. + * + * Called when a new index is created from scratch or when a + * B-tree needs to be converted back into a list. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * Monday, August 28, 2006 + * + *------------------------------------------------------------------------- + */ +static haddr_t +H5SM_create_list(H5F_t *f, H5SM_index_header_t * header, hid_t dxpl_id) +{ + H5SM_list_t *list = NULL; /* List of messages */ + hsize_t x; /* Counter variable */ + hsize_t size; /* Size of list on disk */ + size_t num_entries; /* Number of messages to create in list */ + haddr_t addr = HADDR_UNDEF; /* Address of the list on disk */ + haddr_t ret_value; + + FUNC_ENTER_NOAPI(H5SM_create_list, HADDR_UNDEF) + + HDassert(f); + HDassert(header); + + num_entries = header->list_to_btree; + + /* Allocate list in memory */ + if((list = H5FL_MALLOC(H5SM_list_t)) == NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, "file allocation failed for SOHM list") + 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 */ + /* JAMES: would making fewer operations out of this make it faster? */ + for(x=0; xmessages[x].fheap_id=0; + list->messages[x].hash=H5O_HASH_UNDEF; + } + + list->header = header; + + /* Allocate space for the list on disk */ + size = H5SM_LIST_SIZE(f, num_entries); + if(HADDR_UNDEF == (addr = H5MF_alloc(f, H5FD_MEM_SOHM, dxpl_id, size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, "file allocation failed for SOHM list") + + /* Put the list into the cache */ + if(H5AC_set(f, dxpl_id, H5AC_SOHM_LIST, addr, list, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTINS, HADDR_UNDEF, "can't add SOHM list to cache") + + ret_value = addr; +done: + if(ret_value == HADDR_UNDEF) + { + if(list != NULL) + { + if(list->messages != NULL) + H5FL_ARR_FREE(H5SM_sohm_t, list->messages); + H5FL_FREE(H5SM_list_t, list); + + } + if(addr != HADDR_UNDEF) + { + H5MF_xfree(f, H5FD_MEM_SOHM, dxpl_id, addr, size); + } + } + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5SM_create_list */ + + + +/*------------------------------------------------------------------------- + * Function: H5SM_try_share + * + * Purpose: Attempts to share an object header message. If the message + * should be shared (if sharing has been enabled and this + * message qualified), turns the message into a shared message. + * + * If not, returns FALSE and does nothing. + * + * If this message was already shared, increments its reference + * count and leaves it otherwise unchanged. + * + * Return: TRUE if message is now a SOHM + * FALSE if this message is not a SOHM + * Negative on failure + * + * Programmer: James Laird + * Tuesday, May 2, 2006 + * + *------------------------------------------------------------------------- + */ +htri_t +H5SM_try_share(H5F_t *f, hid_t dxpl_id, unsigned type_id, void *mesg) +{ + size_t mesg_size; + htri_t tri_ret; + H5SM_master_table_t *table = NULL; + unsigned cache_flags = H5AC__NO_FLAGS_SET; + ssize_t index_num; + herr_t ret_value = SUCCEED; + FUNC_ENTER_NOAPI(H5SM_try_share, FAIL) + + /* Check whether this message ought to be shared or not */ + /* If sharing is disabled in this file, don't share the message */ + if(f->shared->sohm_addr == HADDR_UNDEF) + HGOTO_DONE(FALSE); + + /* 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 < 15) /* 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) + { + /* Don't share immutable datatypes */ + if((tri_ret = H5T_is_immutable((H5T_t*) mesg)) > 0) + { + HGOTO_DONE(FALSE); + } + else if(tri_ret <0) + HGOTO_ERROR(H5E_OHDR, H5E_BADTYPE, FAIL, "can't tell if datatype is immutable") + /* Don't share committed datatypes */ + if((tri_ret = H5T_committed((H5T_t*) mesg)) > 0) + { + HGOTO_DONE(FALSE); + } + else if(tri_ret <0) + HGOTO_ERROR(H5E_OHDR, H5E_BADTYPE, FAIL, "can't tell if datatype is comitted") + } + + /* Look up the master SOHM table */ + if (NULL == (table = H5AC_protect(f, dxpl_id, H5AC_SOHM_TABLE, f->shared->sohm_addr, NULL, NULL, H5AC_WRITE))) + HGOTO_ERROR(H5E_CACHE, H5E_CANTPROTECT, FAIL, "unable to load SOHM master table") + + /* Find the right index for this message type. If there is no such index + * then this type of message isn't shareable + */ + H5E_BEGIN_TRY { + index_num = H5SM_get_index(table, type_id); + } H5E_END_TRY + if(index_num < 0) + HGOTO_DONE(FALSE); + + /* At this point, the message should definitely be shared. */ + + /* If the index hasn't been allocated yet, create it */ + if(table->indexes[index_num].index_addr == HADDR_UNDEF) + { + if(H5SM_create_index(f, &(table->indexes[index_num]), dxpl_id) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_CANTINIT, FAIL, "unable to create SOHM index") + cache_flags |= H5AC__DIRTIED_FLAG; + } + + /* Write the message as a shared message */ + if(H5SM_write_mesg(f, dxpl_id, &(table->indexes[index_num]), type_id, mesg, &cache_flags) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_CANTINSERT, FAIL, "can't write shared message") + +done: + /* Release the master SOHM table */ + if (table && H5AC_unprotect(f, dxpl_id, H5AC_SOHM_TABLE, f->shared->sohm_addr, table, cache_flags) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTRELEASE, FAIL, "unable to close SOHM master table") + + FUNC_LEAVE_NOAPI(ret_value) +} + + +/*------------------------------------------------------------------------- + * Function: H5SM_write_mesg + * + * Purpose: Writes a message to an existing index and change the message + * to reflect that it's now shared. + * + * If the message is already in the index, increment its + * reference count instead of writing it again and make the + * user's copy point to the copy we wrote before. + * + * The index could be a list or a B-tree. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * Tuesday, May 2, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5SM_write_mesg(H5F_t *f, hid_t dxpl_id, H5SM_index_header_t *header, + unsigned type_id, void *mesg, unsigned *cache_flags_ptr) +{ + H5SM_list_t *list = NULL; /* List index */ + H5SM_mesg_key_t key; /* Key used to search the index */ + H5O_shared_t shared; /* Shared H5O message */ + hsize_t list_pos; /* Position in a list index */ + hbool_t found = FALSE; /* Was the message in the index? */ + H5HF_t *fheap = NULL; /* Fractal heap handle */ + size_t buf_size; /* Size of the encoded message */ + void * encoding_buf=NULL; /* Buffer for encoded message */ + herr_t ret_value = SUCCEED; + FUNC_ENTER_NOAPI(H5SM_write_mesg, FAIL) + + HDassert(cache_flags_ptr); + HDassert(header); + HDassert(header->index_type != H5SM_BADTYPE); + + /* Set up a shared message so that we can make this message shared once it's + * written to the index. This message is always stored to the heap, not to + * an object header. + */ + shared.flags = H5O_SHARED_IN_HEAP_FLAG; + + /* Encode the message to be written */ + if((buf_size = H5O_raw_size(type_id, f, mesg)) <= 0) + HGOTO_ERROR(H5E_OHDR, H5E_BADSIZE, FAIL, "can't find message size"); + + if(NULL == (encoding_buf = H5MM_calloc(buf_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate buffer for encoding"); + + if(H5O_encode(f, encoding_buf, mesg, type_id) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "can't encode message to be shared"); + + /* Open the fractal heap for this index */ + if(NULL == (fheap=H5HF_open(f, dxpl_id, header->heap_addr))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap") + + /* Set up a key for the message to be written */ + key.hash = H5_checksum_lookup3(encoding_buf, buf_size, type_id); + key.encoding = encoding_buf; + key.encoding_size = buf_size; + key.fheap = fheap; + key.mesg_heap_id = -1; /* Message doesn't yet have a heap ID */ + + /* Assume the message is already in the index and try to increment its + * reference count. If this fails, the message isn't in the index after + * all and we'll need to add it. + */ + if(header->index_type == H5SM_LIST) + { + /* The index is a list; get it from the cache */ + if (NULL == (list = H5AC_protect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, NULL, header, H5AC_WRITE))) + HGOTO_ERROR(H5E_CACHE, H5E_CANTPROTECT, FAIL, "unable to load SOHM index") + + /* JAMES: not very effecient (gets hash value twice, searches list twice). Refactor. */ + /* See if the message is already in the index and get its location */ + /* JAMES: should return a pointer to the message */ + list_pos=H5SM_find_in_list(f, list, &key); + if(list_pos != FAIL) + { + /* The message was in the index. Increment its reference count. */ + ++(list->messages[list_pos].ref_count); + + /* Set up the shared location to point to the shared location */ + shared.u.heap_id = list->messages[list_pos].fheap_id; + found = TRUE; + } + } + else /* Index is a B-tree */ + { + HDassert(header->index_type == H5SM_BTREE); + + /* If this returns failure, it means that the message wasn't found. */ + /* If it succeeds, the heap_id in the shared struct will be set */ + if(H5B2_modify(f, dxpl_id, H5SM_INDEX, header->index_addr, &key, H5SM_incr_ref, &shared.u.heap_id) >= 0) + { + found = TRUE; + } + } + + /* If the message isn't in the list, add it */ + if(!found) + { + hsize_t x; /* Counter variable */ + size_t mesg_size; /* Size of the message on disk */ + + /* JAMES: wrap this in a function call? */ + + /* Encode the message and get its size */ + if((mesg_size = H5O_raw_size(type_id, f, mesg)) == 0) + HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "unable to get size of message") + + 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") + + /* JAMES: this is where we should check for conversion to B-tree. */ + + /* JAMES: should be H5SM_insert or something */ + /* Find an empty spot in the list for the message JAMES: combine this with the previous traversal */ + /* Insert the new message into the SOHM index */ + if(header->index_type == H5SM_LIST) + { + for(x=0; xlist_to_btree; x++) + { + if(list->messages[x].hash == H5O_HASH_UNDEF) /* JAMES: is this a valid test? */ + { + list->messages[x].fheap_id = shared.u.heap_id; + list->messages[x].hash = key.hash; + list->messages[x].ref_count = 1; + break; + } + } + } + else /* Index is a B-tree */ + { + H5SM_sohm_t message; + HDassert(header->index_type == H5SM_BTREE); + message.fheap_id = shared.u.heap_id; + message.hash = key.hash; + message.ref_count = 1; + + if(H5B2_insert(f, dxpl_id, H5SM_INDEX, header->index_addr, &message) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "couldn't add SOHM to B-tree") + } + + ++(header->num_messages); + (*cache_flags_ptr) |= H5AC__DIRTIED_FLAG; + } + + /* Change the original message passed in to reflect that it's now shared */ + if(H5O_set_share(f, dxpl_id, &shared, type_id, mesg) < 0) + HGOTO_ERROR (H5E_OHDR, H5E_BADMESG, FAIL, "unable to set sharing information") + +done: + /* Release the fractal heap if we opened it */ + if(fheap) + if(H5HF_close(fheap, dxpl_id) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CLOSEERROR, FAIL, "can't close fractal heap") + + /* If we got a list out of the cache, release it (it is always dirty after writing a message) */ + if(list && H5AC_unprotect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, list, H5AC__DIRTIED_FLAG) < 0) + HDONE_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "unable to close SOHM index") + + if(encoding_buf) + H5MM_free(encoding_buf); + + FUNC_LEAVE_NOAPI(ret_value) +} + + + +/*------------------------------------------------------------------------- + * Function: H5SM_try_delete + * + * Purpose: Given an object header message that is being deleted, + * checks if it is a SOHM. If so, decrements its reference + * count. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * Tuesday, May 2, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5SM_try_delete(H5F_t *f, hid_t dxpl_id, unsigned type_id, const H5O_shared_t *mesg) +{ + H5SM_master_table_t *table = NULL; + unsigned cache_flags = H5AC__NO_FLAGS_SET; + ssize_t index_num; + herr_t ret_value = SUCCEED; + FUNC_ENTER_NOAPI(H5SM_try_delete, FAIL) + + HDassert(f); + HDassert(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)) + HGOTO_DONE(SUCCEED); + + HDassert(f->shared->sohm_addr != HADDR_UNDEF); + + /* Look up the master SOHM table */ + if (NULL == (table = H5AC_protect(f, dxpl_id, H5AC_SOHM_TABLE, f->shared->sohm_addr, NULL, NULL, H5AC_WRITE))) + HGOTO_ERROR(H5E_CACHE, H5E_CANTPROTECT, FAIL, "unable to load SOHM master table") + + /* Find the correct index and try to delete from it */ + if((index_num = H5SM_get_index(table, type_id)) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_NOTFOUND, HADDR_UNDEF, "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) + HGOTO_ERROR(H5E_SOHM, H5E_CANTDELETE, FAIL, "unable to delete mesage from SOHM index") + +done: + /* Release the master SOHM table */ + if (table && H5AC_unprotect(f, dxpl_id, H5AC_SOHM_TABLE, f->shared->sohm_addr, table, cache_flags) < 0) + HDONE_ERROR(H5E_CACHE, H5E_CANTRELEASE, FAIL, "unable to close SOHM master table") + + FUNC_LEAVE_NOAPI(ret_value) +} + + +/*------------------------------------------------------------------------- + * Function: H5SM_find_in_list + * + * Purpose: Find a message's location in a list + * + * Return: Number of messages remaining in the index on success + * FAIL if message couldn't be found + * + * Programmer: James Laird + * Tuesday, May 2, 2006 + * + *------------------------------------------------------------------------- + */ +static hsize_t +H5SM_find_in_list(H5F_t *f, H5SM_list_t *list, const H5SM_mesg_key_t *key) +{ + hsize_t x; + hsize_t ret_value = FAIL; + FUNC_ENTER_NOAPI_NOFUNC(H5SM_find_in_list) + + HDassert(f); + HDassert(list); + HDassert(key); + + for(x=0; xheader->list_to_btree; x++) + { + if(0 == H5SM_message_compare(key, &(list->messages[x]))) + { + ret_value = x; + break; + } + } + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5SM_find_in_list */ + + +/*------------------------------------------------------------------------- + * Function: H5SM_delete_from_index + * + * Purpose: Given a SOHM message, delete it from this index. + * JAMES: is the message necessarily in the index? Also, name this "dec ref count" or something. + * + * Return: Non-negative on success + * Negative on failure + * + * Programmer: James Laird + * Tuesday, May 2, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5SM_delete_from_index(H5F_t *f, hid_t dxpl_id, H5SM_index_header_t *header, unsigned type_id, const H5O_shared_t * mesg, unsigned *cache_flags) +{ + H5SM_list_t *list = NULL; + H5SM_mesg_key_t key; + H5SM_sohm_t message; + unsigned char *buf = NULL; + size_t buf_size; + hsize_t list_pos; /* Position of the message in the list */ + H5HF_t *fheap=NULL; /* Fractal heap that contains the message */ + herr_t ret_value = SUCCEED; + FUNC_ENTER_NOAPI(H5SM_delete_from_index, FAIL) + + HDassert(header); + 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))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap") + + /* JAMES: use heap op command */ + /* Get the message size */ + if(H5HF_get_obj_len(fheap, dxpl_id, &(mesg->u.heap_id), &buf_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get message size from fractal heap.") + + /* Allocate a buffer to hold the message */ + if(NULL == (buf = HDmalloc(buf_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "couldn't allocate memory"); + + /* Read the message to get its hash value */ + if(H5HF_read(fheap, dxpl_id, &(mesg->u.heap_id), buf) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't read message from fractal heap.") + + + /* Set up key for message to be deleted. */ + key.hash = H5_checksum_lookup3(buf, buf_size, type_id); + key.encoding = NULL; + key.encoding_size = 0; + key.fheap = fheap; /* JAMES: unused */ + key.mesg_heap_id = mesg->u.heap_id; + + /* Try to find the message in the index */ + if(header->index_type == H5SM_LIST) + { + /* If the index is stored as a list, get it from the cache */ + if (NULL == (list = H5AC_protect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, NULL, header, H5AC_WRITE))) + HGOTO_ERROR(H5E_SOHM, H5E_CANTPROTECT, FAIL, "unable to load SOHM index") + + /* Find the message in the list */ + if((list_pos = H5SM_find_in_list(f, list, &key)) == FAIL) + HGOTO_ERROR(H5E_SOHM, H5E_NOTFOUND, FAIL, "message not in index") + + --(list->messages[list_pos].ref_count); + /* Copy the message */ + message = list->messages[list_pos]; + } + else /* Index is a B-tree */ + { + HDassert(header->index_type == H5SM_BTREE); + + /* If this returns failure, it means that the message wasn't found. + * If it succeeds, a copy of the modified message will be returned. */ + if(H5B2_modify(f, dxpl_id, H5SM_INDEX, header->index_addr, &key, H5SM_decr_ref, &message) <0) + HGOTO_ERROR(H5E_SOHM, H5E_NOTFOUND, FAIL, "message not in index") + } + + /* If the ref count is zero, delete the message from the index */ + if(message.ref_count <= 0) + { + /* Remove the message from the heap */ + if(H5HF_remove(fheap, dxpl_id, &(message.fheap_id)) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_CANTREMOVE, FAIL, "unable to remove message from heap") + + if(header->index_type == H5SM_LIST) + { + list->messages[list_pos].hash = H5O_HASH_UNDEF; + } + else + { + if(H5B2_remove(f, dxpl_id, H5SM_INDEX, header->index_addr, &key, NULL, NULL) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTREMOVE, FAIL, "unable to delete message") + } + + /* Update the index header, so set its dirty flag */ + --header->num_messages; + *cache_flags |= H5AC__DIRTIED_FLAG; + } + +done: + /* Free the message buffer */ + if(buf) + HDfree(buf); + + /* Release the SOHM list */ + if (list && H5AC_unprotect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, list, H5AC__DIRTIED_FLAG) < 0) + HDONE_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "unable to close SOHM index") + + /* Release the fractal heap if we opened it */ + if(fheap) + if(H5HF_close(fheap, dxpl_id) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CLOSEERROR, FAIL, "can't close fractal heap") + + FUNC_LEAVE_NOAPI(ret_value) +} + + +/*------------------------------------------------------------------------- + * Function: H5SM_get_info + * + * Purpose: Get the list-to-btree and btree-to-list cutoff numbers for + * an index within the master table. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * Thursday, May 11, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t H5SM_get_info(H5F_t *f, haddr_t table_addr, unsigned *nindexes, + unsigned *index_flags, size_t *list_to_btree, + size_t *btree_to_list, hid_t dxpl_id) +{ + H5SM_master_table_t *table = NULL; + unsigned i; + herr_t ret_value = SUCCEED; + FUNC_ENTER_NOAPI(H5SM_get_info, FAIL) + + HDassert(table_addr != HADDR_UNDEF); + + /* Get the SOHM table from the cache */ + if (NULL == (table = H5AC_protect(f, dxpl_id, H5AC_SOHM_TABLE, table_addr, NULL, NULL, H5AC_READ))) + HGOTO_ERROR(H5E_CACHE, H5E_CANTPROTECT, FAIL, "unable to load SOHM master table") + + /* Return info */ + *nindexes = table->num_indexes; + *list_to_btree = table->indexes[0].list_to_btree; + *btree_to_list = table->indexes[0].btree_to_list; + + /* Get information about the individual SOHM indexes */ + for(i=0; inum_indexes; ++i) + { + index_flags[i] = table->indexes[i].mesg_types; + } + +done: + /* Release the master SOHM table if we took it out of the cache */ + if (table && H5AC_unprotect(f, dxpl_id, H5AC_SOHM_TABLE, table_addr, table, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTRELEASE, FAIL, "unable to close SOHM master table") + + FUNC_LEAVE_NOAPI(ret_value) +} + diff --git a/src/H5SMbtree2.c b/src/H5SMbtree2.c new file mode 100755 index 0000000..7e98b06 --- /dev/null +++ b/src/H5SMbtree2.c @@ -0,0 +1,351 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5SM_PACKAGE /*suppress error about including H5SMpkg */ +#define H5F_PACKAGE /*suppress error about including H5Fpkg */ + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5ACprivate.h" /* Metadata cache */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5FLprivate.h" /* Free Lists */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5Fpkg.h" /* File access */ +#include "H5SMpkg.h" /* Shared object header messages */ + +#include "H5B2private.h" /* v2 B-trees */ +/****************/ +/* Local Macros */ +/****************/ + +/******************/ +/* Local Typedefs */ +/******************/ + +/********************/ +/* Local Prototypes */ +/********************/ + +static herr_t H5SM_message_store(void *native, const void *udata); +static herr_t H5SM_message_retrieve(void *udata, const void *native); +static herr_t H5SM_message_debug(FILE *stream, const H5F_t *f, hid_t dxpl_id, + int indent, int fwidth, const void *record, const void *_udata); + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ +/* v2 B-tree class for SOHM indexes*/ +const H5B2_class_t H5SM_INDEX[1]={{ /* B-tree class information */ + H5B2_SOHM_INDEX_ID, /* Type of B-tree */ + sizeof(H5SM_sohm_t), /* Size of native record */ + H5SM_message_store, /* Record storage callback */ + H5SM_message_retrieve, /* Record retrieval callback */ + H5SM_message_compare, /* Record comparison callback */ + H5SM_message_encode, /* Record encoding callback */ + H5SM_message_decode, /* Record decoding callback */ + H5SM_message_debug /* Record debugging callback */ +}}; + +/*******************/ +/* Local Variables */ +/*******************/ + + +/*------------------------------------------------------------------------- + * Function: H5SM_message_compare + * + * Purpose: Determine whether the search key rec1 represents a shared + * message that is equal to rec2 or not, and if not, whether + * rec1 is "greater than" or "less than" rec2. + * + * Return: 0 if rec1 == rec2 + * Negative if rec1 < rec2 + * Positive if rec1 > rec2 + * + * Programmer: James Laird + * Monday, November 6, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5SM_message_compare(const H5SM_mesg_key_t *rec1, const H5SM_sohm_t *rec2) +{ + herr_t hash_diff; + herr_t ret_value=0; + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_message_compare) + + hash_diff = (herr_t) (rec1->hash - rec2->hash); + + /* If the hash values match, make sure the messages are really the same */ + if(0 == hash_diff) { + /* Compare either the heap_ids directly (if the key has one) + * or the encoded buffers + */ + /* JAMES: not a great test. Use a flag instead? */ + if(rec1->encoding_size == 0) + { + ret_value = (herr_t) (rec1->mesg_heap_id - rec2->fheap_id); + } + else + { + unsigned char buf2[H5O_MESG_MAX_SIZE]; + herr_t ret; + + /* We need to see if this message is in fact the message stored + * in the heap. Read it from the heap and compare the two. + */ + HDmemset(buf2, 0, H5O_MESG_MAX_SIZE); + + ret = H5HF_read(rec1->fheap, H5AC_dxpl_id, &(rec2->fheap_id), &buf2); + HDassert(ret >= 0); + + /* JAMES: I think I want to use in-heap callback here. */ + ret_value = HDmemcmp(rec1->encoding, buf2, rec1->encoding_size); + } + } + else + ret_value = hash_diff; + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5SM_message_compare */ + + + +/*------------------------------------------------------------------------- + * Function: H5SM_message_store + * + * Purpose: Store a H5SM_sohm_t SOHM message in the B-tree by copying it + * from UDATA to NATIVE. + * + * Return: Non-negative on success + * Negative on failure + * + * Programmer: James Laird + * Monday, November 6, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5SM_message_store(void *native, const void *udata) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_message_store) + + /* Copy the source message to the B-tree */ + *(H5SM_sohm_t *)native = *(const H5SM_sohm_t *)udata; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5SM_message_store */ + + + +/*------------------------------------------------------------------------- + * Function: H5SM_message_retrieve + * + * Purpose: Retrieve a H5SM_sohm_t SOHM message from the B-tree by + * copying it from NATIVE to UDATA. + * + * Quincey said this function may no longer be used. + * + * Return: Non-negative on success + * Negative on failure + * + * Programmer: James Laird + * Monday, November 6, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5SM_message_retrieve(void *udata, const void *native) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_message_retrieve) + + /* Copy the B-tree's native message to the udata buffer */ + *(H5SM_sohm_t *)udata = *(const H5SM_sohm_t *)native; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5SM_message_retrieve */ + + + +/*------------------------------------------------------------------------- + * Function: H5SM_message_encode + * + * Purpose: Serialize the SOHM message. + * + * Return: Non-negative on success + * Negative on failure + * + * Programmer: James Laird + * Monday, November 6, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5SM_message_encode(const H5F_t *f, uint8_t *raw, const void *_nrecord) +{ + H5SM_sohm_t *message = (H5SM_sohm_t *)_nrecord; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_message_encode) + + /* Encode the SOHM's fields */ + UINT32ENCODE(raw, message->hash); + UINT16ENCODE(raw, message->ref_count); + UINT64ENCODE(raw, message->fheap_id); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5SM_message_encode */ + + +/*------------------------------------------------------------------------- + * Function: H5SM_message_decode + * + * Purpose: Read an encoded SOHM message into an H5SM_sohm_t struct. + * + * Return: Non-negative on success + * Negative on failure + * + * Programmer: James Laird + * Monday, November 6, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5SM_message_decode(const H5F_t *f, const uint8_t *raw, void *_nrecord) +{ + H5SM_sohm_t *message = (H5SM_sohm_t *)_nrecord; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_message_decode) + + /* Encode the SOHM's fields */ + UINT32DECODE(raw, message->hash); + UINT16DECODE(raw, message->ref_count); + UINT64DECODE(raw, message->fheap_id); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5SM_message_decode */ + + + +/*------------------------------------------------------------------------- + * Function: H5SM_message_debug + * + * Purpose: Print debugging information for a H5SM_sohm_t. + * + * Return: Non-negative on success + * Negative on failure + * + * Programmer: James Laird + * Monday, November 6, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5SM_message_debug(FILE *stream, const H5F_t *f, hid_t dxpl_id, + int indent, int fwidth, const void *record, const void *_udata) +{ + const H5SM_sohm_t *sohm = (const H5SM_sohm_t *)record; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_message_debug) + + HDfprintf(stream, "%*s%-*s {%a, %lo, %Hu}\n", indent, "", fwidth, "Record:", + sohm->fheap_id, sohm->hash, sohm->ref_count); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5SM_message_debug */ + + +/*------------------------------------------------------------------------- + * Function: H5SM_incr_ref + * + * Purpose: Increment the reference count for a SOHM message and return + * the message's heap ID. + * + * The message pointer is actually returned via op_data, which + * should be a pointer to a H5SM_fheap_id_t. + * + * Return: Non-negative on success + * Negative on failure + * + * Programmer: James Laird + * Monday, November 6, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5SM_incr_ref(void *record, void *op_data, hbool_t *changed) +{ + H5SM_sohm_t *message = (H5SM_sohm_t *) record; + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_incr_ref) + + HDassert(record); + HDassert(op_data); + HDassert(changed); + + ++message->ref_count; + *changed = TRUE; + + if(op_data) + *(H5SM_fheap_id_t *)op_data = message->fheap_id; + + FUNC_LEAVE_NOAPI(SUCCEED) +} + + + +/*------------------------------------------------------------------------- + * Function: H5SM_decr_ref + * + * Purpose: Decrement the reference count for a SOHM message. Doesn't + * 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. + * + * Return: Non-negative on success + * Negative on failure + * + * Programmer: James Laird + * Monday, November 6, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5SM_decr_ref(void *record, void *op_data, hbool_t *changed) +{ + H5SM_sohm_t *message = (H5SM_sohm_t *) record; + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_decr_ref) + + HDassert(record); + HDassert(op_data); + HDassert(changed); + + --message->ref_count; + *changed = TRUE; + + if(op_data) + *(hsize_t *)op_data = message->ref_count; + + FUNC_LEAVE_NOAPI(SUCCEED) +} + + diff --git a/src/H5SMcache.c b/src/H5SMcache.c new file mode 100644 index 0000000..6403dc3 --- /dev/null +++ b/src/H5SMcache.c @@ -0,0 +1,626 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5SM_PACKAGE /*suppress error about including H5SMpkg */ +#define H5F_PACKAGE /*suppress error about including H5Fpkg */ + +/***********/ +/* Headers */ +/***********/ +/* JAMES: these need to go first or else FILE isn't defined in H5Fpkg.h */ +/* JAMES: which of these are really needed? H5Fpkg.h, even? */ +#include "H5private.h" /* Generic Functions */ +#include "H5Aprivate.h" /* Attributes */ +#include "H5ACprivate.h" /* Metadata cache */ +#include "H5Dprivate.h" /* Datasets */ +#include "H5Eprivate.h" /* Error handling */ + +#include "H5Fpkg.h" /* File access */ +#include "H5FLprivate.h" /* Free Lists */ +#include "H5FOprivate.h" /* File objects */ +#include "H5HLprivate.h" /* Local heaps */ +#include "H5MFprivate.h" /* File memory management */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5Vprivate.h" /* Vectors and arrays */ +#include "H5SMpkg.h" /* Shared object header messages */ +#include "H5FDprivate.h" /* File drivers */ + +/****************/ +/* Local Macros */ +/****************/ +#define H5F_TABLEBUF_SIZE H5SM_TABLE_SIZEOF_MAGIC + 20 + (H5SM_MAX_INDEXES * 26) +/* JAMES: should this change according to address size? */ +#define H5F_LISTBUF_SIZE H5SM_LIST_SIZEOF_MAGIC + H5SM_MAX_LIST_ELEMS * 16 + +/******************/ +/* Local Typedefs */ +/******************/ + +/********************/ +/* Local Prototypes */ +/********************/ +static herr_t H5SM_flush_table(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5SM_master_table_t *table); +static H5SM_master_table_t *H5SM_load_table(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1, void *udata2); +static herr_t H5SM_clear_table(H5F_t *f, H5SM_master_table_t *table, hbool_t destroy); +static herr_t H5SM_dest_table(H5F_t *f, H5SM_master_table_t* table); +static herr_t H5SM_table_size(const H5F_t *f, const H5SM_master_table_t *table, size_t *size_ptr); + +static herr_t H5SM_flush_list(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5SM_list_t *list); +static H5SM_list_t *H5SM_load_list(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1, void *udata2); +static herr_t H5SM_clear_list(H5F_t *f, H5SM_list_t *list, hbool_t destroy); +static herr_t H5SM_dest_list(H5F_t *f, H5SM_list_t* list); +static herr_t H5SM_list_size(const H5F_t *f, const H5SM_list_t UNUSED *list, size_t *size_ptr); + +/*********************/ +/* Package Variables */ +/*********************/ +/* H5SM inherits cache-like properties from H5AC */ +const H5AC_class_t H5AC_SOHM_TABLE[1] = {{ + H5AC_SOHM_TABLE_ID, + (H5AC_load_func_t) H5SM_load_table, + (H5AC_flush_func_t) H5SM_flush_table, + (H5AC_dest_func_t) H5SM_dest_table, + (H5AC_clear_func_t)H5SM_clear_table, + (H5AC_size_func_t) H5SM_table_size, +}}; + +const H5AC_class_t H5AC_SOHM_LIST[1] = {{ + H5AC_SOHM_LIST_ID, + (H5AC_load_func_t) H5SM_load_list, + (H5AC_flush_func_t) H5SM_flush_list, + (H5AC_dest_func_t) H5SM_dest_list, + (H5AC_clear_func_t)H5SM_clear_list, + (H5AC_size_func_t) H5SM_list_size, +}}; + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + +/*******************/ +/* Local Variables */ +/*******************/ + +/*------------------------------------------------------------------------- + * Function: H5SM_flush_table + * + * Purpose: Flushes (and destroys) the table of Shared Object Header + * Message indexes. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * November 6, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5SM_flush_table(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5SM_master_table_t *table) +{ + herr_t ret_value=SUCCEED; + + FUNC_ENTER_NOAPI(H5SM_flush_table, FAIL) + + /* check arguments */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(table); + + if (table->cache_info.is_dirty) { + uint8_t buf[H5F_TABLEBUF_SIZE]; /* Temporary buffer */ /* JAMES This is big. Do I need to use H5FL_BLK_MALLOC instead? */ + uint8_t *p; /* Pointer into raw data buffer */ + size_t size; /* Header size on disk */ + int x; /* Counter variable */ + + /* Encode the master table and all of the index headers as one big blob */ + size = H5SM_TABLE_SIZE(f) + (H5SM_INDEX_HEADER_SIZE(f) * table->num_indexes); + + /* Encode the master table */ + p = buf; + + /* Encode magic number */ + HDmemcpy(p, H5SM_TABLE_MAGIC, (size_t)H5SM_TABLE_SIZEOF_MAGIC); + p += H5SM_TABLE_SIZEOF_MAGIC; + + *p++ = HDF5_SOHMTABLE_VERSION; /* Version */ + + *p++ = table->num_indexes; /* Number of indexes in the table */ + + /* Encode each index header */ + for(x=0; xnum_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 */ + + 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 */ + H5F_addr_encode(f, &p, table->indexes[x].index_addr); /* Address of the actual index */ + H5F_addr_encode(f, &p, table->indexes[x].heap_addr); /* Address of the index's heap */ + } + + /* Write the table to disk */ + HDassert((size_t)(p - buf) == size); + if(H5F_block_write(f, H5FD_MEM_SOHM, addr, size, dxpl_id, buf) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_CANTFLUSH, FAIL, "unable to save sohm table to disk") + + table->cache_info.is_dirty = FALSE; + } + + if(destroy) + if(H5SM_dest_table(f, table) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_CANTFREE, FAIL, "unable to destroy sohm table") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5SM_flush_table */ + + + +/*------------------------------------------------------------------------- + * Function: H5SM_load_table + * + * Purpose: Loads the master table of Shared Object Header Message + * indexes. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * November 6, 2006 + * + *------------------------------------------------------------------------- + */ +static H5SM_master_table_t * +H5SM_load_table(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *udata1, void UNUSED *udata2) +{ + H5SM_master_table_t *table; /* The SOHM table being read in */ + size_t table_size; /* Size of SOHM master table on disk */ + size_t indexes_size; /* Size of index headers on disk */ + uint8_t *buf=NULL; /* Reading buffer */ + uint8_t *p; /* Pointer into input buffer */ + uint8_t x; /* Counter variable for index headers */ + H5SM_master_table_t *ret_value; + + FUNC_ENTER_NOAPI(H5SM_load_table, NULL) + + /* Allocate space for the SOHM table data structure */ + if(NULL == (table = H5MM_calloc(sizeof(H5SM_master_table_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* Compute the size of the SOHM table header on disk. Read in just the table first */ + table_size = H5SM_TABLE_SIZE(f); + + /* Allocate temporary buffer */ + if(NULL == (buf = HDmalloc(table_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* Read header from disk */ + if(H5F_block_read(f, H5FD_MEM_SOHM, addr, table_size, dxpl_id, buf) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_READERROR, NULL, "can't read SOHM table") + + p = buf; + + /* Check magic number */ + if(HDmemcmp(p, H5SM_TABLE_MAGIC, (size_t)H5SM_TABLE_SIZEOF_MAGIC)) + HGOTO_ERROR(H5E_SOHM, H5E_CANTLOAD, NULL, "bad SOHM table signature"); + p += H5SM_TABLE_SIZEOF_MAGIC; + + /* Version number */ + if (HDF5_SOHMTABLE_VERSION != *p++) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unknown SOHM table version number") + + table->num_indexes = *p++; /* Number of indexes in the table */ + + HDassert((size_t)(p - buf) == table_size); + + /* Allocate space for the index headers */ + if(NULL == (table->indexes = H5FL_ARR_MALLOC(H5SM_index_header_t, table->num_indexes))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for SOHM indexes") + + /* Now read in the list of index headers */ + indexes_size = table->num_indexes * H5SM_INDEX_HEADER_SIZE(f); + + /* Re-allocate temporary buffer */ + HDassert(buf); + HDfree(buf); + if(NULL == (buf = HDmalloc(indexes_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + + if(H5F_block_read(f, H5FD_MEM_SOHM, addr + table_size, indexes_size, dxpl_id, buf) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_READERROR, NULL, "can't read SOHM table") + p=buf; + + for(x=0; xnum_indexes; ++x) { + table->indexes[x].index_type= *p++; /* type of the index (list or B-tree) */ + + UINT16DECODE(p, table->indexes[x].mesg_types); + UINT16DECODE(p, table->indexes[x].list_to_btree); + UINT16DECODE(p, table->indexes[x].btree_to_list); + UINT16DECODE(p, table->indexes[x].num_messages); + H5F_addr_decode(f, &p, &(table->indexes[x].index_addr)); + H5F_addr_decode(f, &p, &(table->indexes[x].heap_addr)); + } + + HDassert((size_t)(p - buf) == indexes_size); + ret_value = table; + +done: + /* Free buffer if it was allocated */ + if(buf) + HDfree(buf); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5SM_load_table */ + + + +/*------------------------------------------------------------------------- + * Function: H5SM_clear_table + * + * Purpose: Mark this table as no longer being dirty. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * November 6, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5SM_clear_table(H5F_t *f, H5SM_master_table_t *table, hbool_t destroy) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5SM_clear_table) + + /* + * Check arguments. + */ + HDassert(table); + + /* Reset the dirty flag. */ + table->cache_info.is_dirty = FALSE; + + if(destroy) + if(H5SM_dest_table(f, table) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_CANTFREE, FAIL, "unable to delete SOHM master table") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5SM_clear_table */ + + + +/*------------------------------------------------------------------------- + * Function: H5SM_dest_table + * + * Purpose: Frees memory used by the SOHM table. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * November 6, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5SM_dest_table(H5F_t *f, H5SM_master_table_t* table) +{ + FUNC_ENTER_NOAPI_NOFUNC(H5SM_dest_table) + + assert(table); + + assert(table->indexes); + + H5FL_ARR_FREE(H5SM_index_header_t, table->indexes); + + H5MM_free(table); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5SM_dest_table */ + + +/*------------------------------------------------------------------------- + * Function: H5SM_table_size + * + * Purpose: Returns the size of the table encoded on disk. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * November 6, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5SM_table_size(const H5F_t *f, const H5SM_master_table_t *table, size_t *size_ptr) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_table_size) + + /* check arguments */ + HDassert(f); + HDassert(table); + HDassert(size_ptr); + + /* Set size value */ + *size_ptr = H5SM_TABLE_SIZE(f) + (table->num_indexes * H5SM_INDEX_HEADER_SIZE(f)); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5SM_table_size */ + + + +/*------------------------------------------------------------------------- + * Function: H5SM_flush_list + * + * Purpose: Flush this list index. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * November 6, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5SM_flush_list(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5SM_list_t *list) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(H5SM_flush_list, FAIL) + + /* check arguments */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(list); + HDassert(list->header); + + if (list->cache_info.is_dirty) { + uint8_t buf[H5F_LISTBUF_SIZE]; /* Temporary buffer */ /* JAMES Do I need to use H5FL_BLK_MALLOC instead? */ + uint8_t *p; /* Pointer into raw data buffer */ + size_t size; /* Header size on disk */ + hsize_t x; + + size = H5SM_LIST_SIZE(f, list->header->num_messages); + + /* Encode the list */ + p = buf; + + /* Encode magic number */ + HDmemcpy(p, H5SM_LIST_MAGIC, (size_t)H5SM_LIST_SIZEOF_MAGIC); + p += H5SM_LIST_SIZEOF_MAGIC; + + /* Write messages from the messages array to disk */ + /* JAMES: we have to search the whole array. not the best way to do it; could go until we've written + * num_messages */ + for(x=0; xheader->list_to_btree; x++) { + if(list->messages[x].fheap_id != 0 && list->messages[x].hash != H5O_HASH_UNDEF) { + /* JAMES: use H5SM_message_encode here */ + UINT32ENCODE(p, list->messages[x].hash); /* Read the hash value for this message */ + UINT16ENCODE(p, list->messages[x].ref_count); /* Read the reference count for this message */ + UINT64ENCODE(p, list->messages[x].fheap_id); /* Get the heap ID for the message */ + } + } + + /* Write the list to disk */ + HDassert((size_t)(p - buf) == size); + if(H5F_block_write(f, H5FD_MEM_SOHM, addr, size, dxpl_id, buf) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_CANTFLUSH, FAIL, "unable to save sohm table to disk") + + list->cache_info.is_dirty = FALSE; + } + + if(destroy) + if(H5SM_dest_list(f, list) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_CANTFREE, FAIL, "unable to destroy list") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5SM_flush_list */ + + + +/*------------------------------------------------------------------------- + * Function: H5SM_load_list + * + * Purpose: Loads a list of SOHM messages. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * November 6, 2006 + * + *------------------------------------------------------------------------- + */ +static H5SM_list_t * +H5SM_load_list(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *udata1, void *udata2) +{ + H5SM_list_t *list; /* The SOHM list being read in */ + H5SM_index_header_t *header = (H5SM_index_header_t *) udata2; /* Index header for this list */ + size_t size; /* Size of SOHM list on disk */ + uint8_t *buf = NULL; /* Reading buffer */ + uint8_t *p; /* Pointer into input buffer */ + hsize_t x; /* Counter variable for messages in list */ + H5SM_list_t *ret_value=NULL; + + FUNC_ENTER_NOAPI(H5SM_load_list, NULL) + + HDassert(header); + + /* Allocate space for the SOHM list data structure and initialize list JAMES don't need to initialize all of list */ + if(NULL == (list = H5FL_MALLOC(H5SM_list_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + HDmemset(&list->cache_info, 0, sizeof(H5AC_info_t)); + + /* Allocate list in memory as an array*/ + if((list->messages = H5FL_ARR_MALLOC(H5SM_sohm_t, header->list_to_btree)) == NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "file allocation failed for SOHM list") + + list->header = header; + + /* Compute the size of the SOHM list on disk */ + size = H5SM_LIST_SIZE(f, header->num_messages); + + /* Allocate temporary buffer */ + /* JAMES: is BLK_MALLOC somehow better for this? */ + if(NULL == (buf = HDmalloc(size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* Read list from disk */ + if(H5F_block_read(f, H5FD_MEM_SOHM, addr, size, dxpl_id, buf) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_READERROR, NULL, "can't read SOHM list") + p = buf; + + /* Check magic number */ + if(HDmemcmp(p, H5SM_LIST_MAGIC, (size_t)H5SM_LIST_SIZEOF_MAGIC)) + HGOTO_ERROR(H5E_SOHM, H5E_CANTLOAD, NULL, "bad SOHM list signature"); + p += H5SM_LIST_SIZEOF_MAGIC; + + /* Read messages into the list array */ + for(x=0; xnum_messages; x++) + { + UINT32DECODE(p, list->messages[x].hash); /* Read the hash value for this message */ + UINT16DECODE(p, list->messages[x].ref_count); /* Read the reference count for this message */ + UINT64DECODE(p, list->messages[x].fheap_id); /* Get the heap ID for the message */ + } + + /* Initialize the rest of the array */ + for(x=header->num_messages; xlist_to_btree; x++) + { + list->messages[x].fheap_id = 0; /* JAMES: would making this one operation make it faster? */ + list->messages[x].hash = H5O_HASH_UNDEF; + } + + HDassert((size_t)(p - buf) == size); + + ret_value = list; +done: + if(buf) + HDfree(buf); + + if(ret_value == NULL) { + if(list) { + if(list->messages) { + H5FL_ARR_FREE(H5SM_sohm_t, list->messages); + } + H5FL_FREE(H5SM_list_t, list); + } + } + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5SM_load_list */ + + +/*------------------------------------------------------------------------- + * Function: H5SM_clear_list + * + * Purpose: Marks a list as not dirty. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * November 6, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5SM_clear_list(H5F_t *f, H5SM_list_t *list, hbool_t destroy) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5SM_clear_list) + + /* + * Check arguments. + */ + HDassert(list); + + /* Reset the dirty flag. */ + list->cache_info.is_dirty = FALSE; + + if(destroy) + if(H5SM_dest_list(f, list) < 0) + HGOTO_ERROR(H5E_SOHM, H5E_CANTFREE, FAIL, "unable to destroy SOHM list") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end of H5SM_clear_list */ + + + +/*------------------------------------------------------------------------- + * Function: H5SM_dest_list + * + * Purpose: Frees all memory used by the list. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * November 6, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5SM_dest_list(H5F_t *f, H5SM_list_t* list) +{ + FUNC_ENTER_NOAPI_NOFUNC(H5SM_dest_list) + + HDassert(list); + HDassert(list->messages); + + H5FL_ARR_FREE(H5SM_sohm_t, list->messages); + + H5FL_FREE(H5SM_list_t, list); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5SM_dest_list */ + + +/* JAMES: should this number be constant, or should it increase and decrease as + * messages are added and removed? */ +/*------------------------------------------------------------------------- + * Function: H5SM_list_size + * + * Purpose: Gets the size of a list on disk. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: James Laird + * November 6, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5SM_list_size(const H5F_t *f, const H5SM_list_t *list, size_t *size_ptr) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_list_size) + + /* check arguments */ + HDassert(f); + HDassert(list); + HDassert(list->header); + HDassert(size_ptr); + + /* Set size value */ + *size_ptr = H5SM_LIST_SIZE(f, list->header->list_to_btree); /* JAMES: might want to have variable-sized lists */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5SM_list_size */ + + + diff --git a/src/H5SMpkg.h b/src/H5SMpkg.h new file mode 100755 index 0000000..9016884 --- /dev/null +++ b/src/H5SMpkg.h @@ -0,0 +1,174 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Programmer: James Laird + * Thursday, March 30, 2006 + * + * Purpose: This file contains declarations which are visible only within + * the H5SM shared object header messages package. Source files + * outside the H5SM package should include H5SMprivate.h instead. + */ +#ifndef _H5SMpkg_H +#define _H5SMpkg_H + +#include "H5SMprivate.h" +#include "H5B2private.h" /* B-trees */ +#include "H5HFprivate.h" /* Fractal heaps */ + + +/****************************/ +/* Package Macros */ +/****************************/ +#define H5SM_LIST_MAGIC "SMLI" +#define H5SM_LIST_SIZEOF_MAGIC 4 +#define H5SM_TABLE_MAGIC "SMTB" +#define H5SM_TABLE_SIZEOF_MAGIC 4 + +#define H5SM_SOHM_ENTRY_SIZE(f) (4 /* Hash value */ \ + + 2 /* reference count*/ \ + + 8) /* JAMES: size of hash value on disk */ + +#define H5SM_TABLE_SIZE(f) ( H5SM_TABLE_SIZEOF_MAGIC \ + + 1 /* Table version */ \ + + 1) /* Number of indexes */ + +#define H5SM_INDEX_HEADER_SIZE(f) (1 /* Whether index is a list or B-tree */ \ + + 2 /* Type of messages stored in the index */ \ + + (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 */ + +#define H5SM_LIST_SIZE(f, num_mesg) H5SM_LIST_SIZEOF_MAGIC \ + + (H5SM_SOHM_ENTRY_SIZE(f) * num_mesg) + +#define H5SM_MAX_INDEXES 8 +#define H5SM_MAX_LIST_ELEMS 1000 + +/****************************/ +/* Package Typedefs */ +/****************************/ + +/* There are a number of Shared Object Header Message-specific structs here. + * + * The H5SM_master_table_t is pointed to by the file superblock. Since a file + * can have more than one SOHM index, this table collects all the indexes into + * one place. It holds an array of H5SM_index_header_t structs. + * + * An H5SM_index_header_t is actually the for a given index. It holds + * the number of messages in the index, the types of messages in the index, + * etc. It also records whether the index is a list or a b-tree, and has + * the address of the list or b-tree. + * + * If the index is a list, the address in the index header should be given + * to the cache, which can load it into a H5SM_list_t struct. This is mostly + * just a header for the cache information; it contains a pointer back to + * the index header and an unsorted array of messages. + * + * These messages are H5SM_sohm_t structs. They hold the actual SOHM's + * address, hash value, and refcount. + * + * If the index is a b-tree, the H5SM_index_header_t struct holds the address + * of the b-tree instead of the address of a H5SM_list_t. The B-tree's nodes + * are still 'H5SM_sohm_t's. + * + * H5SM_mesg_key_t structs are used to search lists and B-trees for a certain + * message. They correspond to a message that hasn't yet been written to + * disk. + */ + +/* Declare free lists to manage H5SM structs */ +H5FL_ARR_EXTERN(H5SM_index_header_t); +H5FL_EXTERN(H5SM_list_t); +H5FL_ARR_EXTERN(H5SM_sohm_t); + +typedef enum { + H5SM_BADTYPE = -1, + H5SM_LIST, /* Index is an unsorted list */ + H5SM_BTREE /* Index is a sorted B-tree */ +} H5SM_index_type_t; + +/* Typedef for searching an index (list or B-tree) */ +typedef struct { + uint32_t hash; /* The hash value for this message */ + const void *encoding; /* The message encoded */ + hsize_t encoding_size; /* Size of the encoding */ + H5HF_t *fheap; /* The heap for this message type, open. */ + H5SM_fheap_id_t mesg_heap_id; /* The heap_id for this message */ +} H5SM_mesg_key_t; + +/* Typedef for a SOHM index header */ +typedef struct { + unsigned mesg_types; /* Bit flag vector of message types */ + 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 */ + H5SM_index_type_t index_type; /* Is the index a list or a B-tree? */ + haddr_t index_addr; /* Address of the actual index (list or B-tree) */ + haddr_t heap_addr; /* Address of the fheap used to store shared messages */ +} H5SM_index_header_t; + +/* Typedef for a SOHM list */ +typedef struct { + /* Information for H5AC cache functions, _must_ be first field in structure */ + H5AC_info_t cache_info; + + H5SM_index_header_t *header; /* Pointer to the corresponding index header */ + H5SM_sohm_t *messages; /* Actual list, stored as an array */ +} H5SM_list_t; + + +/* Typedef for shared object header message master table */ +typedef struct { + /* Information for H5AC cache functions, _must_ be first field in structure */ + H5AC_info_t cache_info; + + uint8_t num_indexes; /* Number of indexes */ + H5SM_index_header_t *indexes; /* Array of num_indexes indexes */ +} H5SM_master_table_t; + + +#define H5SM_B2_NODE_SIZE 512 +#define H5SM_B2_SPLIT_PERCENT 100 +#define H5SM_B2_MERGE_PERCENT 40 + +/****************************/ +/* Package Variables */ +/****************************/ +H5_DLLVAR const H5AC_class_t H5AC_SOHM_TABLE[1]; +H5_DLLVAR const H5AC_class_t H5AC_SOHM_LIST[1]; + +H5_DLLVAR const H5B2_class_t H5SM_INDEX[1]; + +/****************************/ +/* Package Prototypes */ +/****************************/ +/* Encode and decode routines, used for B-tree and cache encoding/decoding */ +H5_DLL herr_t H5SM_message_encode(const H5F_t *f, uint8_t *raw, + const void *native); +H5_DLL herr_t H5SM_message_decode(const H5F_t *f, const uint8_t *raw, + void *native); + +/* Callbacks to give to B-tree traversals */ +/* H5SM_message_compare is in H5SMbtree2.c, but is also used by list code + * in H5SM.c. + */ +H5_DLL herr_t H5SM_message_compare(const H5SM_mesg_key_t *rec1, + const H5SM_sohm_t *rec2); + +/* H5B2_modify_t callbacks to adjust record's refcount. */ +H5_DLL herr_t H5SM_incr_ref(void *record, void *op_data, hbool_t *changed); +H5_DLL herr_t H5SM_decr_ref(void *record, void *op_data, hbool_t *changed); +#endif /*_H5SMpkg_H*/ + diff --git a/src/H5SMprivate.h b/src/H5SMprivate.h new file mode 100755 index 0000000..f1c2ad5 --- /dev/null +++ b/src/H5SMprivate.h @@ -0,0 +1,59 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Programmer: James Laird + * Thursday, March 2, 2006 + * + * Purpose: This file contains private declarations for the H5SM + * shared object header messages module. + */ +#ifndef _H5SMprivate_H +#define _H5SMprivate_H + +#include "H5SMpublic.h" +#include "H5Oprivate.h" +#include "H5Pprivate.h" + +/****************************/ +/* Library Private Typedefs */ +/****************************/ + +#define HDF5_SOHMTABLE_VERSION 0 /* Version of the Shared Object Header Message Master Table*/ +#define HDF5_SOHMINDEX_VERSION 0 /* Verion of Shared Object Header Message Indexes */ + +#define H5SM_MAX_NUM_INDEXES 6 + +/* Typedef for a SOHM index node */ +typedef struct { + /* JAMES: I think I need message type here, and stored in file. */ + uint32_t hash; /* Hash value for OHM */ + H5SM_fheap_id_t fheap_id; /* ID of the OHM in the fractal heap */ + hsize_t ref_count; /* JAMES TODO: should this be hsize_t? */ +} H5SM_sohm_t; + +/******************************/ +/* Library Private Prototypes */ +/******************************/ +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, haddr_t table_addr, unsigned *nindexes, + unsigned *index_flags, 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); + +#endif /*_H5SMprivate_H*/ + diff --git a/src/H5SMpublic.h b/src/H5SMpublic.h new file mode 100755 index 0000000..c1531f7 --- /dev/null +++ b/src/H5SMpublic.h @@ -0,0 +1,42 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Programmer: James Laird + * Monday, October 9, 2006 + * + * Purpose: This file contains public declarations for the H5SM + * shared object header messages module. + */ +#ifndef _H5SMpublic_H +#define _H5SMpublic_H + +/* Flags indicating which kinds of object header messages a given SOHM index + * holds. + * Pass these flags in using the mesg_type_flags array in + * H5P_set_shared_mesgs. + * (Developers: These flags correspond to object header message type_ids, + * but we need to assign each kind of message to a different bit so that + * one index can hold multiple types.) + */ +#define H5SM_NONE_FLAG 0x0000 /* No shared messages */ +#define H5SM_SDSPACE_FLAG 0x0001 /* Simple Dataspace Message. */ +#define H5SM_DTYPE_FLAG 0x0002 /* Datatype Message. */ +#define H5SM_FILL_FLAG 0x0004 /* Fill Value Message. */ +#define H5SM_PLINE_FLAG 0x0008 /* Filter pipeline message. */ +#define H5SM_ATTR_FLAG 0x0010 /* Attribute Message. */ +#define H5SM_ALL_FLAG (H5SM_SDSPACE_FLAG | H5SM_DTYPE_FLAG | H5SM_FILL_FLAG | H5SM_PLINE_FLAG | H5SM_ATTR_FLAG) + +#endif /*_H5SMpublic_H*/ + diff --git a/src/H5Spkg.h b/src/H5Spkg.h index 8764fb6..46f9201 100644 --- a/src/H5Spkg.h +++ b/src/H5Spkg.h @@ -44,6 +44,7 @@ typedef struct { unsigned rank; /* Number of dimensions */ hsize_t *size; /* Current size of the dimensions */ hsize_t *max; /* Maximum size of the dimensions */ + H5O_shared_t sh_loc; /* location of this message if shared */ } H5S_extent_t; /* diff --git a/src/H5T.c b/src/H5T.c index 12ff89f..98fd9b3 100644 --- a/src/H5T.c +++ b/src/H5T.c @@ -405,7 +405,7 @@ static H5T_t *H5T_decode(const unsigned char *buf); /* Define a macro for common code for all newly allocate datatypes */ #define H5T_INIT_TYPE_ALLOC_COMMON(TYPE) { \ - dt->oloc.addr = HADDR_UNDEF; \ + dt->sh_loc.flags = H5O_NOT_SHARED; \ dt->shared->type = TYPE; \ } @@ -3006,7 +3006,7 @@ H5T_create(H5T_class_t type, size_t size) done: if(ret_value==NULL) { - if(dt->shared != NULL) + if(dt && (dt->shared != NULL)) H5FL_FREE(H5T_shared_t, dt->shared); if(dt!=NULL) H5FL_FREE(H5T_t,dt); @@ -3105,22 +3105,22 @@ H5T_copy(const H5T_t *old_dt, H5T_copy_t method) * Return a transient type (locked or unlocked) or an opened named * type. Immutable transient types are degraded to read-only. */ - if(H5F_addr_defined(old_dt->oloc.addr)) { + if(old_dt->sh_loc.flags & H5O_COMMITTED_FLAG) { /* Check if the object is already open */ - if((reopened_fo=H5FO_opened(old_dt->oloc.file, old_dt->oloc.addr))==NULL) { + if((reopened_fo=H5FO_opened(old_dt->sh_loc.u.oloc.file, old_dt->sh_loc.u.oloc.addr))==NULL) { /* Clear any errors from H5FO_opened() */ H5E_clear_stack(NULL); /* Open named datatype again */ - if(H5O_open(&(old_dt->oloc)) < 0) + if(H5O_open(&(old_dt->sh_loc.u.oloc)) < 0) HGOTO_ERROR (H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to reopen named data type"); /* Insert opened named datatype into opened object list for the file */ - if(H5FO_insert(old_dt->oloc.file, old_dt->oloc.addr, new_dt->shared, FALSE)<0) + if(H5FO_insert(old_dt->sh_loc.u.oloc.file, old_dt->sh_loc.u.oloc.addr, new_dt->shared, FALSE)<0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, NULL, "can't insert datatype into list of open objects") /* Increment object count for the object in the top file */ - if(H5FO_top_incr(old_dt->oloc.file, old_dt->oloc.addr) < 0) + if(H5FO_top_incr(old_dt->sh_loc.u.oloc.file, old_dt->sh_loc.u.oloc.addr) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count") new_dt->shared->fo_count=1; @@ -3134,14 +3134,14 @@ H5T_copy(const H5T_t *old_dt, H5T_copy_t method) reopened_fo->fo_count++; /* Check if the object has been opened through the top file yet */ - if(H5FO_top_count(old_dt->oloc.file, old_dt->oloc.addr) == 0) { + if(H5FO_top_count(old_dt->sh_loc.u.oloc.file, old_dt->sh_loc.u.oloc.addr) == 0) { /* Open the object through this top file */ - if(H5O_open(&(old_dt->oloc)) < 0) + if(H5O_open(&(old_dt->sh_loc.u.oloc)) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to open object header") } /* end if */ /* Increment object count for the object in the top file */ - if(H5FO_top_incr(old_dt->oloc.file, old_dt->oloc.addr) < 0) + if(H5FO_top_incr(old_dt->sh_loc.u.oloc.file, old_dt->sh_loc.u.oloc.addr) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count") } new_dt->shared->state = H5T_STATE_OPEN; @@ -3177,6 +3177,7 @@ H5T_copy(const H5T_t *old_dt, H5T_copy_t method) new_dt->shared->u.compnd.memb[i].name = H5MM_xstrdup(s); tmp = H5T_copy (old_dt->shared->u.compnd.memb[i].type, method); new_dt->shared->u.compnd.memb[i].type = tmp; + HDassert(tmp != NULL); /* Apply the accumulated size change to the offset of the field */ new_dt->shared->u.compnd.memb[i].offset += accum_change; @@ -3257,28 +3258,28 @@ H5T_copy(const H5T_t *old_dt, H5T_copy_t method) break; } /* end switch */ - /* Deep copy of the symbol table entry, if there was one */ + /* Set the path name if the original type was a named type and the new + * type is also named. + */ + if(H5G_name_reset(&(new_dt->path)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, NULL, "unable to reset path") + if(new_dt->shared->state == H5T_STATE_NAMED || new_dt->shared->state == H5T_STATE_OPEN) { - if(!H5F_addr_defined(old_dt->oloc.addr)) - HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, NULL, "named dataype with invalid address") -#if defined(H5_USING_PURIFY) || !defined(NDEBUG) - /* Clear object location */ - if(H5O_loc_reset(&(new_dt->oloc)) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, NULL, "unable to reset location") - - /* Clear path name */ - if(H5G_name_reset(&(new_dt->path)) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, NULL, "unable to reset path") -#endif /* H5_USING_PURIFY */ - if(H5O_loc_copy(&(new_dt->oloc), &(old_dt->oloc), H5_COPY_DEEP) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, NULL, "unable to copy entry") if(H5G_name_copy(&(new_dt->path), &(old_dt->path), H5_COPY_DEEP) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, NULL, "unable to copy path") - } /* end if */ - else { - H5O_loc_reset(&(new_dt->oloc)); - H5G_name_reset(&(new_dt->path)); - } /* end else */ + } + + /* Copy shared location information if the new type is named or if it is + * shared in the heap. + */ + if(old_dt->sh_loc.flags & H5O_SHARED_IN_HEAP_FLAG || + new_dt->shared->state == H5T_STATE_NAMED || new_dt->shared->state == H5T_STATE_OPEN) + { + if(NULL == H5O_copy(H5O_SHARED_ID, &(old_dt->sh_loc), &(new_dt->sh_loc))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, NULL, "unable to copy shared location") + } + else + new_dt->sh_loc.flags = H5O_NOT_SHARED; /* Set return value */ ret_value=new_dt; @@ -3366,8 +3367,9 @@ H5T_alloc(void) /* Allocate & initialize new datatype info */ if(NULL == (dt = H5FL_CALLOC(H5T_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - H5O_loc_reset(&(dt->oloc)); H5G_name_reset(&(dt->path)); + dt->sh_loc.flags = H5O_NOT_SHARED; + if(NULL == (dt->shared = H5FL_CALLOC(H5T_shared_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") @@ -3416,14 +3418,15 @@ H5T_free(H5T_t *dt) * remove from the list of open objects in the file. */ if(H5T_STATE_OPEN == dt->shared->state) { - HDassert(H5F_addr_defined(dt->oloc.addr)); + HDassert(dt->sh_loc.flags & H5O_COMMITTED_FLAG); + HDassert(H5F_addr_defined(dt->sh_loc.u.oloc.addr)); /* Remove the datatype from the list of opened objects in the file */ - if(H5FO_top_decr(dt->oloc.file, dt->oloc.addr) < 0) + if(H5FO_top_decr(dt->sh_loc.u.oloc.file, dt->sh_loc.u.oloc.addr) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "can't decrement count for object") - if(H5FO_delete(dt->oloc.file, H5AC_dxpl_id, dt->oloc.addr) < 0) + if(H5FO_delete(dt->sh_loc.u.oloc.file, H5AC_dxpl_id, dt->sh_loc.u.oloc.addr) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "can't remove datatype from list of open objects") - if(H5O_close(&(dt->oloc)) < 0) + if(H5O_close(&(dt->sh_loc.u.oloc)) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to close data type object header") dt->shared->state = H5T_STATE_NAMED; } /* end if */ @@ -3463,6 +3466,7 @@ H5T_free(H5T_t *dt) } /* end switch */ /* Close the parent */ + HDassert(dt->shared->parent != dt); if(dt->shared->parent && H5T_close(dt->shared->parent) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "unable to close parent data type") @@ -3519,13 +3523,15 @@ H5T_close(H5T_t *dt) * remove from the list of open objects in the file. */ if(H5T_STATE_OPEN == dt->shared->state) { + HDassert(dt->sh_loc.flags & H5O_COMMITTED_FLAG); + /* Decrement the ref. count for this object in the top file */ - if(H5FO_top_decr(dt->oloc.file, dt->oloc.addr) < 0) + if(H5FO_top_decr(dt->sh_loc.u.oloc.file, dt->sh_loc.u.oloc.addr) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "can't decrement count for object") /* Check reference count for this object in the top file */ - if(H5FO_top_count(dt->oloc.file, dt->oloc.addr) == 0) - if(H5O_close(&(dt->oloc)) < 0) + if(H5FO_top_count(dt->sh_loc.u.oloc.file, dt->sh_loc.u.oloc.addr) == 0) + if(H5O_close(&(dt->sh_loc.u.oloc)) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to close") } /* end if */ @@ -4645,7 +4651,8 @@ H5T_oloc(H5T_t *dt) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "not a named datatype") case H5T_STATE_NAMED: case H5T_STATE_OPEN: - ret_value = &(dt->oloc); + HDassert(dt->sh_loc.flags & H5O_COMMITTED_FLAG); + ret_value = &(dt->sh_loc.u.oloc); break; } /* end switch */ @@ -5034,6 +5041,7 @@ done: } /* end H5T_is_relocatable() */ + /*------------------------------------------------------------------------- * Function: H5T_print_stats * diff --git a/src/H5Tcommit.c b/src/H5Tcommit.c index c2488f8..77ffe35 100644 --- a/src/H5Tcommit.c +++ b/src/H5Tcommit.c @@ -134,7 +134,9 @@ done: /* If the datatype was committed but couldn't be linked, we need to return it to the state it was in * before it was committed. */ if(TRUE == uncommit) { - if(type->shared->state == H5T_STATE_OPEN && H5F_addr_defined(type->oloc.addr)) { +#ifdef JAMES + // JAMES: I'm not convinced that this really works anyway + if(type->shared->state == H5T_STATE_OPEN && type->sh_loc.flags & H5O_COMMITTED_FLAG)) { /* Remove the datatype from the list of opened objects in the file */ if(H5FO_top_decr(type->oloc.file, type->oloc.addr) < 0) HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "can't decrement count for object") @@ -150,6 +152,7 @@ done: type->oloc.addr = HADDR_UNDEF; type->shared->state = old_state; } /* end if */ +#endif /* JAMES */ } /* end if */ FUNC_LEAVE_API(ret_value) @@ -228,7 +231,9 @@ static herr_t H5T_commit(H5F_t *file, H5T_t *type, hid_t dxpl_id, hid_t tcpl_id, hid_t UNUSED tapl_id) { H5P_genplist_t *tc_plist; /* Property list created */ - H5G_loc_t type_loc; /* Dataset location */ + H5O_loc_t temp_oloc; /* Temporary object header location */ + H5G_name_t temp_path; /* Temporary path */ + hbool_t loc_init=FALSE; /* Have temp_oloc and temp_path been initialized? */ size_t dtype_size; /* Size of the datatype message */ herr_t ret_value = SUCCEED; /* Return value */ @@ -260,10 +265,12 @@ H5T_commit(H5F_t *file, H5T_t *type, hid_t dxpl_id, hid_t tcpl_id, hid_t UNUSED if(H5T_set_loc(type, file, H5T_LOC_DISK) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "cannot mark datatype on disk") - /* Set up & reset datatype location */ - type_loc.oloc = &(type->oloc); - type_loc.path = &(type->path); - H5G_loc_reset(&type_loc); + /* Reset datatype location and path */ + if(H5O_loc_reset(&temp_oloc) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTRESET, FAIL, "unable to initialize location") + if(H5G_name_reset(&temp_path) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTRESET, FAIL, "unable to initialize path") + loc_init = TRUE; /* Calculate message size infomation, for creating object header */ dtype_size = H5O_mesg_size(H5O_DTYPE_ID, file, type, (size_t)0); @@ -273,22 +280,30 @@ H5T_commit(H5F_t *file, H5T_t *type, hid_t dxpl_id, hid_t tcpl_id, hid_t UNUSED * Create the object header and open it for write access. Insert the data * type message and then give the object header a name. */ - if(H5O_create(file, dxpl_id, dtype_size, &(type->oloc)) < 0) + if(H5O_create(file, dxpl_id, dtype_size, &temp_oloc) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to create datatype object header") - if(H5O_modify(&(type->oloc), H5O_DTYPE_ID, 0, H5O_FLAG_CONSTANT, H5O_UPDATE_TIME, type, dxpl_id) < 0) + if(H5O_modify(&temp_oloc, H5O_DTYPE_ID, 0, H5O_FLAG_CONSTANT | H5O_FLAG_DONTSOHM, H5O_UPDATE_TIME, type, dxpl_id) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to update type header message") + /* Copy the new object header's location into the datatype, taking ownership of it */ + if(H5O_loc_copy(&(type->sh_loc.u.oloc), &temp_oloc, H5_COPY_SHALLOW) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy datatype location") + if(H5G_name_copy(&(type->path), &temp_path, H5_COPY_SHALLOW) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy datatype location") + loc_init = FALSE; + /* Get the property list */ if(NULL == (tc_plist = H5I_object(tcpl_id))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list") + type->sh_loc.flags = H5O_COMMITTED_FLAG; type->shared->state = H5T_STATE_OPEN; type->shared->fo_count=1; /* Add datatype to the list of open objects in the file */ - if(H5FO_top_incr(type->oloc.file, type->oloc.addr) < 0) + if(H5FO_top_incr(type->sh_loc.u.oloc.file, type->sh_loc.u.oloc.addr) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, FAIL, "can't incr object ref. count") - if(H5FO_insert(type->oloc.file, type->oloc.addr, type->shared, TRUE) < 0) + if(H5FO_insert(type->sh_loc.u.oloc.file, type->sh_loc.u.oloc.addr, type->shared, TRUE) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "can't insert datatype into list of open objects") /* Mark datatype as being on memory now. Since this datatype may still be used in memory @@ -298,12 +313,17 @@ H5T_commit(H5F_t *file, H5T_t *type, hid_t dxpl_id, hid_t tcpl_id, hid_t UNUSED done: if(ret_value < 0) { - if((type->shared->state == H5T_STATE_TRANSIENT || type->shared->state == H5T_STATE_RDONLY) && H5F_addr_defined(type->oloc.addr)) { - if(H5O_close(&(type->oloc)) < 0) + if(loc_init) + { + H5O_loc_free(&temp_oloc); + H5G_name_free(&temp_path); + } + if((type->shared->state == H5T_STATE_TRANSIENT || type->shared->state == H5T_STATE_RDONLY) && (type->sh_loc.flags & H5O_COMMITTED_FLAG)) { + if(H5O_close(&(type->sh_loc.u.oloc)) < 0) HDONE_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, FAIL, "unable to release object header") - if(H5O_delete(file, dxpl_id, type->oloc.addr) < 0) + if(H5O_delete(file, dxpl_id, type->sh_loc.u.oloc.addr) < 0) HDONE_ERROR(H5E_DATATYPE, H5E_CANTDELETE, FAIL, "unable to delete object header") - type->oloc.addr = HADDR_UNDEF; + type->sh_loc.flags = H5O_NOT_SHARED; } /* end if */ } /* end if */ @@ -394,9 +414,10 @@ H5T_link(const H5T_t *type, int adjust, hid_t dxpl_id) FUNC_ENTER_NOAPI(H5T_link,FAIL) HDassert(type); + HDassert(type->sh_loc.flags & H5O_COMMITTED_FLAG); /* Adjust the link count on the named datatype */ - if((ret_value = H5O_link(&(type->oloc), adjust, dxpl_id)) < 0) + if((ret_value = H5O_link(&(type->sh_loc.u.oloc), adjust, dxpl_id)) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_LINKCOUNT, FAIL, "unable to adjust named datatype link count") done: @@ -594,11 +615,11 @@ H5T_open(H5G_loc_t *loc, hid_t dxpl_id) HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, NULL, "not found") /* Add the datatype to the list of opened objects in the file */ - if(H5FO_insert(dt->oloc.file, dt->oloc.addr, dt->shared, FALSE) < 0) + if(H5FO_insert(dt->sh_loc.u.oloc.file, dt->sh_loc.u.oloc.addr, dt->shared, FALSE) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, NULL, "can't insert datatype into list of open objects") /* Increment object count for the object in the top file */ - if(H5FO_top_incr(dt->oloc.file, dt->oloc.addr) < 0) + if(H5FO_top_incr(dt->sh_loc.u.oloc.file, dt->sh_loc.u.oloc.addr) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count") /* Mark any datatypes as being in memory now */ @@ -613,7 +634,7 @@ H5T_open(H5G_loc_t *loc, hid_t dxpl_id) #if defined(H5_USING_PURIFY) || !defined(NDEBUG) /* Clear object location */ - if(H5O_loc_reset(&(dt->oloc)) < 0) + if(H5O_loc_reset(&(dt->sh_loc.u.oloc)) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to reset location") /* Clear path name */ @@ -622,7 +643,7 @@ H5T_open(H5G_loc_t *loc, hid_t dxpl_id) #endif /* H5_USING_PURIFY */ /* Shallow copy (take ownership) of the object location object */ - if(H5O_loc_copy(&(dt->oloc), loc->oloc, H5_COPY_SHALLOW) < 0) + if(H5O_loc_copy(&(dt->sh_loc.u.oloc), loc->oloc, H5_COPY_SHALLOW) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy object location") /* Shallow copy (take ownership) of the group hier. path */ @@ -630,18 +651,19 @@ H5T_open(H5G_loc_t *loc, hid_t dxpl_id) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy path") dt->shared = shared_fo; + dt->sh_loc.flags |= H5O_COMMITTED_FLAG; shared_fo->fo_count++; /* Check if the object has been opened through the top file yet */ - if(H5FO_top_count(dt->oloc.file, dt->oloc.addr) == 0) { + if(H5FO_top_count(dt->sh_loc.u.oloc.file, dt->sh_loc.u.oloc.addr) == 0) { /* Open the object through this top file */ - if(H5O_open(&(dt->oloc)) < 0) + if(H5O_open(&(dt->sh_loc.u.oloc)) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to open object header") } /* end if */ /* Increment object count for the object in the top file */ - if(H5FO_top_incr(dt->oloc.file, dt->oloc.addr) < 0) + if(H5FO_top_incr(dt->sh_loc.u.oloc.file, dt->sh_loc.u.oloc.addr) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count") } /* end else */ @@ -653,7 +675,7 @@ done: if(shared_fo == NULL) /* Need to free shared fo */ H5FL_FREE(H5T_shared_t, dt->shared); - H5O_loc_free(&(dt->oloc)); + H5O_loc_free(&(dt->sh_loc.u.oloc)); H5G_name_free(&(dt->path)); H5FL_FREE(H5T_t, dt); @@ -698,9 +720,10 @@ H5T_open_oid(H5G_loc_t *loc, hid_t dxpl_id) /* Mark the type as named and open */ dt->shared->state = H5T_STATE_OPEN; + dt->sh_loc.flags |= H5O_COMMITTED_FLAG; /* Shallow copy (take ownership) of the object location object */ - if(H5O_loc_copy(&(dt->oloc), loc->oloc, H5_COPY_SHALLOW) < 0) + if(H5O_loc_copy(&(dt->sh_loc.u.oloc), loc->oloc, H5_COPY_SHALLOW) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy object location") /* Shallow copy (take ownership) of the group hier. path */ diff --git a/src/H5Tpkg.h b/src/H5Tpkg.h index e2c811a..16fe983 100644 --- a/src/H5Tpkg.h +++ b/src/H5Tpkg.h @@ -41,6 +41,7 @@ #include "H5Fprivate.h" /* Files */ #include "H5FLprivate.h" /* Free Lists */ #include "H5Oprivate.h" /* Object headers */ +#include "H5SMprivate.h" /* Shared Messages */ /* Other public headers needed by this file */ #include "H5Spublic.h" /* Dataspace functions */ @@ -327,8 +328,8 @@ typedef struct H5T_shared_t { struct H5T_t { H5T_shared_t *shared; /* all other information */ - H5O_loc_t oloc; /* object location information if the type is a named type */ H5G_name_t path; /* group hier. path if the type is a named type */ + H5O_shared_t sh_loc; /* shared object message if this is a shared type*/ }; /* A compound datatype member */ @@ -353,9 +354,6 @@ typedef enum H5T_sdir_t { H5T_BIT_MSB /*search msb toward lsb */ } H5T_sdir_t; -/* The native endianess of the platform */ -H5_DLLVAR H5T_order_t H5T_native_order_g; - /* * Alignment information for native types. A value of N indicates that the * data must be aligned on an address ADDR such that 0 == ADDR mod N. When diff --git a/src/H5Tprivate.h b/src/H5Tprivate.h index 2fb6b54..c676b1a 100644 --- a/src/H5Tprivate.h +++ b/src/H5Tprivate.h @@ -66,6 +66,9 @@ typedef struct H5T_conv_cb_t { /* Forward declarations for prototype arguments */ struct H5O_t; +/* The native endianess of the platform */ +H5_DLLVAR H5T_order_t H5T_native_order_g; + /* Private functions */ H5_DLL herr_t H5TN_init_interface(void); H5_DLL herr_t H5T_init(void); @@ -93,6 +96,7 @@ H5_DLL herr_t H5T_vlen_reclaim(void *elem, hid_t type_id, unsigned ndim, const h H5_DLL herr_t H5T_vlen_get_alloc_info(hid_t dxpl_id, H5T_vlen_alloc_info_t **vl_alloc_info); H5_DLL htri_t H5T_set_loc(H5T_t *dt, H5F_t *f, H5T_loc_t loc); H5_DLL htri_t H5T_is_sensible(const H5T_t *dt); +H5_DLL uint32_t H5T_hash(H5F_t * file, const H5T_t *dt); /* Reference specific functions */ H5_DLL H5R_type_t H5T_get_ref_type(const H5T_t *dt); diff --git a/src/H5err.txt b/src/H5err.txt index cb399dd..410fd52 100644 --- a/src/H5err.txt +++ b/src/H5err.txt @@ -72,6 +72,7 @@ MAJOR, H5E_RS, Reference Counted Strings MAJOR, H5E_ERROR, Error API MAJOR, H5E_SLIST, Skip Lists MAJOR, H5E_FSPACE, Free Space Manager +MAJOR, H5E_SOHM, Shared Object Header Messages MAJOR, H5E_NONE_MAJOR, No error # Sections (for grouping minor errors) diff --git a/src/H5private.h b/src/H5private.h index 599b636..0a50b56 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -265,7 +265,9 @@ /* Version #'s of the major components of the file format */ #define HDF5_SUPERBLOCK_VERSION_DEF 0 /* The default super block format */ -#define HDF5_SUPERBLOCK_VERSION_MAX 1 /* The maximum super block format */ +#define HDF5_SUPERBLOCK_VERSION_1 1 /* Version with non-default B-tree 'K' value */ +#define HDF5_SUPERBLOCK_VERSION_2 2 /* Version with implicit shared OH messages */ +#define HDF5_SUPERBLOCK_VERSION_MAX HDF5_SUPERBLOCK_VERSION_2 /* The maximum super block format */ #define HDF5_FREESPACE_VERSION 0 /* of the Free-Space Info */ #define HDF5_OBJECTDIR_VERSION 0 /* of the Object Directory format */ #define HDF5_SHAREDHEADER_VERSION 0 /* of the Shared-Header Info */ diff --git a/src/Makefile.am b/src/Makefile.am index 3f18498..428ab3d 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -65,8 +65,8 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \ H5Pgcpl.c \ H5Plapl.c H5Plcpl.c H5Pocpl.c H5Pstrcpl.c H5Ptest.c H5R.c H5RC.c \ H5RS.c H5S.c H5Sall.c H5Shyper.c H5Smpio.c H5Snone.c H5Spoint.c \ - H5Sselect.c H5Stest.c \ - H5SL.c H5ST.c H5T.c H5Tarray.c H5Tbit.c H5Tcommit.c \ + H5Sselect.c H5Stest.c H5SL.c H5SM.c H5SMbtree2.c \ + H5SMcache.c H5ST.c H5T.c H5Tarray.c H5Tbit.c H5Tcommit.c \ H5Tcompound.c H5Tconv.c H5Tcset.c H5Tenum.c H5Tfields.c H5Tfixed.c \ H5Tfloat.c H5Tinit.c H5Tnative.c H5Toffset.c H5Toh.c H5Topaque.c \ H5Torder.c \ @@ -83,7 +83,7 @@ include_HEADERS =H5public.h H5Apublic.h H5ACpublic.h \ H5FDmulti.h H5FDsec2.h H5FDstdio.h H5FDstream.h \ H5Gpublic.h H5Ipublic.h H5Lpublic.h \ H5MMpublic.h H5Opublic.h H5Ppublic.h H5Rpublic.h H5Spublic.h \ - H5Tpublic.h H5Zpublic.h H5pubconf.h hdf5.h H5api_adpt.h + H5SMpublic.h H5Tpublic.h H5Zpublic.h H5pubconf.h hdf5.h H5api_adpt.h # install libhdf5.settings in lib directory settingsdir=$(libdir) diff --git a/src/Makefile.in b/src/Makefile.in index ef11c1e..6e84c6c 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -106,13 +106,14 @@ am_libhdf5_la_OBJECTS = H5.lo H5checksum.lo H5dbg.lo H5system.lo \ H5Pfcpl.lo H5Pfmpl.lo H5Pgcpl.lo H5Plapl.lo H5Plcpl.lo \ H5Pocpl.lo H5Pstrcpl.lo H5Ptest.lo H5R.lo H5RC.lo H5RS.lo \ H5S.lo H5Sall.lo H5Shyper.lo H5Smpio.lo H5Snone.lo H5Spoint.lo \ - H5Sselect.lo H5Stest.lo H5SL.lo H5ST.lo H5T.lo H5Tarray.lo \ - H5Tbit.lo H5Tcommit.lo H5Tcompound.lo H5Tconv.lo H5Tcset.lo \ - H5Tenum.lo H5Tfields.lo H5Tfixed.lo H5Tfloat.lo H5Tinit.lo \ - H5Tnative.lo H5Toffset.lo H5Toh.lo H5Topaque.lo H5Torder.lo \ - H5Tpad.lo H5Tprecis.lo H5Tstrpad.lo H5Tvlen.lo H5TS.lo H5V.lo \ - H5Z.lo H5Zdeflate.lo H5Zfletcher32.lo H5Znbit.lo H5Zshuffle.lo \ - H5Zszip.lo H5Zscaleoffset.lo H5Ztrans.lo + H5Sselect.lo H5Stest.lo H5SL.lo H5SM.lo H5SMbtree2.lo \ + H5SMcache.lo H5ST.lo H5T.lo H5Tarray.lo H5Tbit.lo H5Tcommit.lo \ + H5Tcompound.lo H5Tconv.lo H5Tcset.lo H5Tenum.lo H5Tfields.lo \ + H5Tfixed.lo H5Tfloat.lo H5Tinit.lo H5Tnative.lo H5Toffset.lo \ + H5Toh.lo H5Topaque.lo H5Torder.lo H5Tpad.lo H5Tprecis.lo \ + H5Tstrpad.lo H5Tvlen.lo H5TS.lo H5V.lo H5Z.lo H5Zdeflate.lo \ + H5Zfletcher32.lo H5Znbit.lo H5Zshuffle.lo H5Zszip.lo \ + H5Zscaleoffset.lo H5Ztrans.lo libhdf5_la_OBJECTS = $(am_libhdf5_la_OBJECTS) PROGRAMS = $(noinst_PROGRAMS) H5detect_SOURCES = H5detect.c @@ -418,8 +419,8 @@ libhdf5_la_SOURCES = H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \ H5Pgcpl.c \ H5Plapl.c H5Plcpl.c H5Pocpl.c H5Pstrcpl.c H5Ptest.c H5R.c H5RC.c \ H5RS.c H5S.c H5Sall.c H5Shyper.c H5Smpio.c H5Snone.c H5Spoint.c \ - H5Sselect.c H5Stest.c \ - H5SL.c H5ST.c H5T.c H5Tarray.c H5Tbit.c H5Tcommit.c \ + H5Sselect.c H5Stest.c H5SL.c H5SM.c H5SMbtree2.c \ + H5SMcache.c H5ST.c H5T.c H5Tarray.c H5Tbit.c H5Tcommit.c \ H5Tcompound.c H5Tconv.c H5Tcset.c H5Tenum.c H5Tfields.c H5Tfixed.c \ H5Tfloat.c H5Tinit.c H5Tnative.c H5Toffset.c H5Toh.c H5Topaque.c \ H5Torder.c \ @@ -436,7 +437,7 @@ include_HEADERS = H5public.h H5Apublic.h H5ACpublic.h \ H5FDmulti.h H5FDsec2.h H5FDstdio.h H5FDstream.h \ H5Gpublic.h H5Ipublic.h H5Lpublic.h \ H5MMpublic.h H5Opublic.h H5Ppublic.h H5Rpublic.h H5Spublic.h \ - H5Tpublic.h H5Zpublic.h H5pubconf.h hdf5.h H5api_adpt.h + H5SMpublic.h H5Tpublic.h H5Zpublic.h H5pubconf.h hdf5.h H5api_adpt.h # install libhdf5.settings in lib directory @@ -687,6 +688,9 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5RS.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5S.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5SL.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5SM.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5SMbtree2.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5SMcache.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5ST.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Sall.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Shyper.Plo@am__quote@ diff --git a/src/hdf5.h b/src/hdf5.h index a3ae138..0b973f9 100644 --- a/src/hdf5.h +++ b/src/hdf5.h @@ -35,6 +35,7 @@ #include "H5Ppublic.h" /* Property lists */ #include "H5Rpublic.h" /* References */ #include "H5Spublic.h" /* Dataspaces */ +#include "H5SMpublic.h" /* Shared Object Header Messages */ #include "H5Tpublic.h" /* Datatypes */ #include "H5Zpublic.h" /* Data filters */ diff --git a/test/Makefile.am b/test/Makefile.am index 450d28e..ecbce02 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -121,7 +121,7 @@ CHECK_CLEANFILES+=cmpd_dset.h5 compact_dataset.h5 dataset.h5 extend.h5 istore.h5 # Sources for testhdf5 executable testhdf5_SOURCES=testhdf5.c tarray.c tattr.c tchecksum.c tconfig.c tfile.c \ tgenprop.c th5o.c th5s.c theap.c tid.c titerate.c tmeta.c tmisc.c ttime.c \ - trefer.c trefstr.c tselect.c tskiplist.c ttst.c tunicode.c tvltypes.c \ + trefer.c trefstr.c tselect.c tsohm.c tskiplist.c ttst.c tunicode.c tvltypes.c \ tvlstr.c include $(top_srcdir)/config/conclude.am diff --git a/test/Makefile.in b/test/Makefile.in index 8671a4c..b984914 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -297,8 +297,9 @@ am_testhdf5_OBJECTS = testhdf5.$(OBJEXT) tarray.$(OBJEXT) \ th5s.$(OBJEXT) theap.$(OBJEXT) tid.$(OBJEXT) \ titerate.$(OBJEXT) tmeta.$(OBJEXT) tmisc.$(OBJEXT) \ ttime.$(OBJEXT) trefer.$(OBJEXT) trefstr.$(OBJEXT) \ - tselect.$(OBJEXT) tskiplist.$(OBJEXT) ttst.$(OBJEXT) \ - tunicode.$(OBJEXT) tvltypes.$(OBJEXT) tvlstr.$(OBJEXT) + tselect.$(OBJEXT) tsohm.$(OBJEXT) tskiplist.$(OBJEXT) \ + ttst.$(OBJEXT) tunicode.$(OBJEXT) tvltypes.$(OBJEXT) \ + tvlstr.$(OBJEXT) testhdf5_OBJECTS = $(am_testhdf5_OBJECTS) testhdf5_LDADD = $(LDADD) testhdf5_DEPENDENCIES = libh5test.la $(am__DEPENDENCIES_1) @@ -668,7 +669,7 @@ ttsafe_SOURCES = ttsafe.c ttsafe_dcreate.c ttsafe_error.c ttsafe_cancel.c # Sources for testhdf5 executable testhdf5_SOURCES = testhdf5.c tarray.c tattr.c tchecksum.c tconfig.c tfile.c \ tgenprop.c th5o.c th5s.c theap.c tid.c titerate.c tmeta.c tmisc.c ttime.c \ - trefer.c trefstr.c tselect.c tskiplist.c ttst.c tunicode.c tvltypes.c \ + trefer.c trefstr.c tselect.c tsohm.c tskiplist.c ttst.c tunicode.c tvltypes.c \ tvlstr.c @@ -990,6 +991,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trefstr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tselect.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tskiplist.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsohm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ttime.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ttsafe.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ttsafe_acreate.Po@am__quote@ diff --git a/test/h5test.c b/test/h5test.c index 93f992e..bae9da2 100644 --- a/test/h5test.c +++ b/test/h5test.c @@ -86,8 +86,9 @@ MPI_Info h5_io_info_g=MPI_INFO_NULL;/* MPI INFO object for IO */ * g: Global heap * l: local heap (object names) * o: object headers + * h: shared object header message structures */ -static const char *multi_letters = "msbrglo"; +static const char *multi_letters = "msbrgloh"; static herr_t h5_errors(void *client_data); @@ -692,7 +693,6 @@ h5_show_hostname(void) WSACleanup(); #endif } - #ifdef H5_HAVE_PARALLEL /* diff --git a/test/objcopy.c b/test/objcopy.c index 507c881..3373bec 100755 --- a/test/objcopy.c +++ b/test/objcopy.c @@ -30,6 +30,9 @@ #define H5S_TESTING #include "H5Spkg.h" /* Dataspaces */ +#include "H5Dprivate.h" /* Datasets (for EFL property name) */ + + const char *FILENAME[] = { "objcopy_src", "objcopy_dst", @@ -104,7 +107,7 @@ compare_data(hid_t parent1, hid_t parent2, hid_t pid, hid_t tid, size_t nelmts, static int compare_datasets(hid_t did, hid_t did2, hid_t pid, const void *wbuf); static int -compare_groups(hid_t gid, hid_t gid2, hid_t pid, int depth); +compare_groups(hid_t gid, hid_t gid2, hid_t pid, int depth, unsigned copy_flags); /*------------------------------------------------------------------------- @@ -800,7 +803,7 @@ compare_data(hid_t parent1, hid_t parent2, hid_t pid, hid_t tid, size_t nelmts, break; case H5G_GROUP: - if(compare_groups(obj1_id, obj2_id, pid, -1) != TRUE) TEST_ERROR + if(compare_groups(obj1_id, obj2_id, pid, -1, 0) != TRUE) TEST_ERROR break; case H5G_TYPE: @@ -844,7 +847,7 @@ compare_data(hid_t parent1, hid_t parent2, hid_t pid, hid_t tid, size_t nelmts, break; case H5G_GROUP: - if(compare_groups(obj1_id, obj2_id, pid, -1) != TRUE) TEST_ERROR + if(compare_groups(obj1_id, obj2_id, pid, -1, 0) != TRUE) TEST_ERROR break; case H5G_TYPE: @@ -906,6 +909,7 @@ compare_datasets(hid_t did, hid_t did2, hid_t pid, const void *wbuf) size_t elmt_size; /* Size of datatype */ htri_t is_committed; /* If the datatype is committed */ htri_t is_committed2; /* If the datatype is committed */ + int ext_count; /* Number of external files in plist */ int nfilters; /* Number of filters applied to dataset */ hssize_t nelmts; /* # of elements in dataspace */ void *rbuf = NULL; /* Buffer for reading raw data */ @@ -956,7 +960,43 @@ compare_datasets(hid_t did, hid_t did2, hid_t pid, const void *wbuf) /* Open the dataset creation property list for the destination dataset */ if((dcpl2 = H5Dget_create_plist(did2)) < 0) TEST_ERROR - /* Compare the dataset creation property lists */ + /* If external file storage is being used, the value stored in the + * dcpl will be a heap ID, which is not guaranteed to be the same in + * source and destination files. + * Instead, compare the actual external file values and then + * delete this property from the dcpls before comparing them. + */ + if((ext_count = H5Pget_external_count(dcpl)) < 0) TEST_ERROR + + if(ext_count > 0) + { + unsigned x; /* Counter varaible */ + char name1[NAME_BUF_SIZE]; + char name2[NAME_BUF_SIZE]; + off_t offset1=0; + off_t offset2=0; + hsize_t size1=0; + hsize_t size2=0; + + if(H5Pget_external_count(dcpl2) != ext_count) TEST_ERROR + + /* Ensure that all external file information is the same */ + for(x=0; x < (unsigned) ext_count; ++x) + { + if(H5Pget_external(dcpl, x, NAME_BUF_SIZE, name1, &offset1, &size1) < 0) TEST_ERROR + if(H5Pget_external(dcpl2, x, NAME_BUF_SIZE, name2, &offset2, &size2) < 0) TEST_ERROR + + if(offset1 != offset2) TEST_ERROR + if(size1 != size2) TEST_ERROR + if(strcmp(name1, name2) != 0) TEST_ERROR + } + + /* Remove external file information from the dcpls */ + if(H5Premove(dcpl, H5D_CRT_EXT_FILE_LIST_NAME) < 0) TEST_ERROR + if(H5Premove(dcpl2, H5D_CRT_EXT_FILE_LIST_NAME) < 0) TEST_ERROR + } + + /* Compare the rest of the dataset creation property lists */ if(H5Pequal(dcpl, dcpl2) != TRUE) TEST_ERROR /* Get the number of filters on dataset */ @@ -1068,7 +1108,7 @@ error: *------------------------------------------------------------------------- */ static int -compare_groups(hid_t gid, hid_t gid2, hid_t pid, int depth) +compare_groups(hid_t gid, hid_t gid2, hid_t pid, int depth, unsigned copy_flags) { hsize_t num_objs; /* Number of objects in group */ hsize_t num_objs2; /* Number of objects in group */ @@ -1122,8 +1162,18 @@ compare_groups(hid_t gid, hid_t gid2, hid_t pid, int depth) if(objstat.type != objstat2.type) TEST_ERROR if(objstat.type != H5G_LINK && objstat.type != H5G_UDLINK) { if(objstat.nlink != objstat2.nlink) TEST_ERROR - if(objstat.ohdr.nmesgs != objstat2.ohdr.nmesgs) TEST_ERROR - if(objstat.ohdr.nchunks != objstat2.ohdr.nchunks) TEST_ERROR + + /* If NULL messages are preserved, the number of messages + * should be the same in the destination. + * Otherwise, it should simply be true that the number + * of messages hasn't increased. + */ + if(H5O_COPY_PRESERVE_NULL_FLAG & copy_flags) { + if(objstat.ohdr.nmesgs != objstat2.ohdr.nmesgs); + else + if(objstat.ohdr.nmesgs < objstat2.ohdr.nmesgs) TEST_ERROR + } + if(1 != objstat2.ohdr.nchunks) TEST_ERROR } /* end if */ /* Get link info */ @@ -1156,7 +1206,7 @@ compare_groups(hid_t gid, hid_t gid2, hid_t pid, int depth) if((oid2 = H5Gopen(gid2, objname2)) < 0) TEST_ERROR /* Compare groups */ - if(compare_groups(oid, oid2, pid, depth - 1) != TRUE) TEST_ERROR + if(compare_groups(oid, oid2, pid, depth - 1, copy_flags) != TRUE) TEST_ERROR /* Close groups */ if(H5Gclose(oid) < 0) TEST_ERROR @@ -2600,15 +2650,8 @@ test_copy_dataset_external(hid_t fapl) /* create destination file */ if((fid_dst = H5Fcreate(dst_filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR -/* Don't change the address in the destination file for this test, it causes the - * external file list's heap to be at a different location and generates a false - * negative for this test. The test is _slightly_ weaker because of this, but - * I can't see any easy way around it. -QAK - */ -#if 0 /* Create an uncopied object in destination file so that addresses in source and destination files aren't the same */ if(H5Gclose(H5Gcreate(fid_dst, NAME_GROUP_UNCOPIED, (size_t)0)) < 0) TEST_ERROR -#endif /* 0 */ /* copy the dataset from SRC to DST */ if(H5Ocopy(fid_src, NAME_DATASET_EXTERNAL, fid_dst, NAME_DATASET_EXTERNAL, H5P_DEFAULT, H5P_DEFAULT) < 0) TEST_ERROR @@ -2878,7 +2921,7 @@ test_copy_dataset_named_dtype_hier(hid_t fapl) if((gid2 = H5Gopen(fid_dst, NAME_GROUP_TOP)) < 0) TEST_ERROR /* Check if the groups are equal */ - if(compare_groups(gid, gid2, H5P_DEFAULT, -1) != TRUE) TEST_ERROR + if(compare_groups(gid, gid2, H5P_DEFAULT, -1, 0) != TRUE) TEST_ERROR /* close the destination group */ if(H5Gclose(gid2) < 0) TEST_ERROR @@ -3017,7 +3060,7 @@ test_copy_dataset_named_dtype_hier_outside(hid_t fapl) if((gid2 = H5Gopen(fid_dst, NAME_GROUP_TOP)) < 0) TEST_ERROR /* Check if the groups are equal */ - if(compare_groups(gid, gid2, H5P_DEFAULT, -1) != TRUE) TEST_ERROR + if(compare_groups(gid, gid2, H5P_DEFAULT, -1, 0) != TRUE) TEST_ERROR /* close the destination group */ if(H5Gclose(gid2) < 0) TEST_ERROR @@ -3151,7 +3194,7 @@ test_copy_dataset_multi_ohdr_chunks(hid_t fapl) if((gid2 = H5Gopen(fid_dst, NAME_GROUP_TOP)) < 0) TEST_ERROR /* Check if the groups are equal */ - if(compare_groups(gid, gid2, H5P_DEFAULT, -1) != TRUE) TEST_ERROR + if(compare_groups(gid, gid2, H5P_DEFAULT, -1, 0) != TRUE) TEST_ERROR /* close the destination group */ if(H5Gclose(gid2) < 0) TEST_ERROR @@ -3292,7 +3335,7 @@ test_copy_dataset_attr_named_dtype(hid_t fapl) if((gid2 = H5Gopen(fid_dst, NAME_GROUP_TOP)) < 0) TEST_ERROR /* Check if the groups are equal */ - if(compare_groups(gid, gid2, H5P_DEFAULT, -1) != TRUE) TEST_ERROR + if(compare_groups(gid, gid2, H5P_DEFAULT, -1, 0) != TRUE) TEST_ERROR /* close the destination group */ if(H5Gclose(gid2) < 0) TEST_ERROR @@ -4061,7 +4104,7 @@ test_copy_group_empty(hid_t fapl) if((gid2 = H5Gopen(fid_dst, NAME_GROUP_EMPTY)) < 0) TEST_ERROR /* Check if the groups are equal */ - if(compare_groups(gid, gid2, H5P_DEFAULT, -1) != TRUE) TEST_ERROR + if(compare_groups(gid, gid2, H5P_DEFAULT, -1, 0) != TRUE) TEST_ERROR /* close the destination group */ if(H5Gclose(gid2) < 0) TEST_ERROR @@ -4192,7 +4235,7 @@ test_copy_group(hid_t fapl) if((gid2 = H5Gopen(fid_dst, NAME_GROUP_TOP)) < 0) TEST_ERROR /* Check if the groups are equal */ - if(compare_groups(gid, gid2, H5P_DEFAULT, -1) != TRUE) TEST_ERROR + if(compare_groups(gid, gid2, H5P_DEFAULT, -1, 0) != TRUE) TEST_ERROR /* close the destination group */ if(H5Gclose(gid2) < 0) TEST_ERROR @@ -4325,7 +4368,7 @@ test_copy_root_group(hid_t fapl) if((gid2 = H5Gopen(fid_dst, "/root_from_src")) < 0) TEST_ERROR /* Check if the groups are equal */ - if(compare_groups(gid, gid2, H5P_DEFAULT, -1) != TRUE) TEST_ERROR + if(compare_groups(gid, gid2, H5P_DEFAULT, -1, 0) != TRUE) TEST_ERROR /* close the destination group */ if(H5Gclose(gid2) < 0) TEST_ERROR @@ -4467,7 +4510,7 @@ test_copy_group_deep(hid_t fapl) if((gid2 = H5Gopen(fid_dst, NAME_GROUP_TOP)) < 0) TEST_ERROR /* Check if the groups are equal */ - if(compare_groups(gid, gid2, H5P_DEFAULT, -1) != TRUE) TEST_ERROR + if(compare_groups(gid, gid2, H5P_DEFAULT, -1, 0) != TRUE) TEST_ERROR /* close the destination group */ if(H5Gclose(gid2) < 0) TEST_ERROR @@ -4578,7 +4621,7 @@ test_copy_group_loop(hid_t fapl) if((gid2 = H5Gopen(fid_dst, NAME_GROUP_TOP)) < 0) TEST_ERROR /* Check if the groups are equal */ - if(compare_groups(gid, gid2, H5P_DEFAULT, -1) != TRUE) TEST_ERROR + if(compare_groups(gid, gid2, H5P_DEFAULT, -1, 0) != TRUE) TEST_ERROR /* close the destination group */ if(H5Gclose(gid2) < 0) TEST_ERROR @@ -4707,7 +4750,7 @@ test_copy_group_wide_loop(hid_t fapl) if((gid2 = H5Gopen(fid_dst, NAME_GROUP_TOP)) < 0) TEST_ERROR /* Check if the groups are equal */ - if(compare_groups(gid, gid2, H5P_DEFAULT, -1) != TRUE) TEST_ERROR + if(compare_groups(gid, gid2, H5P_DEFAULT, -1, 0) != TRUE) TEST_ERROR /* close the destination group */ if(H5Gclose(gid2) < 0) TEST_ERROR @@ -4843,7 +4886,7 @@ test_copy_group_links(hid_t fapl) if((gid2 = H5Gopen(fid_dst, NAME_GROUP_LINK)) < 0) TEST_ERROR /* Check if the groups are equal */ - if(compare_groups(gid, gid2, H5P_DEFAULT, -1) != TRUE) TEST_ERROR + if(compare_groups(gid, gid2, H5P_DEFAULT, -1, 0) != TRUE) TEST_ERROR /* close the destination group */ if(H5Gclose(gid2) < 0) TEST_ERROR @@ -6857,7 +6900,7 @@ test_copy_option(hid_t fapl, unsigned flag, hbool_t crt_intermediate_grp, const /* open the destination group */ if((gid2 = H5Gopen(fid_dst, NAME_GROUP_LINK)) < 0) TEST_ERROR - } else if(flag & H5O_COPY_WITHOUT_ATTR_FLAG) { + } else if(flag & (H5O_COPY_WITHOUT_ATTR_FLAG | H5O_COPY_PRESERVE_NULL_FLAG)) { if(H5Ocopy(fid_src, NAME_GROUP_TOP, fid_dst, NAME_GROUP_TOP, pid, H5P_DEFAULT) < 0) TEST_ERROR /* open the group for copy */ @@ -6890,7 +6933,7 @@ test_copy_option(hid_t fapl, unsigned flag, hbool_t crt_intermediate_grp, const } /* end else */ /* Check if the groups are equal */ - if(compare_groups(gid, gid2, pid, depth) != TRUE) TEST_ERROR + if(compare_groups(gid, gid2, pid, depth, flag) != TRUE) TEST_ERROR if(H5Gclose(gid2) < 0) TEST_ERROR if(H5Gclose(gid) < 0) TEST_ERROR @@ -7026,6 +7069,7 @@ main(void) nerrors += test_copy_option(my_fapl, H5O_COPY_EXPAND_SOFT_LINK_FLAG, FALSE, "H5Ocopy(): expand soft link"); nerrors += test_copy_option(my_fapl, H5O_COPY_SHALLOW_HIERARCHY_FLAG, FALSE, "H5Ocopy(): shallow group copy"); nerrors += test_copy_option(my_fapl, H5O_COPY_EXPAND_REFERENCE_FLAG, FALSE, "H5Ocopy(): expand object reference"); + nerrors += test_copy_option(my_fapl, H5O_COPY_PRESERVE_NULL_FLAG, FALSE, "H5Gcopy(): preserve NULL messages"); /* TODO: not implemented nerrors += test_copy_option(my_fapl, H5O_COPY_EXPAND_EXT_LINK_FLAG, FALSE, "H5Ocopy: expand external link"); diff --git a/test/tattr.c b/test/tattr.c index cca4cbf..8a1370e 100644 --- a/test/tattr.c +++ b/test/tattr.c @@ -20,6 +20,9 @@ * *************************************************************/ +/* JAMES: try writing a second value to an existing shared attribute. + * Does modifying attributes work? */ + #include "testhdf5.h" #include "h5test.h" #include "hdf5.h" @@ -92,6 +95,7 @@ float attr_data5=(float)-5.123; /* Test data for 5th attribute */ herr_t attr_op1(hid_t loc_id, const char *name, void *op_data); + /**************************************************************** ** ** test_attr_basic_write(): Test basic H5A (attribute) code. @@ -216,7 +220,6 @@ test_attr_basic_write(hid_t fapl) ret=H5Aclose(attr); CHECK(ret, FAIL, "H5Aclose"); - /* Open the second attribute again */ attr2=H5Aopen_name(dataset, ATTR1A_NAME); CHECK(attr, FAIL, "H5Aopen_name"); @@ -243,7 +246,7 @@ test_attr_basic_write(hid_t fapl) /* Verify values read in */ for(i=0; i= 0); + CHECK(ret, FAIL, "H5Gunlink"); /* Close objects */ ret = H5Dclose(did); diff --git a/tools/h5dump/h5dumpgentest.c b/tools/h5dump/h5dumpgentest.c index 463f718..669445c 100644 --- a/tools/h5dump/h5dumpgentest.c +++ b/tools/h5dump/h5dumpgentest.c @@ -2999,7 +2999,7 @@ void gent_family(void) H5Pclose(fapl); } -static const char *multi_letters = "msbrglo"; +static const char *multi_letters = "msbrgloh"; static void gent_multi(void) -- cgit v0.12