summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2008-12-18 14:16:03 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2008-12-18 14:16:03 (GMT)
commit26a82c35750b688cb9a5c21bc27e272416027622 (patch)
tree57c03b720dc5e8273f147c7dd80806b8aa12b15b /src
parent8625a8bd6be9a3c89b5195f36df14bb66b26b2c7 (diff)
parente77303f48370403e04b4185aa54fb6417e1e52fa (diff)
downloadhdf5-26a82c35750b688cb9a5c21bc27e272416027622.zip
hdf5-26a82c35750b688cb9a5c21bc27e272416027622.tar.gz
hdf5-26a82c35750b688cb9a5c21bc27e272416027622.tar.bz2
[svn-r16206] Creating a branch of hdf5/trunk for working on using new data structures for indexing chunks
Diffstat (limited to 'src')
-rw-r--r--src/H5.c14
-rw-r--r--src/H5A.c410
-rw-r--r--src/H5AC.c163
-rw-r--r--src/H5ACpkg.h9
-rw-r--r--src/H5ACprivate.h14
-rw-r--r--src/H5ACpublic.h79
-rw-r--r--src/H5Abtree2.c4
-rw-r--r--src/H5Adense.c63
-rw-r--r--src/H5Adeprec.c6
-rw-r--r--src/H5Aint.c132
-rw-r--r--src/H5Apkg.h24
-rw-r--r--src/H5Apublic.h4
-rw-r--r--src/H5Atest.c2
-rw-r--r--src/H5B.c819
-rw-r--r--src/H5B2.c36
-rw-r--r--src/H5B2cache.c113
-rw-r--r--src/H5B2int.c125
-rw-r--r--src/H5B2pkg.h10
-rw-r--r--src/H5B2private.h2
-rw-r--r--src/H5Bcache.c53
-rw-r--r--src/H5Bdbg.c284
-rw-r--r--src/H5Bpkg.h12
-rw-r--r--src/H5Bprivate.h65
-rw-r--r--src/H5Bpublic.h11
-rw-r--r--src/H5C.c1309
-rw-r--r--src/H5CS.c2
-rw-r--r--src/H5Cpkg.h70
-rw-r--r--src/H5Cprivate.h157
-rw-r--r--src/H5Cpublic.h6
-rw-r--r--src/H5D.c231
-rw-r--r--src/H5Dbtree.c1385
-rw-r--r--src/H5Dchunk.c4504
-rw-r--r--src/H5Dcompact.c170
-rw-r--r--src/H5Dcontig.c580
-rw-r--r--src/H5Ddbg.c2
-rw-r--r--src/H5Ddeprec.c22
-rw-r--r--src/H5Defl.c274
-rw-r--r--src/H5Dfill.c44
-rw-r--r--src/H5Dint.c896
-rw-r--r--src/H5Dio.c3120
-rw-r--r--src/H5Distore.c4039
-rw-r--r--src/H5Dmpio.c2748
-rw-r--r--src/H5Doh.c34
-rw-r--r--src/H5Dpkg.h654
-rw-r--r--src/H5Dprivate.h40
-rw-r--r--src/H5Dpublic.h12
-rw-r--r--src/H5Dscatgath.c900
-rw-r--r--src/H5Dselect.c756
-rw-r--r--src/H5Dtest.c22
-rw-r--r--src/H5E.c96
-rw-r--r--src/H5EA.c969
-rw-r--r--src/H5EAcache.c1883
-rw-r--r--src/H5EAdbg.c440
-rw-r--r--src/H5EAdblkpage.c313
-rw-r--r--src/H5EAdblock.c465
-rw-r--r--src/H5EAhdr.c720
-rw-r--r--src/H5EAiblock.c468
-rw-r--r--src/H5EAint.c81
-rw-r--r--src/H5EApkg.h698
-rw-r--r--src/H5EAprivate.h122
-rw-r--r--src/H5EAsblock.c428
-rw-r--r--src/H5EAstat.c116
-rw-r--r--src/H5EAtest.c325
-rw-r--r--src/H5Edefin.h1
-rw-r--r--src/H5Edeprec.c4
-rw-r--r--src/H5Einit.h293
-rw-r--r--src/H5Eint.c135
-rw-r--r--src/H5Eprivate.h10
-rw-r--r--src/H5Epubgen.h2
-rw-r--r--src/H5Epublic.h2
-rw-r--r--src/H5Eterm.h1
-rw-r--r--src/H5F.c1411
-rw-r--r--src/H5FD.c2536
-rw-r--r--src/H5FDcore.c177
-rw-r--r--src/H5FDdirect.c91
-rw-r--r--src/H5FDdirect.h4
-rw-r--r--src/H5FDfamily.c256
-rw-r--r--src/H5FDint.c297
-rw-r--r--src/H5FDlog.c95
-rw-r--r--src/H5FDmpi.h9
-rw-r--r--src/H5FDmpio.c434
-rw-r--r--src/H5FDmpio.h2
-rw-r--r--src/H5FDmpiposix.c37
-rw-r--r--src/H5FDmpiposix.h3
-rw-r--r--src/H5FDmulti.c179
-rw-r--r--src/H5FDpkg.h63
-rw-r--r--src/H5FDprivate.h29
-rw-r--r--src/H5FDpublic.h71
-rw-r--r--src/H5FDsec2.c187
-rw-r--r--src/H5FDspace.c367
-rw-r--r--src/H5FDstdio.c97
-rw-r--r--src/H5FDstream.c1170
-rw-r--r--src/H5FDstream.h101
-rw-r--r--src/H5FDwindows.c181
-rw-r--r--src/H5FL.c52
-rw-r--r--src/H5FLprivate.h4
-rw-r--r--src/H5FO.c62
-rw-r--r--src/H5FS.c471
-rw-r--r--src/H5FScache.c156
-rw-r--r--src/H5FSdbg.c25
-rw-r--r--src/H5FSpkg.h46
-rw-r--r--src/H5FSprivate.h36
-rw-r--r--src/H5FSsection.c1213
-rw-r--r--src/H5FSstat.c101
-rw-r--r--src/H5FStest.c154
-rw-r--r--src/H5Faccum.c656
-rw-r--r--src/H5Fdbg.c6
-rw-r--r--src/H5Ffake.c4
-rw-r--r--src/H5Fio.c165
-rw-r--r--src/H5Fmount.c168
-rw-r--r--src/H5Fmpi.c181
-rw-r--r--src/H5Fpkg.h101
-rw-r--r--src/H5Fprivate.h148
-rw-r--r--src/H5Fpublic.h10
-rw-r--r--src/H5Fquery.c663
-rw-r--r--src/H5Fsfile.c2
-rw-r--r--src/H5Fsuper.c242
-rw-r--r--src/H5Ftest.c2
-rw-r--r--src/H5G.c582
-rw-r--r--src/H5Gbtree2.c2
-rw-r--r--src/H5Gcache.c470
-rw-r--r--src/H5Gcompact.c21
-rw-r--r--src/H5Gdense.c69
-rw-r--r--src/H5Gdeprec.c30
-rw-r--r--src/H5Gent.c2
-rw-r--r--src/H5Glink.c43
-rw-r--r--src/H5Gloc.c10
-rw-r--r--src/H5Gname.c318
-rw-r--r--src/H5Gnode.c640
-rw-r--r--src/H5Gobj.c179
-rw-r--r--src/H5Goh.c13
-rw-r--r--src/H5Gpkg.h64
-rw-r--r--src/H5Gprivate.h15
-rw-r--r--src/H5Gpublic.h3
-rw-r--r--src/H5Gstab.c63
-rw-r--r--src/H5Gtest.c18
-rw-r--r--src/H5Gtraverse.c132
-rw-r--r--src/H5HF.c18
-rw-r--r--src/H5HFcache.c102
-rw-r--r--src/H5HFdbg.c107
-rw-r--r--src/H5HFdblock.c35
-rw-r--r--src/H5HFdtable.c8
-rw-r--r--src/H5HFhdr.c23
-rw-r--r--src/H5HFhuge.c10
-rw-r--r--src/H5HFiblock.c45
-rw-r--r--src/H5HFiter.c4
-rw-r--r--src/H5HFman.c2
-rw-r--r--src/H5HFpkg.h18
-rw-r--r--src/H5HFsection.c106
-rw-r--r--src/H5HFspace.c64
-rw-r--r--src/H5HFstat.c11
-rw-r--r--src/H5HG.c740
-rw-r--r--src/H5HGcache.c442
-rw-r--r--src/H5HGdbg.c2
-rw-r--r--src/H5HGpkg.h56
-rw-r--r--src/H5HGprivate.h6
-rw-r--r--src/H5HL.c727
-rw-r--r--src/H5HLcache.c478
-rw-r--r--src/H5HLdbg.c4
-rw-r--r--src/H5HLpkg.h21
-rw-r--r--src/H5HLprivate.h3
-rw-r--r--src/H5HP.c40
-rw-r--r--src/H5I.c1057
-rw-r--r--src/H5Iprivate.h14
-rw-r--r--src/H5Ipublic.h1
-rw-r--r--src/H5L.c160
-rw-r--r--src/H5Lexternal.c246
-rw-r--r--src/H5Lprivate.h5
-rw-r--r--src/H5Lpublic.h7
-rw-r--r--src/H5MF.c954
-rw-r--r--src/H5MFaggr.c568
-rw-r--r--src/H5MFdbg.c246
-rw-r--r--src/H5MFpkg.h175
-rw-r--r--src/H5MFprivate.h57
-rw-r--r--src/H5MFsection.c531
-rw-r--r--src/H5MM.c16
-rw-r--r--src/H5MP.c10
-rw-r--r--src/H5O.c520
-rw-r--r--src/H5Oainfo.c11
-rw-r--r--src/H5Oalloc.c241
-rw-r--r--src/H5Oattr.c315
-rw-r--r--src/H5Oattribute.c288
-rw-r--r--src/H5Obogus.c5
-rw-r--r--src/H5Obtreek.c17
-rw-r--r--src/H5Ocache.c100
-rw-r--r--src/H5Ocont.c7
-rw-r--r--src/H5Ocopy.c43
-rw-r--r--src/H5Odbg.c10
-rw-r--r--src/H5Odrvinfo.c19
-rw-r--r--src/H5Odtype.c143
-rw-r--r--src/H5Oefl.c27
-rw-r--r--src/H5Ofill.c54
-rw-r--r--src/H5Oginfo.c9
-rw-r--r--src/H5Olayout.c73
-rw-r--r--src/H5Olinfo.c20
-rw-r--r--src/H5Olink.c25
-rw-r--r--src/H5Omessage.c80
-rw-r--r--src/H5Omtime.c46
-rw-r--r--src/H5Oname.c58
-rw-r--r--src/H5Opkg.h54
-rw-r--r--src/H5Opline.c11
-rw-r--r--src/H5Oprivate.h37
-rw-r--r--src/H5Opublic.h25
-rw-r--r--src/H5Orefcount.c9
-rw-r--r--src/H5Osdspace.c13
-rw-r--r--src/H5Oshared.c19
-rw-r--r--src/H5Oshared.h19
-rw-r--r--src/H5Oshmesg.c9
-rw-r--r--src/H5Ostab.c47
-rw-r--r--src/H5Otest.c10
-rw-r--r--src/H5Ounknown.c2
-rw-r--r--src/H5P.c106
-rw-r--r--src/H5Pdapl.c273
-rw-r--r--src/H5Pdcpl.c142
-rw-r--r--src/H5Pdeprec.c4
-rw-r--r--src/H5Pdxpl.c16
-rw-r--r--src/H5Pfapl.c239
-rw-r--r--src/H5Pfcpl.c12
-rw-r--r--src/H5Pint.c258
-rw-r--r--src/H5Plapl.c230
-rw-r--r--src/H5Pprivate.h8
-rw-r--r--src/H5Ppublic.h24
-rw-r--r--src/H5Ptest.c24
-rw-r--r--src/H5R.c46
-rw-r--r--src/H5RC.c18
-rw-r--r--src/H5RS.c14
-rw-r--r--src/H5Rpublic.h2
-rw-r--r--src/H5S.c356
-rw-r--r--src/H5SL.c529
-rw-r--r--src/H5SLprivate.h5
-rwxr-xr-xsrc/H5SM.c121
-rw-r--r--src/H5SMcache.c57
-rwxr-xr-xsrc/H5SMpkg.h11
-rw-r--r--src/H5SMtest.c2
-rw-r--r--src/H5ST.c63
-rw-r--r--src/H5Sall.c110
-rw-r--r--src/H5Shyper.c332
-rw-r--r--src/H5Smpio.c16
-rw-r--r--src/H5Snone.c100
-rw-r--r--src/H5Spkg.h14
-rw-r--r--src/H5Spoint.c404
-rw-r--r--src/H5Sprivate.h57
-rw-r--r--src/H5Spublic.h15
-rw-r--r--src/H5Sselect.c473
-rw-r--r--src/H5Stest.c12
-rw-r--r--src/H5T.c637
-rw-r--r--src/H5TS.c53
-rw-r--r--src/H5TSprivate.h1
-rw-r--r--src/H5Tarray.c106
-rw-r--r--src/H5Tbit.c145
-rw-r--r--src/H5Tcommit.c110
-rw-r--r--src/H5Tcompound.c246
-rw-r--r--src/H5Tconv.c2267
-rw-r--r--src/H5Tdeprec.c2
-rw-r--r--src/H5Tenum.c2
-rw-r--r--src/H5Tfields.c125
-rw-r--r--src/H5Tnative.c8
-rw-r--r--src/H5Toh.c7
-rw-r--r--src/H5Tpkg.h48
-rw-r--r--src/H5Tprivate.h34
-rw-r--r--src/H5Tpublic.h2
-rw-r--r--src/H5Tvisit.c2
-rw-r--r--src/H5Tvlen.c271
-rw-r--r--src/H5V.c31
-rw-r--r--src/H5Vprivate.h96
-rw-r--r--src/H5Z.c62
-rw-r--r--src/H5Znbit.c10
-rw-r--r--src/H5Zprivate.h3
-rw-r--r--src/H5Zpublic.h19
-rw-r--r--src/H5Zscaleoffset.c1
-rw-r--r--src/H5Zshuffle.c2
-rw-r--r--src/H5Zszip.c7
-rw-r--r--src/H5Ztrans.c136
-rw-r--r--src/H5checksum.c45
-rw-r--r--src/H5config.h.in39
-rw-r--r--src/H5detect.c143
-rw-r--r--src/H5err.txt1
-rw-r--r--src/H5private.h1284
-rw-r--r--src/H5public.h8
-rw-r--r--src/H5system.c103
-rw-r--r--src/H5trace.c64
-rw-r--r--src/H5version.h4
-rw-r--r--src/H5win32defs.h69
-rwxr-xr-xsrc/Makefile.am31
-rw-r--r--src/Makefile.in227
-rw-r--r--src/hdf5.h1
-rw-r--r--src/libhdf5.settings.in76
287 files changed, 41542 insertions, 25706 deletions
diff --git a/src/H5.c b/src/H5.c
index 39f7b3a..795e30e 100644
--- a/src/H5.c
+++ b/src/H5.c
@@ -206,7 +206,7 @@ void
H5_term_library(void)
{
int pending, ntries = 0, n;
- unsigned at = 0;
+ size_t at = 0;
char loop[1024];
H5E_auto2_t func;
@@ -476,7 +476,7 @@ H5_debug_mask(const char *s)
FILE *stream = stderr;
char pkg_name[32], *rest;
size_t i;
- int clear;
+ hbool_t clear;
while (s && *s) {
if (HDisalpha(*s) || '-'==*s || '+'==*s) {
@@ -499,20 +499,20 @@ H5_debug_mask(const char *s)
/* Trace, all, or one? */
if (!HDstrcmp(pkg_name, "trace")) {
- H5_debug_g.trace = clear?NULL:stream;
+ H5_debug_g.trace = clear ? NULL : stream;
} else if (!HDstrcmp(pkg_name, "ttop")) {
H5_debug_g.trace = stream;
- H5_debug_g.ttop = !clear;
+ H5_debug_g.ttop = (hbool_t)!clear;
} else if (!HDstrcmp(pkg_name, "ttimes")) {
H5_debug_g.trace = stream;
- H5_debug_g.ttimes = !clear;
+ H5_debug_g.ttimes = (hbool_t)!clear;
} else if (!HDstrcmp(pkg_name, "all")) {
for (i=0; i<(size_t)H5_NPKGS; i++)
- H5_debug_g.pkg[i].stream = clear?NULL:stream;
+ H5_debug_g.pkg[i].stream = clear ? NULL : stream;
} else {
for (i=0; i<(size_t)H5_NPKGS; i++) {
if (!HDstrcmp(H5_debug_g.pkg[i].name, pkg_name)) {
- H5_debug_g.pkg[i].stream = clear?NULL:stream;
+ H5_debug_g.pkg[i].stream = clear ? NULL : stream;
break;
}
}
diff --git a/src/H5A.c b/src/H5A.c
index 8e464af..0af4aaf 100644
--- a/src/H5A.c
+++ b/src/H5A.c
@@ -85,9 +85,12 @@ static herr_t H5A_read(const H5A_t *attr, const H5T_t *mem_type, void *buf, hid_
/* Local Variables */
/*******************/
-/* Declare the free lists for H5A_t's */
+/* Declare the free lists of H5A_t */
H5FL_DEFINE(H5A_t);
+/* Declare the free lists for H5A_shared_t's */
+H5FL_DEFINE(H5A_shared_t);
+
/* Declare a free list to manage blocks of type conversion data */
H5FL_BLK_DEFINE(attr_buf);
@@ -173,7 +176,7 @@ H5A_term_interface(void)
if(H5_interface_initialize_g) {
if((n = H5I_nmembers(H5I_ATTR))>0) {
- (void)H5I_clear_type(H5I_ATTR, FALSE);
+ (void)H5I_clear_type(H5I_ATTR, FALSE, FALSE);
} else {
(void)H5I_dec_type_ref(H5I_ATTR);
H5_interface_initialize_g = 0;
@@ -342,7 +345,7 @@ done:
* Purpose:
* This is the guts of creating an attribute.
* Usage:
- * hid_t H5A_create (ent, name, type, space)
+ * hid_t H5A_create(ent, name, type, space)
* const H5G_entry_t *ent; IN: Pointer to symbol table entry for object to attribute
* const char *name; IN: Name of attribute
* H5T_t *type; IN: Datatype of attribute
@@ -360,9 +363,11 @@ hid_t
H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type,
const H5S_t *space, hid_t acpl_id, hid_t dxpl_id)
{
- H5A_t *attr = NULL;
- htri_t tri_ret; /* htri_t return value */
- hid_t ret_value; /* Return value */
+ H5A_t *attr = NULL; /* Attribute created */
+ hssize_t snelmts; /* elements in attribute */
+ size_t nelmts; /* elements in attribute */
+ htri_t tri_ret; /* htri_t return value */
+ hid_t ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5A_create)
@@ -387,12 +392,15 @@ H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type,
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspace extent has not been set")
/* Build the attribute information */
- if((attr = H5FL_CALLOC(H5A_t)) == NULL)
+ if(NULL == (attr = H5FL_CALLOC(H5A_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for attribute info")
+ if(NULL == (attr->shared = H5FL_CALLOC(H5A_shared_t)))
+ HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, FAIL, "can't allocate shared attr structure")
+
/* If the creation property list is H5P_DEFAULT, use the default character encoding */
if(acpl_id == H5P_DEFAULT)
- attr->encoding = H5F_DEFAULT_CSET;
+ attr->shared->encoding = H5F_DEFAULT_CSET;
else {
H5P_genplist_t *ac_plist; /* ACPL Property list */
@@ -400,59 +408,60 @@ H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type,
if(NULL == (ac_plist = (H5P_genplist_t *)H5I_object(acpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
- if(H5P_get(ac_plist, H5P_STRCRT_CHAR_ENCODING_NAME, &(attr->encoding)) < 0)
+ if(H5P_get(ac_plist, H5P_STRCRT_CHAR_ENCODING_NAME, &(attr->shared->encoding)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get character encoding flag")
} /* end else */
/* Copy the attribute name */
- attr->name = H5MM_xstrdup(name);
+ attr->shared->name = H5MM_xstrdup(name);
- /* Copy the attribute's datatype */
- attr->dt = H5T_copy(type, H5T_COPY_ALL);
+ /* Copy datatype */
+ if(NULL == (attr->shared->dt = H5T_copy(type, H5T_COPY_ALL)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get shared datatype info")
- /* Mark any datatypes as being on disk now */
- if(H5T_set_loc(attr->dt, loc->oloc->file, H5T_LOC_DISK) < 0)
+ /* Mark datatype as being on disk now */
+ if(H5T_set_loc(attr->shared->dt, loc->oloc->file, H5T_LOC_DISK) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location")
/* Set the latest format for datatype, if requested */
if(H5F_USE_LATEST_FORMAT(loc->oloc->file))
- if(H5T_set_latest_version(attr->dt) < 0)
+ if(H5T_set_latest_version(attr->shared->dt) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set latest version of datatype")
/* Copy the dataspace for the attribute */
- attr->ds = H5S_copy(space, FALSE);
+ attr->shared->ds = H5S_copy(space, FALSE, TRUE);
/* Set the latest format for dataspace, if requested */
if(H5F_USE_LATEST_FORMAT(loc->oloc->file))
- if(H5S_set_latest_version(attr->ds) < 0)
+ if(H5S_set_latest_version(attr->shared->ds) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set latest version of dataspace")
/* Mark it initially set to initialized */
- attr->initialized = TRUE; /*for now, set to false later*/
+ attr->shared->initialized = TRUE; /*for now, set to false later*/
/* Copy the object header information */
- if(H5O_loc_copy(&(attr->oloc), loc->oloc, H5_COPY_DEEP) < 0)
+ if(H5O_loc_copy(&(attr->shared->oloc), loc->oloc, H5_COPY_DEEP) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to copy entry")
/* Deep copy of the group hierarchy path */
if(H5G_name_copy(&(attr->path), loc->path, H5_COPY_DEEP) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to copy path")
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "unable to copy path")
/* Check if any of the pieces should be (or are already) shared in the
* SOHM table
*/
- if(H5SM_try_share(attr->oloc.file, dxpl_id, NULL, H5O_DTYPE_ID, attr->dt, NULL) < 0)
+ if(H5SM_try_share(attr->shared->oloc.file, dxpl_id, NULL, H5O_DTYPE_ID, attr->shared->dt, NULL) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "trying to share datatype failed")
- if(H5SM_try_share(attr->oloc.file, dxpl_id, NULL, H5O_SDSPACE_ID, attr->ds, NULL) < 0)
+ if(H5SM_try_share(attr->shared->oloc.file, dxpl_id, NULL, H5O_SDSPACE_ID, attr->shared->ds, NULL) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "trying to share dataspace failed")
/* Check whether datatype is committed & increment ref count
* (to maintain ref. count incr/decr similarity with "shared message"
* type of datatype sharing)
*/
- if(H5T_committed(attr->dt)) {
+ if(H5T_committed(attr->shared->dt)) {
/* Increment the reference count on the shared datatype */
- if(H5T_link(attr->dt, 1, dxpl_id) < 0)
+ if(H5T_link(attr->shared->dt, 1, dxpl_id) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared datatype link count")
} /* end if */
@@ -460,37 +469,41 @@ H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type,
* datatype and dataspace messages themselves, or the size of the "shared"
* messages if either or both of them are shared.
*/
- attr->dt_size = H5O_msg_raw_size(attr->oloc.file, H5O_DTYPE_ID, FALSE, attr->dt);
- attr->ds_size = H5O_msg_raw_size(attr->oloc.file, H5O_SDSPACE_ID, FALSE, attr->ds);
+ attr->shared->dt_size = H5O_msg_raw_size(attr->shared->oloc.file, H5O_DTYPE_ID, FALSE, attr->shared->dt);
+ attr->shared->ds_size = H5O_msg_raw_size(attr->shared->oloc.file, H5O_SDSPACE_ID, FALSE, attr->shared->ds);
+
+ /* Get # of elements for attribute's dataspace */
+ if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->shared->ds)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, FAIL, "dataspace is invalid")
+ H5_ASSIGN_OVERFLOW(nelmts, snelmts, hssize_t, size_t);
- HDassert(attr->dt_size > 0);
- 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);
+ HDassert(attr->shared->dt_size > 0);
+ HDassert(attr->shared->ds_size > 0);
+ attr->shared->data_size = nelmts * H5T_GET_SIZE(attr->shared->dt);
/* Hold the symbol table entry (and file) open */
- if(H5O_open(&(attr->oloc)) < 0)
+ if(H5O_open(&(attr->shared->oloc)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open")
attr->obj_opened = TRUE;
/* Set the version to encode the attribute with */
- if(H5A_set_version(attr->oloc.file, attr) < 0)
+ if(H5A_set_version(attr->shared->oloc.file, attr) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "unable to update attribute version")
/* Insert the attribute into the object header */
- if(H5O_attr_create(&(attr->oloc), dxpl_id, attr) < 0)
+ if(H5O_attr_create(&(attr->shared->oloc), dxpl_id, attr) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to create attribute in object header")
/* Register the new attribute and get an ID for it */
- if((ret_value = H5I_register(H5I_ATTR, attr)) < 0)
+ if((ret_value = H5I_register(H5I_ATTR, attr, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register attribute for ID")
/* Now it's safe to say it's uninitialized */
- attr->initialized = FALSE;
+ attr->shared->initialized = FALSE;
done:
/* Cleanup on failure */
- if(ret_value < 0)
- if(attr && H5A_close(attr) < 0)
+ if(ret_value < 0 && attr && H5A_close(attr) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "can't close attribute")
FUNC_LEAVE_NOAPI(ret_value)
@@ -537,14 +550,14 @@ H5Aopen(hid_t loc_id, const char *attr_name, hid_t UNUSED aapl_id)
/* Read in attribute from object header */
if(NULL == (attr = H5O_attr_open_by_name(loc.oloc, attr_name, H5AC_ind_dxpl_id)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to load attribute info from object header")
- attr->initialized = TRUE;
+ attr->shared->initialized = TRUE;
/* Finish initializing attribute */
if(H5A_open_common(&loc, attr) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to initialize attribute")
/* Register the attribute and get an ID for it */
- if((ret_value = H5I_register(H5I_ATTR, attr)) < 0)
+ if((ret_value = H5I_register(H5I_ATTR, attr, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register attribute for ID")
done:
@@ -609,7 +622,7 @@ H5Aopen_by_name(hid_t loc_id, const char *obj_name, const char *attr_name,
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "can't open attribute")
/* Register the attribute and get an ID for it */
- if((ret_value = H5I_register(H5I_ATTR, attr)) < 0)
+ if((ret_value = H5I_register(H5I_ATTR, attr, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register attribute for ID")
done:
@@ -680,7 +693,7 @@ H5Aopen_by_idx(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open attribute")
/* Register the attribute and get an ID for it */
- if((ret_value = H5I_register(H5I_ATTR, attr)) < 0)
+ if((ret_value = H5I_register(H5I_ATTR, attr, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register attribute for ID")
done:
@@ -698,7 +711,7 @@ done:
*
* Purpose:
* Finishes initializing an attributes the open
- *
+ *
* Usage:
* herr_t H5A_open_common(loc, name, dxpl_id)
* const H5G_loc_t *loc; IN: Pointer to group location for object
@@ -724,7 +737,7 @@ H5A_open_common(const H5G_loc_t *loc, H5A_t *attr)
#if defined(H5_USING_MEMCHECKER) || !defined(NDEBUG)
/* Clear object location */
- if(H5O_loc_reset(&(attr->oloc)) < 0)
+ if(H5O_loc_reset(&(attr->shared->oloc)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to reset location")
#endif /* H5_USING_MEMCHECKER */
@@ -733,15 +746,15 @@ H5A_open_common(const H5G_loc_t *loc, H5A_t *attr)
HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release group hier. path")
/* Deep copy of the symbol table entry */
- if(H5O_loc_copy(&(attr->oloc), loc->oloc, H5_COPY_DEEP) < 0)
+ if(H5O_loc_copy(&(attr->shared->oloc), loc->oloc, H5_COPY_DEEP) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to copy entry")
/* Deep copy of the group hier. path */
if(H5G_name_copy(&(attr->path), loc->path, H5_COPY_DEEP) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to copy entry")
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "unable to copy entry")
/* Hold the symbol table entry (and file) open */
- if(H5O_open(&(attr->oloc)) < 0)
+ if(H5O_open(&(attr->shared->oloc)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open")
attr->obj_opened = TRUE;
@@ -792,7 +805,7 @@ H5A_open_by_idx(const H5G_loc_t *loc, const char *obj_name, H5_index_t idx_type,
/* Read in attribute from object header */
if(NULL == (attr = H5O_attr_open_by_idx(obj_loc.oloc, idx_type, order, n, dxpl_id)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to load attribute info from object header")
- attr->initialized = TRUE;
+ attr->shared->initialized = TRUE;
/* Finish initializing attribute */
if(H5A_open_common(&obj_loc, attr) < 0)
@@ -819,7 +832,7 @@ done:
* Function: H5A_open_by_name
*
* Purpose: Open an attribute in an object header, according to it's name
- *
+ *
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
@@ -858,7 +871,7 @@ H5A_open_by_name(const H5G_loc_t *loc, const char *obj_name, const char *attr_na
/* Read in attribute from object header */
if(NULL == (attr = H5O_attr_open_by_name(obj_loc.oloc, attr_name, dxpl_id)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to load attribute info from object header")
- attr->initialized = TRUE;
+ attr->shared->initialized = TRUE;
/* Finish initializing attribute */
if(H5A_open_common(loc, attr) < 0)
@@ -900,9 +913,9 @@ done:
herr_t
H5Awrite(hid_t attr_id, hid_t dtype_id, const void *buf)
{
- H5A_t *attr; /* Attribute object for ID */
- const H5T_t *mem_type = NULL;
- herr_t ret_value;
+ H5A_t *attr; /* Attribute object for ID */
+ H5T_t *mem_type; /* Memory datatype */
+ herr_t ret_value; /* Return value */
FUNC_ENTER_API(H5Awrite, FAIL)
H5TRACE3("e", "ii*x", attr_id, dtype_id, buf);
@@ -962,31 +975,33 @@ H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf, hid_t dxpl_id)
HDassert(buf);
/* Get # of elements for attribute's dataspace */
- if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->ds)) < 0)
+ if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->shared->ds)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, FAIL, "dataspace is invalid")
H5_ASSIGN_OVERFLOW(nelmts, snelmts, hssize_t, size_t);
/* If there's actually data elements for the attribute, make a copy of the data passed in */
if(nelmts > 0) {
/* Get the memory and file datatype sizes */
- src_type_size = H5T_get_size(mem_type);
- dst_type_size = H5T_get_size(attr->dt);
+ src_type_size = H5T_GET_SIZE(mem_type);
+ dst_type_size = H5T_GET_SIZE(attr->shared->dt);
/* Convert memory buffer into disk buffer */
/* Set up type conversion function */
- if(NULL == (tpath = H5T_path_find(mem_type, attr->dt, NULL, NULL, dxpl_id, FALSE)))
+ if(NULL == (tpath = H5T_path_find(mem_type, attr->shared->dt, NULL, NULL, dxpl_id, FALSE)))
HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dst datatypes")
/* Check for type conversion required */
if(!H5T_path_noop(tpath)) {
- if((src_id = H5I_register(H5I_DATATYPE, H5T_copy(mem_type, H5T_COPY_ALL))) < 0 ||
- (dst_id = H5I_register(H5I_DATATYPE, H5T_copy(attr->dt, H5T_COPY_ALL))) < 0)
+ if((src_id = H5I_register(H5I_DATATYPE, H5T_copy(mem_type, H5T_COPY_ALL), FALSE)) < 0 ||
+ (dst_id = H5I_register(H5I_DATATYPE, H5T_copy(attr->shared->dt, H5T_COPY_ALL), FALSE)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, FAIL, "unable to register types for conversion")
/* Get the maximum buffer size needed and allocate it */
buf_size = nelmts * MAX(src_type_size, dst_type_size);
- if(NULL == (tconv_buf = H5FL_BLK_MALLOC (attr_buf, buf_size)) || NULL == (bkg_buf = H5FL_BLK_CALLOC(attr_buf, buf_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ if(NULL == (tconv_buf = H5FL_BLK_MALLOC(attr_buf, buf_size)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, "memory allocation failed")
+ if(NULL == (bkg_buf = H5FL_BLK_CALLOC(attr_buf, buf_size)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, "memory allocation failed")
/* Copy the user's data into the buffer for conversion */
HDmemcpy(tconv_buf, buf, (src_type_size * nelmts));
@@ -996,11 +1011,11 @@ H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf, hid_t dxpl_id)
HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "datatype conversion failed")
/* Free the previous attribute data buffer, if there is one */
- if(attr->data)
- attr->data = H5FL_BLK_FREE(attr_buf, attr->data);
+ if(attr->shared->data)
+ attr->shared->data = H5FL_BLK_FREE(attr_buf, attr->shared->data);
/* Set the pointer to the attribute data to the converted information */
- attr->data = tconv_buf;
+ attr->shared->data = tconv_buf;
tconv_owned = TRUE;
} /* end if */
/* No type conversion necessary */
@@ -1008,32 +1023,32 @@ H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf, hid_t dxpl_id)
HDassert(dst_type_size == src_type_size);
/* Allocate the attribute buffer, if there isn't one */
- if(attr->data == NULL)
- if(NULL == (attr->data = H5FL_BLK_MALLOC(attr_buf, dst_type_size * nelmts)))
+ if(attr->shared->data == NULL)
+ if(NULL == (attr->shared->data = H5FL_BLK_MALLOC(attr_buf, dst_type_size * nelmts)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Copy the attribute data into the user's buffer */
- HDmemcpy(attr->data, buf, (dst_type_size * nelmts));
+ HDmemcpy(attr->shared->data, buf, (dst_type_size * nelmts));
} /* end else */
/* Modify the attribute in the object header */
- if(H5O_attr_write(&(attr->oloc), dxpl_id, attr) < 0)
+ if(H5O_attr_write(&(attr->shared->oloc), dxpl_id, attr) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to modify attribute")
} /* end if */
/* Indicate the the attribute doesn't need fill-values */
- attr->initialized = TRUE;
+ attr->shared->initialized = TRUE;
done:
/* Release resources */
if(src_id >= 0)
- (void)H5I_dec_ref(src_id);
+ (void)H5I_dec_ref(src_id, FALSE);
if(dst_id >= 0)
- (void)H5I_dec_ref(dst_id);
+ (void)H5I_dec_ref(dst_id, FALSE);
if(tconv_buf && !tconv_owned)
- H5FL_BLK_FREE(attr_buf, tconv_buf);
+ (void)H5FL_BLK_FREE(attr_buf, tconv_buf);
if(bkg_buf)
- H5FL_BLK_FREE(attr_buf, bkg_buf);
+ (void)H5FL_BLK_FREE(attr_buf, bkg_buf);
FUNC_LEAVE_NOAPI(ret_value)
} /* H5A_write() */
@@ -1058,9 +1073,9 @@ done:
herr_t
H5Aread(hid_t attr_id, hid_t dtype_id, void *buf)
{
- H5A_t *attr; /* Attribute object for ID */
- const H5T_t *mem_type = NULL;
- herr_t ret_value;
+ H5A_t *attr; /* Attribute object for ID */
+ H5T_t *mem_type; /* Memory datatype */
+ herr_t ret_value; /* Return value */
FUNC_ENTER_API(H5Aread, FAIL)
H5TRACE3("e", "ii*x", attr_id, dtype_id, buf);
@@ -1119,37 +1134,39 @@ H5A_read(const H5A_t *attr, const H5T_t *mem_type, void *buf, hid_t dxpl_id)
HDassert(buf);
/* Create buffer for data to store on disk */
- if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->ds)) < 0)
+ if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->shared->ds)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, FAIL, "dataspace is invalid")
H5_ASSIGN_OVERFLOW(nelmts, snelmts, hssize_t, size_t);
if(nelmts > 0) {
/* Get the memory and file datatype sizes */
- src_type_size = H5T_get_size(attr->dt);
- dst_type_size = H5T_get_size(mem_type);
+ src_type_size = H5T_GET_SIZE(attr->shared->dt);
+ dst_type_size = H5T_GET_SIZE(mem_type);
/* Check if the attribute has any data yet, if not, fill with zeroes */
- if(attr->obj_opened && !attr->initialized)
+ if(attr->obj_opened && !attr->shared->initialized)
HDmemset(buf, 0, (dst_type_size * nelmts));
else { /* Attribute exists and has a value */
/* Convert memory buffer into disk buffer */
/* Set up type conversion function */
- if(NULL == (tpath = H5T_path_find(attr->dt, mem_type, NULL, NULL, dxpl_id, FALSE)))
+ if(NULL == (tpath = H5T_path_find(attr->shared->dt, mem_type, NULL, NULL, dxpl_id, FALSE)))
HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dst datatypes")
/* Check for type conversion required */
if(!H5T_path_noop(tpath)) {
- if((src_id = H5I_register(H5I_DATATYPE, H5T_copy(attr->dt, H5T_COPY_ALL))) < 0 ||
- (dst_id = H5I_register(H5I_DATATYPE, H5T_copy(mem_type, H5T_COPY_ALL))) < 0)
+ if((src_id = H5I_register(H5I_DATATYPE, H5T_copy(attr->shared->dt, H5T_COPY_ALL), FALSE)) < 0 ||
+ (dst_id = H5I_register(H5I_DATATYPE, H5T_copy(mem_type, H5T_COPY_ALL), FALSE)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, FAIL, "unable to register types for conversion")
/* Get the maximum buffer size needed and allocate it */
buf_size = nelmts * MAX(src_type_size, dst_type_size);
- if(NULL == (tconv_buf = H5FL_BLK_MALLOC(attr_buf, buf_size)) || NULL == (bkg_buf = H5FL_BLK_CALLOC(attr_buf, buf_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ if(NULL == (tconv_buf = H5FL_BLK_MALLOC(attr_buf, buf_size)))
+ HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "memory allocation failed")
+ if(NULL == (bkg_buf = H5FL_BLK_CALLOC(attr_buf, buf_size)))
+ HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Copy the attribute data into the buffer for conversion */
- HDmemcpy(tconv_buf, attr->data, (src_type_size * nelmts));
+ HDmemcpy(tconv_buf, attr->shared->data, (src_type_size * nelmts));
/* Perform datatype conversion. */
if(H5T_convert(tpath, src_id, dst_id, nelmts, (size_t)0, (size_t)0, tconv_buf, bkg_buf, dxpl_id) < 0)
@@ -1163,7 +1180,7 @@ H5A_read(const H5A_t *attr, const H5T_t *mem_type, void *buf, hid_t dxpl_id)
HDassert(dst_type_size == src_type_size);
/* Copy the attribute data into the user's buffer */
- HDmemcpy(buf, attr->data, (dst_type_size * nelmts));
+ HDmemcpy(buf, attr->shared->data, (dst_type_size * nelmts));
} /* end else */
} /* end else */
} /* end if */
@@ -1171,13 +1188,13 @@ H5A_read(const H5A_t *attr, const H5T_t *mem_type, void *buf, hid_t dxpl_id)
done:
/* Release resources */
if(src_id >= 0)
- (void)H5I_dec_ref(src_id);
+ (void)H5I_dec_ref(src_id, FALSE);
if(dst_id >= 0)
- (void)H5I_dec_ref(dst_id);
+ (void)H5I_dec_ref(dst_id, FALSE);
if(tconv_buf)
- H5FL_BLK_FREE(attr_buf, tconv_buf);
+ (void)H5FL_BLK_FREE(attr_buf, tconv_buf);
if(bkg_buf)
- H5FL_BLK_FREE(attr_buf, bkg_buf);
+ (void)H5FL_BLK_FREE(attr_buf, bkg_buf);
FUNC_LEAVE_NOAPI(ret_value)
} /* H5A_read() */
@@ -1214,11 +1231,11 @@ H5Aget_space(hid_t attr_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute")
/* Copy the attribute's dataspace */
- if(NULL == (ds = H5S_copy (attr->ds, FALSE)))
+ if(NULL == (ds = H5S_copy(attr->shared->ds, FALSE, TRUE)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to copy dataspace")
/* Atomize */
- if((ret_value = H5I_register(H5I_DATASPACE, ds)) < 0)
+ if((ret_value = H5I_register(H5I_DATASPACE, ds, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace atom")
done:
@@ -1250,7 +1267,7 @@ H5Aget_type(hid_t attr_id)
{
H5A_t *attr; /* Attribute object for ID */
H5T_t *dt = NULL; /* Copy of attribute's datatype */
- hid_t ret_value;
+ hid_t ret_value; /* Return value */
FUNC_ENTER_API(H5Aget_type, FAIL)
H5TRACE1("i", "i", attr_id);
@@ -1264,22 +1281,26 @@ H5Aget_type(hid_t attr_id)
* reopen the type before returning it to the user. Make the type
* read-only.
*/
- if(NULL == (dt = H5T_copy(attr->dt, H5T_COPY_REOPEN)))
+ if(NULL == (dt = H5T_copy(attr->shared->dt, H5T_COPY_REOPEN)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to copy datatype")
/* Mark any datatypes as being in memory now */
if(H5T_set_loc(dt, NULL, H5T_LOC_MEMORY) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location")
+
+ /* Lock copied type */
if(H5T_lock(dt, FALSE) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to lock transient datatype")
/* Atomize */
- if((ret_value = H5I_register(H5I_DATATYPE, dt)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register datatype atom")
+ if((ret_value = H5I_register(H5I_DATATYPE, dt, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register datatype ID")
done:
- if(ret_value < 0 && dt)
- (void)H5T_close(dt);
+ if(ret_value < 0) {
+ if(dt && H5T_close(dt) < 0)
+ HDONE_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, FAIL, "unable to release datatype")
+ } /* end if */
FUNC_LEAVE_API(ret_value)
} /* H5Aget_type() */
@@ -1325,13 +1346,13 @@ H5Aget_create_plist(hid_t attr_id)
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "can't get default ACPL")
/* Create the property list object to return */
- if((new_plist_id = H5P_copy_plist(plist)) < 0)
+ if((new_plist_id = H5P_copy_plist(plist, TRUE)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "unable to copy attribute creation properties")
if(NULL == (new_plist = (H5P_genplist_t *)H5I_object(new_plist_id)))
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "can't get property list")
/* Set the character encoding on the new property list */
- if(H5P_set(new_plist, H5P_STRCRT_CHAR_ENCODING_NAME, &(attr->encoding)) < 0)
+ if(H5P_set(new_plist, H5P_STRCRT_CHAR_ENCODING_NAME, &(attr->shared->encoding)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set character encoding")
ret_value = new_plist_id;
@@ -1365,21 +1386,53 @@ done:
ssize_t
H5Aget_name(hid_t attr_id, size_t buf_size, char *buf)
{
- H5A_t *attr; /* Attribute object for ID */
- size_t copy_len, nbytes;
+ H5A_t *my_attr; /* Attribute object for ID */
ssize_t ret_value;
FUNC_ENTER_API(H5Aget_name, FAIL)
H5TRACE3("Zs", "iz*s", attr_id, buf_size, buf);
/* check arguments */
- if(NULL == (attr = (H5A_t *)H5I_object_verify(attr_id, H5I_ATTR)))
+ if(NULL == (my_attr = (H5A_t *)H5I_object_verify(attr_id, H5I_ATTR)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute")
if(!buf && buf_size)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid buffer")
+ /* Call private function in turn */
+ if(0 > (ret_value = H5A_get_name(my_attr, buf_size, buf)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get attribute name")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* H5Aget_name() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5A_get_name
+ PURPOSE
+ Private function for H5Aget_name. Gets a copy of the name for an
+ attribute
+ RETURNS
+ This function returns the length of the attribute's name (which may be
+ longer than 'buf_size') on success or negative for failure.
+ DESCRIPTION
+ This function retrieves the name of an attribute for an attribute ID.
+ Up to 'buf_size' characters are stored in 'buf' followed by a '\0' string
+ terminator. If the name of the attribute is longer than 'buf_size'-1,
+ the string terminator is stored in the last position of the buffer to
+ properly terminate the string.
+--------------------------------------------------------------------------*/
+ssize_t
+H5A_get_name(H5A_t *attr, size_t buf_size, char *buf)
+{
+ size_t copy_len, nbytes;
+ ssize_t ret_value;
+
+ FUNC_ENTER_NOAPI(H5A_get_name, FAIL)
+
/* get the real attribute length */
- nbytes = HDstrlen(attr->name);
+ nbytes = HDstrlen(attr->shared->name);
HDassert((ssize_t)nbytes >= 0); /*overflow, pretty unlikely --rpm*/
/* compute the string length which will fit into the user's buffer */
@@ -1387,7 +1440,7 @@ H5Aget_name(hid_t attr_id, size_t buf_size, char *buf)
/* Copy all/some of the name */
if(buf && copy_len > 0) {
- HDmemcpy(buf, attr->name, copy_len);
+ HDmemcpy(buf, attr->shared->name, copy_len);
/* Terminate the string */
buf[copy_len]='\0';
@@ -1397,8 +1450,8 @@ H5Aget_name(hid_t attr_id, size_t buf_size, char *buf)
ret_value = (ssize_t)nbytes;
done:
- FUNC_LEAVE_API(ret_value)
-} /* H5Aget_name() */
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5A_get_name() */
/*-------------------------------------------------------------------------
@@ -1453,11 +1506,11 @@ H5Aget_name_by_idx(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "can't open attribute")
/* Get the length of the name */
- ret_value = (ssize_t)HDstrlen(attr->name);
+ ret_value = (ssize_t)HDstrlen(attr->shared->name);
/* Copy the name into the user's buffer, if given */
if(name) {
- HDstrncpy(name, attr->name, MIN((size_t)(ret_value + 1), size));
+ HDstrncpy(name, attr->shared->name, MIN((size_t)(ret_value + 1), size));
if((size_t)ret_value >= size)
name[size - 1]='\0';
} /* end if */
@@ -1502,7 +1555,7 @@ H5Aget_storage_size(hid_t attr_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not an attribute")
/* Set return value */
- ret_value = attr->data_size;
+ ret_value = attr->shared->data_size;
done:
FUNC_LEAVE_API(ret_value)
@@ -1689,15 +1742,15 @@ H5A_get_info(const H5A_t *attr, H5A_info_t *ainfo)
HDassert(ainfo);
/* Set info for attribute */
- ainfo->cset = attr->encoding;
- ainfo->data_size = attr->data_size;
- if(attr->crt_idx == H5O_MAX_CRT_ORDER_IDX) {
+ ainfo->cset = attr->shared->encoding;
+ ainfo->data_size = attr->shared->data_size;
+ if(attr->shared->crt_idx == H5O_MAX_CRT_ORDER_IDX) {
ainfo->corder_valid = FALSE;
ainfo->corder = 0;
} /* end if */
else {
ainfo->corder_valid = TRUE;
- ainfo->corder = attr->crt_idx;
+ ainfo->corder = attr->shared->crt_idx;
} /* end else */
done:
@@ -1987,7 +2040,7 @@ H5Aiterate_by_name(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
loc_found = TRUE;
/* Open the object */
- if((obj_loc_id = H5O_open_by_loc(&obj_loc, H5AC_ind_dxpl_id)) < 0)
+ if((obj_loc_id = H5O_open_by_loc(&obj_loc, lapl_id, H5AC_ind_dxpl_id, TRUE)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open object")
/* Build attribute operator info */
@@ -2006,7 +2059,7 @@ H5Aiterate_by_name(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
done:
/* Release resources */
if(obj_loc_id > 0) {
- if(H5I_dec_ref(obj_loc_id) < 0)
+ if(H5I_dec_ref(obj_loc_id, TRUE) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "unable to close temporary object")
} /* end if */
else if(loc_found && H5G_loc_free(&obj_loc) < 0)
@@ -2230,7 +2283,7 @@ H5Aclose(hid_t attr_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute")
/* Decrement references to that atom (and close it) */
- if(H5I_dec_ref(attr_id) < 0)
+ if(H5I_dec_ref(attr_id, TRUE) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "can't close attribute")
done:
@@ -2250,6 +2303,10 @@ done:
* Programmer: Robb Matzke
* Thursday, December 4, 1997
*
+ * Modification:Raymond Lu
+ * 4 June 2008
+ * Changed some attribute information to be shared.
+ *
*-------------------------------------------------------------------------
*/
H5A_t *
@@ -2266,7 +2323,7 @@ H5A_copy(H5A_t *_new_attr, const H5A_t *old_attr)
/* Allocate attribute structure */
if(_new_attr == NULL) {
- if(NULL == (new_attr = H5FL_MALLOC(H5A_t)))
+ if(NULL == (new_attr = H5FL_CALLOC(H5A_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
allocated_attr = TRUE;
} /* end if */
@@ -2274,44 +2331,20 @@ H5A_copy(H5A_t *_new_attr, const H5A_t *old_attr)
new_attr = _new_attr;
/* Copy the top level of the attribute */
- *new_attr = *old_attr;
-
- /* Don't open the object header for a copy */
- new_attr->obj_opened = FALSE;
-
- /* Copy the guts of the attribute */
- if(NULL == (new_attr->name = H5MM_xstrdup(old_attr->name)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "unable to copy attribute name")
- if(NULL == (new_attr->dt = H5T_copy(old_attr->dt, H5T_COPY_ALL)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "unable to copy attribute datatype")
- if(NULL == (new_attr->ds = H5S_copy(old_attr->ds, FALSE)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "unable to copy attribute dataspace")
-
-#if defined(H5_USING_MEMCHECKER) || !defined(NDEBUG)
- /* Clear object location */
- if(H5O_loc_reset(&(new_attr->oloc)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to reset location")
+ new_attr->sh_loc = old_attr->sh_loc;
- /* Clear path name */
- if(H5G_name_reset(&(new_attr->path)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to reset path")
-#endif /* H5_USING_MEMCHECKER */
-
- /* Copy the object location and group path */
- if(H5O_loc_copy(&(new_attr->oloc), &(old_attr->oloc), H5_COPY_DEEP) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "can't copy object location")
+ /* Deep copy of the group hierarchy path */
if(H5G_name_copy(&(new_attr->path), &(old_attr->path), H5_COPY_DEEP) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "can't copy path")
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "unable to copy path")
- /* Copy the attribute data, if there is any */
- if(old_attr->data) {
- /* Allocate data buffer for new attribute */
- if(NULL == (new_attr->data = H5FL_BLK_MALLOC(attr_buf, old_attr->data_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ /* Share some attribute information */
+ new_attr->shared = old_attr->shared;
- /* Copy the attribute data */
- HDmemcpy(new_attr->data, old_attr->data, old_attr->data_size);
- } /* end if */
+ /* Increment reference count for shared object */
+ new_attr->shared->nrefs++;
+
+ /* Don't open the object header for a copy */
+ new_attr->obj_opened = FALSE;
/* Set the return value */
ret_value = new_attr;
@@ -2350,18 +2383,22 @@ H5A_free(H5A_t *attr)
HDassert(attr);
/* Free dynamicly allocated items */
- if(attr->name)
- H5MM_xfree(attr->name);
- if(attr->dt)
- if(H5T_close(attr->dt) < 0)
+ if(attr->shared->name) {
+ H5MM_xfree(attr->shared->name);
+ attr->shared->name = NULL;
+ }
+ if(attr->shared->dt) {
+ if(H5T_close(attr->shared->dt) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release datatype info")
- if(attr->ds)
- if(H5S_close(attr->ds) < 0)
+ attr->shared->dt = NULL;
+ }
+ if(attr->shared->ds) {
+ if(H5S_close(attr->shared->ds) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release dataspace info")
- if(attr->data)
- attr->data = H5FL_BLK_FREE(attr_buf, attr->data);
- if(H5G_name_free(&(attr->path)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release group hier. path")
+ attr->shared->ds = NULL;
+ }
+ if(attr->shared->data)
+ attr->shared->data = H5FL_BLK_FREE(attr_buf, attr->shared->data);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -2379,7 +2416,9 @@ done:
* Monday, December 8, 1997
*
* Modifications:
- *
+ * Raymond Lu
+ * 4 June 2008
+ * Changed some attribute object information to be shared.
*-------------------------------------------------------------------------
*/
herr_t
@@ -2390,31 +2429,32 @@ H5A_close(H5A_t *attr)
FUNC_ENTER_NOAPI(H5A_close, FAIL)
HDassert(attr);
-
- /* Check if the attribute has any data yet, if not, fill with zeroes */
- if(attr->obj_opened && !attr->initialized && attr->data_size) {
- uint8_t *tmp_buf = H5FL_BLK_CALLOC(attr_buf, attr->data_size);
- if(NULL == tmp_buf)
- HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "memory allocation failed for attribute fill-value")
-
- /* Go write the fill data to the attribute */
- if(H5A_write(attr, attr->dt, tmp_buf, H5AC_dxpl_id) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_WRITEERROR, FAIL, "unable to write attribute")
-
- /* Free temporary buffer */
- H5FL_BLK_FREE(attr_buf, tmp_buf);
- } /* end if */
-
- /* Free dynamicly allocated items */
- if(H5A_free(attr) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release attribute info")
+ HDassert(attr->shared);
/* Close the object's symbol-table entry */
- if(attr->obj_opened)
- if(H5O_close(&(attr->oloc)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release object header info")
+ if(attr->obj_opened && (H5O_close(&(attr->shared->oloc)) < 0))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release object header info")
+
+ /* Reference count can be 0. It only happens when H5A_create fails. */
+ if(1 >= attr->shared->nrefs) {
+ /* Free dynamicly allocated items */
+ if(H5A_free(attr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release attribute info")
+
+ /* Destroy shared attribute struct */
+ attr->shared = H5FL_FREE(H5A_shared_t, attr->shared);
+ } else if(attr->shared->nrefs > 1) {
+ /* There are other references to the shared part of the attribute.
+ * Only decrement the reference count. */
+ --attr->shared->nrefs;
+ }
+
+ /* Free group hierarchy path */
+ if(H5G_name_free(&(attr->path)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release group hier. path")
- H5FL_FREE(H5A_t, attr);
+ attr->shared = NULL;
+ (void)H5FL_FREE(H5A_t, attr);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -2446,7 +2486,7 @@ H5A_oloc(H5A_t *attr)
HDassert(attr);
/* Set return value */
- ret_value = &(attr->oloc);
+ ret_value = &(attr->shared->oloc);
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5AC.c b/src/H5AC.c
index 8f62095..950615a 100644
--- a/src/H5AC.c
+++ b/src/H5AC.c
@@ -43,8 +43,8 @@
*-------------------------------------------------------------------------
*/
-#define H5C_PACKAGE /*suppress error about including H5Cpkg */
#define H5AC_PACKAGE /*suppress error about including H5ACpkg */
+#define H5C_PACKAGE /*suppress error about including H5Cpkg */
#define H5F_PACKAGE /*suppress error about including H5Fpkg */
/* Interface initialization */
@@ -260,7 +260,7 @@ H5AC_init_interface(void)
HGOTO_ERROR(H5E_CACHE, H5E_BADATOM, FAIL, "can't get property list class")
/* Get an ID for the blocking, collective H5AC dxpl */
- if ((H5AC_dxpl_id=H5P_create_id(xfer_pclass)) < 0)
+ if ((H5AC_dxpl_id=H5P_create_id(xfer_pclass,FALSE)) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTCREATE, FAIL, "unable to register property list")
/* Get the property list object */
@@ -282,7 +282,7 @@ H5AC_init_interface(void)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set value")
/* Get an ID for the non-blocking, collective H5AC dxpl */
- if ((H5AC_noblock_dxpl_id=H5P_create_id(xfer_pclass)) < 0)
+ if ((H5AC_noblock_dxpl_id=H5P_create_id(xfer_pclass,FALSE)) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTCREATE, FAIL, "unable to register property list")
/* Get the property list object */
@@ -304,7 +304,7 @@ H5AC_init_interface(void)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set value")
/* Get an ID for the non-blocking, independent H5AC dxpl */
- if ((H5AC_ind_dxpl_id=H5P_create_id(xfer_pclass)) < 0)
+ if ((H5AC_ind_dxpl_id=H5P_create_id(xfer_pclass,FALSE)) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTCREATE, FAIL, "unable to register property list")
/* Get the property list object */
@@ -374,9 +374,9 @@ H5AC_term_interface(void)
n = 1; /* H5I */
/* Close H5AC dxpl */
- if (H5I_dec_ref(H5AC_dxpl_id) < 0 ||
- H5I_dec_ref(H5AC_noblock_dxpl_id) < 0 ||
- H5I_dec_ref(H5AC_ind_dxpl_id) < 0)
+ if (H5I_dec_ref(H5AC_dxpl_id, FALSE) < 0 ||
+ H5I_dec_ref(H5AC_noblock_dxpl_id, FALSE) < 0 ||
+ H5I_dec_ref(H5AC_ind_dxpl_id, FALSE) < 0)
H5E_clear_stack(NULL); /*ignore error*/
else {
/* Reset static IDs */
@@ -491,6 +491,11 @@ static const char * H5AC_entry_type_names[H5AC_NTYPES] =
"free space sections",
"shared OH message master table",
"shared OH message index",
+ "extensible array headers",
+ "extensible array index blocks",
+ "extensible array super blocks",
+ "extensible array data blocks",
+ "extensible array data block pages",
"test entry" /* for testing only -- not used for actual files */
};
@@ -746,9 +751,9 @@ done:
* Added code to free the auxiliary structure and its
* associated slist if present.
* JRM - 6/28/05
- *
+ *
* Added code to close the trace file if it is present.
- *
+ *
* JRM - 6/8/06
*
*-------------------------------------------------------------------------
@@ -830,24 +835,27 @@ done:
* 6/30/06
*
* Modifications:
- *
- * None.
+ *
+ * Added 'flags' paramater, to allow freeing file space
+ *
+ * QAK - 2/5/08
*
*-------------------------------------------------------------------------
*/
herr_t
-H5AC_expunge_entry(H5F_t *f,
- hid_t dxpl_id,
- const H5AC_class_t *type,
- haddr_t addr)
+H5AC_expunge_entry(H5F_t *f,
+ hid_t dxpl_id,
+ const H5AC_class_t *type,
+ haddr_t addr,
+ unsigned flags)
{
herr_t result;
- herr_t ret_value=SUCCEED; /* Return value */
H5AC_t * cache_ptr = NULL;
#if H5AC__TRACE_FILE_ENABLED
char trace[128] = "";
FILE * trace_file_ptr = NULL;
#endif /* H5AC__TRACE_FILE_ENABLED */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5AC_expunge_entry, FAIL)
@@ -862,8 +870,8 @@ H5AC_expunge_entry(H5F_t *f,
cache_ptr = f->shared->cache;
#if H5AC__TRACE_FILE_ENABLED
- /* For the expunge entry call, only the addr, and type id are really
- * necessary in the trace file. Write the return value to catch occult
+ /* For the expunge entry call, only the addr, and type id are really
+ * necessary in the trace file. Write the return value to catch occult
* errors.
*/
if ( ( cache_ptr != NULL ) &&
@@ -881,7 +889,8 @@ H5AC_expunge_entry(H5F_t *f,
H5AC_noblock_dxpl_id,
cache_ptr,
type,
- addr);
+ addr,
+ flags);
if ( result < 0 ) {
@@ -1002,8 +1011,8 @@ H5AC_flush(H5F_t *f, hid_t dxpl_id, unsigned flags)
/* For the flush, only the flags are really necessary in the trace file.
* Write the result to catch occult errors.
*/
- if ( ( f != NULL ) &&
- ( f->shared != NULL ) &&
+ if ( ( f != NULL ) &&
+ ( f->shared != NULL ) &&
( f->shared->cache != NULL ) &&
( H5C_get_trace_file_ptr(f->shared->cache, &trace_file_ptr) >= 0 ) &&
( trace_file_ptr != NULL ) ) {
@@ -1280,9 +1289,13 @@ H5AC_set(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr, void *
HDassert(H5F_addr_defined(addr));
HDassert(thing);
+ /* Check for invalid access request */
+ if(0 == (f->intent & H5F_ACC_RDWR))
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "no write intent on file")
+
#if H5AC__TRACE_FILE_ENABLED
- /* For the insert, only the addr, size, type id and flags are really
- * necessary in the trace file. Write the result to catch occult
+ /* For the insert, only the addr, size, type id and flags are really
+ * necessary in the trace file. Write the result to catch occult
* errors.
*
* Note that some data is not available right now -- put what we can
@@ -1369,8 +1382,8 @@ done:
#if H5AC__TRACE_FILE_ENABLED
if ( trace_file_ptr != NULL ) {
- HDfprintf(trace_file_ptr, "%s %d %d\n", trace,
- (int)trace_entry_size,
+ HDfprintf(trace_file_ptr, "%s %d %d\n", trace,
+ (int)trace_entry_size,
(int)ret_value);
}
#endif /* H5AC__TRACE_FILE_ENABLED */
@@ -1417,8 +1430,8 @@ H5AC_mark_pinned_entry_dirty(H5F_t * f,
FUNC_ENTER_NOAPI(H5AC_mark_pinned_entry_dirty, FAIL)
#if H5AC__TRACE_FILE_ENABLED
- /* For the mark pinned entry dirty call, only the addr, size_changed,
- * and new_size are really necessary in the trace file. Write the result
+ /* For the mark pinned entry dirty call, only the addr, size_changed,
+ * and new_size are really necessary in the trace file. Write the result
* to catch occult errors.
*/
if ( ( f != NULL ) &&
@@ -1539,7 +1552,7 @@ H5AC_mark_pinned_or_protected_entry_dirty(H5F_t * f,
#if H5AC__TRACE_FILE_ENABLED
/* For the mark pinned or protected entry dirty call, only the addr
- * is really necessary in the trace file. Write the result to catch
+ * is really necessary in the trace file. Write the result to catch
* occult errors.
*/
if ( ( f != NULL ) &&
@@ -1671,7 +1684,7 @@ H5AC_rename(H5F_t *f, const H5AC_class_t *type, haddr_t old_addr, haddr_t new_ad
HDassert(H5F_addr_ne(old_addr, new_addr));
#if H5AC__TRACE_FILE_ENABLED
- /* For the rename call, only the old addr and new addr are really
+ /* For the rename call, only the old addr and new addr are really
* necessary in the trace file. Include the type id so we don't have to
* look it up. Also write the result to catch occult errors.
*/
@@ -1776,7 +1789,7 @@ H5AC_pin_protected_entry(H5F_t * f,
FUNC_ENTER_NOAPI(H5AC_pin_protected_entry, FAIL)
#if H5AC__TRACE_FILE_ENABLED
- /* For the pin protected entry call, only the addr is really necessary
+ /* For the pin protected entry call, only the addr is really necessary
* in the trace file. Also write the result to catch occult errors.
*/
if ( ( f != NULL ) &&
@@ -1873,11 +1886,11 @@ done:
* Added trace file support.
*
* JRM - 3/18/07
- * Modified code to support the new flags parameter for
- * H5C_protect(). For now, that means passing in the
+ * Modified code to support the new flags parameter for
+ * H5C_protect(). For now, that means passing in the
* H5C_READ_ONLY_FLAG if rw == H5AC_READ.
*
- * Also updated the trace file output to save the
+ * Also updated the trace file output to save the
* rw parameter, since we are now doing something with it.
*
*-------------------------------------------------------------------------
@@ -1917,9 +1930,9 @@ H5AC_protect(H5F_t *f,
HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, NULL, "no write intent on file")
#if H5AC__TRACE_FILE_ENABLED
- /* For the protect call, only the addr and type id is really necessary
- * in the trace file. Include the size of the entry protected as a
- * sanity check. Also indicate whether the call was successful to
+ /* For the protect call, only the addr and type id is really necessary
+ * in the trace file. Include the size of the entry protected as a
+ * sanity check. Also indicate whether the call was successful to
* catch occult errors.
*/
if ( ( f != NULL ) &&
@@ -1986,7 +1999,7 @@ done:
#if H5AC__TRACE_FILE_ENABLED
if ( trace_file_ptr != NULL ) {
- HDfprintf(trace_file_ptr, "%s %d %d\n", trace,
+ HDfprintf(trace_file_ptr, "%s %d %d\n", trace,
(int)trace_entry_size,
(int)(ret_value != NULL));
}
@@ -2030,8 +2043,8 @@ H5AC_resize_pinned_entry(H5F_t * f,
FUNC_ENTER_NOAPI(H5AC_resize_pinned_entry, FAIL)
#if H5AC__TRACE_FILE_ENABLED
- /* For the resize pinned entry call, only the addr, and new_size are
- * really necessary in the trace file. Write the result to catch
+ /* For the resize pinned entry call, only the addr, and new_size are
+ * really necessary in the trace file. Write the result to catch
* occult errors.
*/
if ( ( f != NULL ) &&
@@ -2141,7 +2154,7 @@ H5AC_unpin_entry(H5F_t * f,
FUNC_ENTER_NOAPI(H5AC_unpin_entry, FAIL)
#if H5AC__TRACE_FILE_ENABLED
- /* For the unpin entry call, only the addr is really necessary
+ /* For the unpin entry call, only the addr is really necessary
* in the trace file. Also write the result to catch occult errors.
*/
if ( ( f != NULL ) &&
@@ -2302,7 +2315,7 @@ H5AC_unprotect(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr,
#if H5AC__TRACE_FILE_ENABLED
/* For the unprotect call, only the addr, type id, flags, and possible
- * new size are really necessary in the trace file. Write the return
+ * new size are really necessary in the trace file. Write the return
* value to catch occult errors.
*/
if ( ( f != NULL ) &&
@@ -2319,7 +2332,7 @@ H5AC_unprotect(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr,
}
#endif /* H5AC__TRACE_FILE_ENABLED */
- dirtied = ( ( (flags & H5AC__DIRTIED_FLAG) == H5AC__DIRTIED_FLAG ) ||
+ dirtied = (hbool_t)( ( (flags & H5AC__DIRTIED_FLAG) == H5AC__DIRTIED_FLAG ) ||
( ((H5AC_info_t *)thing)->dirtied ) );
if ( dirtied ) {
@@ -2413,8 +2426,8 @@ done:
#if H5AC__TRACE_FILE_ENABLED
if ( trace_file_ptr != NULL ) {
- HDfprintf(trace_file_ptr, "%s %d %x %d\n",
- trace,
+ HDfprintf(trace_file_ptr, "%s %d %x %d\n",
+ trace,
(int)trace_new_size,
(unsigned)trace_flags,
(int)ret_value);
@@ -2539,13 +2552,17 @@ done:
*
* JRM - 7/28/07
* Added support for the new evictions enabled related fields.
- *
- * Observe that H5AC_get_cache_auto_resize_config() and
+ *
+ * Observe that H5AC_get_cache_auto_resize_config() and
* H5AC_set_cache_auto_resize_config() are becoming generic
- * metadata cache configuration routines as they gain
- * switches for functions that are only tenuously related
+ * metadata cache configuration routines as they gain
+ * switches for functions that are only tenuously related
* to auto resize configuration.
*
+ * JRM - 1/2/08
+ * Added support for the new flash cache increment related
+ * fields.
+ *
*-------------------------------------------------------------------------
*/
@@ -2625,6 +2642,9 @@ H5AC_get_cache_auto_resize_config(H5AC_t * cache_ptr,
config_ptr->max_increment = internal_config.max_increment;
config_ptr->decr_mode = internal_config.decr_mode;
config_ptr->upper_hr_threshold = internal_config.upper_hr_threshold;
+ config_ptr->flash_incr_mode = internal_config.flash_incr_mode;
+ config_ptr->flash_multiple = internal_config.flash_multiple;
+ config_ptr->flash_threshold = internal_config.flash_threshold;
config_ptr->decrement = internal_config.decrement;
config_ptr->apply_max_decrement = internal_config.apply_max_decrement;
config_ptr->max_decrement = internal_config.max_decrement;
@@ -2801,7 +2821,7 @@ done:
* Updated for the addition of H5AC_cache_config_t.
*
* John Mainzer -- 10/25/05
- * Added support for the new dirty_bytes_threshold field of
+ * Added support for the new dirty_bytes_threshold field of
* both H5AC_cache_config_t and H5AC_aux_t.
*
* John Mainzer -- 6/7/06
@@ -2809,13 +2829,17 @@ done:
*
* John Mainzer -- 7/28/07
* Added support for the new evictions enabled related fields.
- *
- * Observe that H5AC_get_cache_auto_resize_config() and
+ *
+ * Observe that H5AC_get_cache_auto_resize_config() and
* H5AC_set_cache_auto_resize_config() are becoming generic
- * metadata cache configuration routines as they gain
- * switches for functions that are only tenuously related
+ * metadata cache configuration routines as they gain
+ * switches for functions that are only tenuously related
* to auto resize configuration.
*
+ * John Mainzer -- 1/3/07
+ * Updated trace file code to record the new flash cache
+ * size increase related fields.
+ *
*-------------------------------------------------------------------------
*/
@@ -2960,16 +2984,16 @@ H5AC_set_cache_auto_resize_config(H5AC_t * cache_ptr,
done:
#if H5AC__TRACE_FILE_ENABLED
- /* For the set cache auto resize config call, only the contents
- * of the config is necessary in the trace file. Write the return
+ /* For the set cache auto resize config call, only the contents
+ * of the config is necessary in the trace file. Write the return
* value to catch occult errors.
*/
if ( ( cache_ptr != NULL ) &&
( H5C_get_trace_file_ptr(cache_ptr, &trace_file_ptr) >= 0 ) &&
( trace_file_ptr != NULL ) ) {
- HDfprintf(trace_file_ptr,
- "%s %d %d %d %d \"%s\" %d %d %d %f %d %d %ld %d %f %f %d %d %d %f %f %d %d %d %d %f %d %d\n",
+ HDfprintf(trace_file_ptr,
+ "%s %d %d %d %d \"%s\" %d %d %d %f %d %d %ld %d %f %f %d %f %f %d %d %d %f %f %d %d %d %d %f %d %d\n",
"H5AC_set_cache_auto_resize_config",
trace_config.version,
(int)(trace_config.rpt_fcn_enabled),
@@ -2986,6 +3010,9 @@ done:
(int)(trace_config.incr_mode),
trace_config.lower_hr_threshold,
trace_config.increment,
+ (int)(trace_config.flash_incr_mode),
+ trace_config.flash_multiple,
+ trace_config.flash_threshold,
(int)(trace_config.apply_max_increment),
(int)(trace_config.max_increment),
(int)(trace_config.decr_mode),
@@ -3034,9 +3061,9 @@ done:
* are applied.
* JRM - 5/15/06
*
- * - Added code testing the evictions enabled field. At
- * present this consists of verifying that if
- * evictions_enabled is FALSE, then automatic cache
+ * - Added code testing the evictions enabled field. At
+ * present this consists of verifying that if
+ * evictions_enabled is FALSE, then automatic cache
* resizing in disabled.
*
* JRM - 7/28/07
@@ -3050,7 +3077,7 @@ H5AC_validate_config(H5AC_cache_config_t * config_ptr)
{
herr_t result;
herr_t ret_value = SUCCEED; /* Return value */
- int name_len;
+ size_t name_len;
H5C_auto_size_ctl_t internal_config;
FUNC_ENTER_NOAPI(H5AC_validate_config, FAIL)
@@ -3089,13 +3116,13 @@ H5AC_validate_config(H5AC_cache_config_t * config_ptr)
/* don't bother to test trace_file_name unless open_trace_file is TRUE */
if ( config_ptr->open_trace_file ) {
- /* Can't really test the trace_file_name field without trying to
+ /* Can't really test the trace_file_name field without trying to
* open the file, so we will content ourselves with a couple of
* sanity checks on the length of the file name.
*/
name_len = HDstrlen(config_ptr->trace_file_name);
- if ( name_len <= 0 ) {
+ if ( name_len == 0 ) {
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, \
"config_ptr->trace_file_name is empty.")
@@ -3115,7 +3142,8 @@ H5AC_validate_config(H5AC_cache_config_t * config_ptr)
}
if ( ( config_ptr->evictions_enabled == FALSE ) &&
- ( ( config_ptr->incr_mode != H5C_incr__off ) ||
+ ( ( config_ptr->incr_mode != H5C_incr__off ) ||
+ ( config_ptr->flash_incr_mode != H5C_flash_incr__off ) ||
( config_ptr->incr_mode != H5C_decr__off ) ) ) {
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, \
@@ -3618,7 +3646,9 @@ done:
*
* Modifications:
*
- * None.
+ * Updated function for flash cache increment fields.
+ *
+ * JRM -- 1/2/08
*
*-------------------------------------------------------------------------
*/
@@ -3661,6 +3691,9 @@ H5AC_ext_config_2_int_config(H5AC_cache_config_t * ext_conf_ptr,
int_conf_ptr->increment = ext_conf_ptr->increment;
int_conf_ptr->apply_max_increment = ext_conf_ptr->apply_max_increment;
int_conf_ptr->max_increment = ext_conf_ptr->max_increment;
+ int_conf_ptr->flash_incr_mode = ext_conf_ptr->flash_incr_mode;
+ int_conf_ptr->flash_multiple = ext_conf_ptr->flash_multiple;
+ int_conf_ptr->flash_threshold = ext_conf_ptr->flash_threshold;
int_conf_ptr->decr_mode = ext_conf_ptr->decr_mode;
int_conf_ptr->upper_hr_threshold = ext_conf_ptr->upper_hr_threshold;
diff --git a/src/H5ACpkg.h b/src/H5ACpkg.h
index 973f988..5f226ed 100644
--- a/src/H5ACpkg.h
+++ b/src/H5ACpkg.h
@@ -34,14 +34,12 @@
#ifndef _H5ACpkg_H
#define _H5ACpkg_H
-#define H5C_PACKAGE /*suppress error about including H5Cpkg */
-
/* Get package's private header */
-#include "H5Cprivate.h"
+#include "H5ACprivate.h"
/* Get needed headers */
-#include "H5Cpkg.h" /* Cache */
+#include "H5Cprivate.h" /* Cache */
#include "H5SLprivate.h" /* Skip lists */
@@ -323,4 +321,5 @@ typedef struct H5AC_aux_t
#endif /* H5_HAVE_PARALLEL */
-#endif /* _H5Cpkg_H */
+#endif /* _H5ACpkg_H */
+
diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h
index 628a269..4a6f9f3 100644
--- a/src/H5ACprivate.h
+++ b/src/H5ACprivate.h
@@ -62,6 +62,11 @@ typedef enum {
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_EARRAY_HDR_ID, /*extensible array header */
+ H5AC_EARRAY_IBLOCK_ID, /*extensible array index block */
+ H5AC_EARRAY_SBLOCK_ID, /*extensible array super block */
+ H5AC_EARRAY_DBLOCK_ID, /*extensible array data block */
+ H5AC_EARRAY_DBLK_PAGE_ID, /*extensible array data block page */
H5AC_TEST_ID, /*test entry -- not used for actual files */
H5AC_NTYPES /* Number of types, must be last */
} H5AC_type_t;
@@ -213,6 +218,10 @@ extern hid_t H5AC_ind_dxpl_id;
/* double increment = */ 2.0, \
/* hbool_t apply_max_increment = */ TRUE, \
/* size_t max_increment = */ (4 * 1024 * 1024), \
+ /* enum H5C_cache_flash_incr_mode */ \
+ /* flash_incr_mode = */ H5C_flash_incr__add_space, \
+ /* double flash_multiple = */ 1.0, \
+ /* double flash_threshold = */ 0.25, \
/* enum H5C_cache_decr_mode decr_mode = */ H5C_decr__age_out_with_threshold,\
/* double upper_hr_threshold = */ 0.999, \
/* double decrement = */ 0.9, \
@@ -245,6 +254,8 @@ extern hid_t H5AC_ind_dxpl_id;
#define H5AC__FLUSH_CLEAR_ONLY_FLAG H5C__FLUSH_CLEAR_ONLY_FLAG
#define H5AC__FLUSH_MARKED_ENTRIES_FLAG H5C__FLUSH_MARKED_ENTRIES_FLAG
#define H5AC__FLUSH_IGNORE_PROTECTED_FLAG H5C__FLUSH_IGNORE_PROTECTED_FLAG
+#define H5AC__FREE_FILE_SPACE_FLAG H5C__FREE_FILE_SPACE_FLAG
+#define H5AC__TAKE_OWNERSHIP_FLAG H5C__TAKE_OWNERSHIP_FLAG
/* #defines of flags used to report entry status in the
@@ -290,7 +301,8 @@ H5_DLL herr_t H5AC_rename(H5F_t *f, const H5AC_class_t *type,
H5_DLL herr_t H5AC_dest(H5F_t *f, hid_t dxpl_id);
H5_DLL herr_t H5AC_expunge_entry(H5F_t *f, hid_t dxpl_id,
- const H5AC_class_t *type, haddr_t addr);
+ const H5AC_class_t *type, haddr_t addr,
+ unsigned flags);
H5_DLL herr_t H5AC_set_write_done_callback(H5C_t * cache_ptr,
void (* write_done)(void));
diff --git a/src/H5ACpublic.h b/src/H5ACpublic.h
index 0ddef92..3c62fbf 100644
--- a/src/H5ACpublic.h
+++ b/src/H5ACpublic.h
@@ -15,7 +15,7 @@
/*-------------------------------------------------------------------------
*
- * Created: H5ACproto.h
+ * Created: H5ACpublic.h
* Jul 10 1997
* Robb Matzke <matzke@llnl.gov>
*
@@ -57,7 +57,7 @@ extern "C" {
* structure.
*
* Similarly, the open_trace_file, close_trace_file, and trace_file_name
- * fields do not appear in H5C_auto_size_ctl_t, as most trace file
+ * fields do not appear in H5C_auto_size_ctl_t, as most trace file
* issues are handled at the H5AC level. The one exception is storage of
* the pointer to the trace file, which is handled by H5C.
*
@@ -82,7 +82,7 @@ extern "C" {
*
* The trace file is a debuging feature that allow the capture of
* top level metadata cache requests for purposes of debugging and/or
- * optimization. This field should normally be set to FALSE, as
+ * optimization. This field should normally be set to FALSE, as
* trace file collection imposes considerable overhead.
*
* This field should only be set to TRUE when the trace_file_name
@@ -100,7 +100,7 @@ extern "C" {
* trace_file_name: Full path of the trace file to be opened if the
* open_trace_file field is TRUE.
*
- * In the parallel case, an ascii representation of the mpi rank of
+ * In the parallel case, an ascii representation of the mpi rank of
* the process will be appended to the file name to yield a unique
* trace file name for each process.
*
@@ -108,12 +108,12 @@ extern "C" {
* characters.
*
* evictions_enabled: Boolean field used to either report the current
- * evictions enabled status of the cache, or to set the cache's
+ * evictions enabled status of the cache, or to set the cache's
* evictions enabled status.
*
- * In general, the metadata cache should always be allowed to
- * evict entries. However, in some cases it is advantageous to
- * disable evictions briefly, and thereby postpone metadata
+ * In general, the metadata cache should always be allowed to
+ * evict entries. However, in some cases it is advantageous to
+ * disable evictions briefly, and thereby postpone metadata
* writes. However, this must be done with care, as the cache
* can grow quickly. If you do this, re-enable evictions as
* soon as possible and monitor cache size.
@@ -179,7 +179,7 @@ extern "C" {
* at its maximum size, or if the cache is not already using
* all available space.
*
- * Note that you must set decr_mode to H5C_incr__off if you
+ * Note that you must set decr_mode to H5C_incr__off if you
* disable metadata cache entry evictions.
*
* lower_hr_threshold: Lower hit rate threshold. If the increment mode
@@ -208,6 +208,61 @@ extern "C" {
* above, this field contains the maximum number of bytes by which the
* cache size can be increased in a single re-size.
*
+ * flash_incr_mode: Instance of the H5C_cache_flash_incr_mode enumerated
+ * type whose value indicates whether and by which algorithm we should
+ * make flash increases in the size of the cache to accomodate insertion
+ * of large entries and large increases in the size of a single entry.
+ *
+ * The addition of the flash increment mode was occasioned by performance
+ * problems that appear when a local heap is increased to a size in excess
+ * of the current cache size. While the existing re-size code dealt with
+ * this eventually, performance was very bad for the remainder of the
+ * epoch.
+ *
+ * At present, there are two possible values for the flash_incr_mode:
+ *
+ * H5C_flash_incr__off: Don't perform flash increases in the size of
+ * the cache.
+ *
+ * H5C_flash_incr__add_space: Let x be either the size of a newly
+ * newly inserted entry, or the number of bytes by which the
+ * size of an existing entry has been increased.
+ *
+ * If
+ * x > flash_threshold * current max cache size,
+ *
+ * increase the current maximum cache size by x * flash_multiple
+ * less any free space in the cache, and star a new epoch. For
+ * now at least, pay no attention to the maximum increment.
+ *
+ * In both of the above cases, the flash increment pays no attention to
+ * the maximum increment (at least in this first incarnation), but DOES
+ * stay within max_size.
+ *
+ * With a little thought, it should be obvious that the above flash
+ * cache size increase algorithm is not sufficient for all circumstances --
+ * for example, suppose the user round robins through
+ * (1/flash_threshold) +1 groups, adding one data set to each on each
+ * pass. Then all will increase in size at about the same time, requiring
+ * the max cache size to at least double to maintain acceptable
+ * performance, however the above flash increment algorithm will not be
+ * triggered.
+ *
+ * Hopefully, the add space algorithms detailed above will be sufficient
+ * for the performance problems encountered to date. However, we should
+ * expect to revisit the issue.
+ *
+ * flash_multiple: Double containing the multiple described above in the
+ * H5C_flash_incr__add_space section of the discussion of the
+ * flash_incr_mode section. This field is ignored unless flash_incr_mode
+ * is H5C_flash_incr__add_space.
+ *
+ * flash_threshold: Double containing the factor by which current max cache size
+ * is multiplied to obtain the size threshold for the add_space flash
+ * increment algorithm. The field is ignored unless flash_incr_mode is
+ * H5C_flash_incr__add_space.
+ *
+ *
*
* Cache size decrease control fields:
*
@@ -239,7 +294,7 @@ extern "C" {
* over the last epoch exceeds the value provided in the
* upper_hr_threshold field.
*
- * Note that you must set decr_mode to H5C_decr__off if you
+ * Note that you must set decr_mode to H5C_decr__off if you
* disable metadata cache entry evictions.
*
* upper_hr_threshold: Upper hit rate threshold. The use of this field
@@ -364,6 +419,10 @@ typedef struct H5AC_cache_config_t
hbool_t apply_max_increment;
size_t max_increment;
+ enum H5C_cache_flash_incr_mode flash_incr_mode;
+ double flash_multiple;
+ double flash_threshold;
+
/* size decrease control fields: */
enum H5C_cache_decr_mode decr_mode;
diff --git a/src/H5Abtree2.c b/src/H5Abtree2.c
index b685af7..07550da 100644
--- a/src/H5Abtree2.c
+++ b/src/H5Abtree2.c
@@ -172,7 +172,7 @@ H5A_dense_fh_name_cmp(const void *obj, size_t UNUSED obj_len, void *_udata)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "can't decode attribute")
/* Compare the string values */
- udata->cmp = HDstrcmp(udata->name, attr->name);
+ udata->cmp = HDstrcmp(udata->name, attr->shared->name);
/* Check for correct attribute & callback to make */
if(udata->cmp == 0 && udata->found_op) {
@@ -181,7 +181,7 @@ H5A_dense_fh_name_cmp(const void *obj, size_t UNUSED obj_len, void *_udata)
H5SM_reconstitute(&(attr->sh_loc), udata->f, H5O_ATTR_ID, udata->record->id);
/* Set the creation order index for the attribute */
- attr->crt_idx = udata->record->corder;
+ attr->shared->crt_idx = udata->record->corder;
/* Make callback */
if((udata->found_op)(attr, &took_ownership, udata->found_op_data) < 0)
diff --git a/src/H5Adense.c b/src/H5Adense.c
index de6bc8c..76ab95d 100644
--- a/src/H5Adense.c
+++ b/src/H5Adense.c
@@ -327,6 +327,7 @@ H5A_dense_open(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char *na
H5HF_t *fheap = NULL; /* Fractal heap handle */
H5HF_t *shared_fheap = NULL; /* Fractal heap handle for shared header messages */
htri_t attr_sharable; /* Flag indicating attributes are sharable */
+ htri_t attr_exists; /* Attribute exists in v2 B-tree */
H5A_t *ret_value = NULL; /* Return value */
FUNC_ENTER_NOAPI(H5A_dense_open, NULL)
@@ -375,7 +376,9 @@ H5A_dense_open(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char *na
udata.found_op_data = &ret_value;
/* Find & copy the attribute in the 'name' index */
- if(H5B2_find(f, dxpl_id, H5A_BT2_NAME, ainfo->name_bt2_addr, &udata, NULL, NULL) < 0)
+ if((attr_exists = H5B2_find(f, dxpl_id, H5A_BT2_NAME, ainfo->name_bt2_addr, &udata, NULL, NULL)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "can't search for attribute in name index")
+ else if(attr_exists == FALSE)
HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "can't locate attribute in name index")
done:
@@ -502,10 +505,10 @@ H5A_dense_insert(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, H5A_t *attr)
udata.common.dxpl_id = dxpl_id;
udata.common.fheap = fheap;
udata.common.shared_fheap = shared_fheap;
- udata.common.name = attr->name;
- udata.common.name_hash = H5_checksum_lookup3(attr->name, HDstrlen(attr->name), 0);
- udata.common.flags = mesg_flags;
- udata.common.corder = attr->crt_idx;
+ udata.common.name = attr->shared->name;
+ udata.common.name_hash = H5_checksum_lookup3(attr->shared->name, HDstrlen(attr->shared->name), 0);
+ H5_ASSIGN_OVERFLOW(udata.common.flags, mesg_flags, unsigned, uint8_t);
+ udata.common.corder = attr->shared->crt_idx;
udata.common.found_op = NULL;
udata.common.found_op_data = NULL;
/* udata.id already set */
@@ -624,7 +627,7 @@ H5A_dense_write_bt2_cb(void *_record, void *_op_data, hbool_t *changed)
udata.name = NULL;
udata.name_hash = 0;
udata.flags = 0;
- udata.corder = op_data->attr->crt_idx;
+ udata.corder = op_data->attr->shared->crt_idx;
udata.found_op = NULL;
udata.found_op_data = NULL;
@@ -744,8 +747,8 @@ H5A_dense_write(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, H5A_t *attr)
udata.dxpl_id = dxpl_id;
udata.fheap = fheap;
udata.shared_fheap = shared_fheap;
- udata.name = attr->name;
- udata.name_hash = H5_checksum_lookup3(attr->name, HDstrlen(attr->name), 0);
+ udata.name = attr->shared->name;
+ udata.name_hash = H5_checksum_lookup3(attr->shared->name, HDstrlen(attr->shared->name), 0);
udata.flags = 0;
udata.corder = 0;
udata.found_op = NULL;
@@ -807,7 +810,7 @@ H5A_dense_copy_fh_cb(const void *obj, size_t UNUSED obj_len, void *_udata)
HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, FAIL, "can't decode attribute")
/* Set the creation order index for the attribute */
- udata->attr->crt_idx = udata->record->corder;
+ udata->attr->shared->crt_idx = udata->record->corder;
/* Check whether we should "reconstitute" the shared message info */
if(udata->record->flags & H5O_MSG_FLAG_SHARED)
@@ -841,6 +844,7 @@ H5A_dense_rename(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char *
H5A_t *attr_copy = NULL; /* Copy of attribute to rename */
htri_t attr_sharable; /* Flag indicating attributes are sharable */
htri_t shared_mesg; /* Should this message be stored in the Shared Message table? */
+ htri_t attr_exists; /* Attribute exists in v2 B-tree */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5A_dense_rename, FAIL)
@@ -890,8 +894,10 @@ H5A_dense_rename(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char *
udata.found_op_data = &attr_copy;
/* Get copy of attribute through 'name' tracking v2 B-tree */
- if(H5B2_find(f, dxpl_id, H5A_BT2_NAME, ainfo->name_bt2_addr, &udata, NULL, NULL) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to find record in v2 B-tree")
+ if((attr_exists = H5B2_find(f, dxpl_id, H5A_BT2_NAME, ainfo->name_bt2_addr, &udata, NULL, NULL)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "can't search for attribute in name index")
+ else if(attr_exists == FALSE)
+ HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "can't locate attribute in name index")
HDassert(attr_copy);
/* Check if message is already shared */
@@ -904,8 +910,8 @@ H5A_dense_rename(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char *
} /* end if */
/* Change name of attribute */
- H5MM_xfree(attr_copy->name);
- attr_copy->name = H5MM_xstrdup(new_name);
+ H5MM_xfree(attr_copy->shared->name);
+ attr_copy->shared->name = H5MM_xstrdup(new_name);
/* Recompute the version to encode the attribute with */
if(H5A_set_version(f, attr_copy) < 0)
@@ -1020,20 +1026,27 @@ H5A_dense_iterate_bt2_cb(const void *_record, void *_bt2_udata)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, H5_ITER_ERROR, "unable to get attribute info")
/* Make the application callback */
- ret_value = (bt2_udata->attr_op->u.app_op2)(bt2_udata->loc_id, fh_udata.attr->name, &ainfo, bt2_udata->op_data);
+ ret_value = (bt2_udata->attr_op->u.app_op2)(bt2_udata->loc_id, fh_udata.attr->shared->name, &ainfo, bt2_udata->op_data);
break;
}
#ifndef H5_NO_DEPRECATED_SYMBOLS
case H5A_ATTR_OP_APP:
/* Make the application callback */
- ret_value = (bt2_udata->attr_op->u.app_op)(bt2_udata->loc_id, fh_udata.attr->name, bt2_udata->op_data);
+ ret_value = (bt2_udata->attr_op->u.app_op)(bt2_udata->loc_id, fh_udata.attr->shared->name, bt2_udata->op_data);
break;
#endif /* H5_NO_DEPRECATED_SYMBOLS */
case H5A_ATTR_OP_LIB:
/* Call the library's callback */
ret_value = (bt2_udata->attr_op->u.lib_op)(fh_udata.attr, bt2_udata->op_data);
+ break;
+
+ default:
+ HDassert("unknown attribute op type" && 0);
+#ifdef NDEBUG
+ HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "unsupported attribute op type")
+#endif /* NDEBUG */
} /* end switch */
/* Release the space allocated for the attribute */
@@ -1213,7 +1226,7 @@ H5A_dense_remove_bt2_cb(const void *_record, void *_udata)
/* Check for removing the link from the creation order index */
if(H5F_addr_defined(udata->corder_bt2_addr)) {
/* Set up the user data for the v2 B-tree 'record remove' callback */
- udata->common.corder = attr->crt_idx;
+ udata->common.corder = attr->shared->crt_idx;
/* Remove the record from the creation order index v2 B-tree */
if(H5B2_remove(udata->common.f, udata->common.dxpl_id, H5A_BT2_CORDER, udata->corder_bt2_addr, udata, NULL, NULL) < 0)
@@ -1393,7 +1406,7 @@ H5A_dense_remove_by_idx_bt2_cb(const void *_record, void *_bt2_udata)
other_bt2_class = H5A_BT2_CORDER;
/* Set up the user data for the v2 B-tree 'record remove' callback */
- other_bt2_udata.corder = fh_udata.attr->crt_idx;
+ other_bt2_udata.corder = fh_udata.attr->shared->crt_idx;
} /* end if */
else {
HDassert(bt2_udata->idx_type == H5_INDEX_CRT_ORDER);
@@ -1406,8 +1419,8 @@ H5A_dense_remove_by_idx_bt2_cb(const void *_record, void *_bt2_udata)
other_bt2_udata.dxpl_id = bt2_udata->dxpl_id;
other_bt2_udata.fheap = bt2_udata->fheap;
other_bt2_udata.shared_fheap = bt2_udata->shared_fheap;
- other_bt2_udata.name = fh_udata.attr->name;
- other_bt2_udata.name_hash = H5_checksum_lookup3(fh_udata.attr->name, HDstrlen(fh_udata.attr->name), 0);
+ other_bt2_udata.name = fh_udata.attr->shared->name;
+ other_bt2_udata.name_hash = H5_checksum_lookup3(fh_udata.attr->shared->name, HDstrlen(fh_udata.attr->shared->name), 0);
other_bt2_udata.found_op = NULL;
other_bt2_udata.found_op_data = NULL;
} /* end else */
@@ -1468,7 +1481,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5A_dense_remove_by_idx(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
+H5A_dense_remove_by_idx(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
H5_index_t idx_type, H5_iter_order_t order, hsize_t n)
{
H5HF_t *fheap = NULL; /* Fractal heap handle */
@@ -1563,7 +1576,7 @@ H5A_dense_remove_by_idx(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified")
/* Delete appropriate attribute from dense storage */
- if(H5A_dense_remove(f, dxpl_id, ainfo, atable.attrs[n].name) < 0)
+ if(H5A_dense_remove(f, dxpl_id, ainfo, ((atable.attrs[n])->shared)->name) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute in dense storage")
} /* end else */
@@ -1649,12 +1662,8 @@ H5A_dense_exists(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo, const char *
udata.found_op_data = NULL;
/* Find the attribute in the 'name' index */
- if(H5B2_find(f, dxpl_id, H5A_BT2_NAME, ainfo->name_bt2_addr, &udata, NULL, NULL) < 0) {
- /* Assume that the failure was just not finding the attribute & clear stack */
- H5E_clear_stack(NULL);
-
- ret_value = FALSE;
- } /* end if */
+ if((ret_value = H5B2_find(f, dxpl_id, H5A_BT2_NAME, ainfo->name_bt2_addr, &udata, NULL, NULL)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "can't search for attribute in name index")
done:
/* Release resources */
diff --git a/src/H5Adeprec.c b/src/H5Adeprec.c
index 9f888c8..77f5736 100644
--- a/src/H5Adeprec.c
+++ b/src/H5Adeprec.c
@@ -214,7 +214,7 @@ H5Aopen_name(hid_t loc_id, const char *name)
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "can't open attribute")
/* Register the attribute and get an ID for it */
- if((ret_value = H5I_register(H5I_ATTR, attr)) < 0)
+ if((ret_value = H5I_register(H5I_ATTR, attr, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register attribute for ID")
done:
@@ -270,7 +270,7 @@ H5Aopen_idx(hid_t loc_id, unsigned idx)
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open attribute")
/* Register the attribute and get an ID for it */
- if((ret_value = H5I_register(H5I_ATTR, attr)) < 0)
+ if((ret_value = H5I_register(H5I_ATTR, attr, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register attribute for ID")
done:
@@ -312,6 +312,8 @@ H5Aget_num_attrs(hid_t loc_id)
H5TRACE1("Is", "i", loc_id);
/* check arguments */
+ if(H5I_BADID == H5I_get_type(loc_id))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bad location ID")
if(H5I_FILE == H5I_get_type(loc_id) || H5I_ATTR == H5I_get_type(loc_id))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute")
if(NULL == (obj = H5I_object(loc_id)))
diff --git a/src/H5Aint.c b/src/H5Aint.c
index c08c6cf..aadf79c 100644
--- a/src/H5Aint.c
+++ b/src/H5Aint.c
@@ -100,6 +100,8 @@ static herr_t H5A_attr_sort_table(H5A_attr_table_t *atable, H5_index_t idx_type,
/* Local Variables */
/*******************/
+typedef H5A_t* H5A_t_ptr;
+H5FL_SEQ_DEFINE(H5A_t_ptr);
/*-------------------------------------------------------------------------
@@ -114,6 +116,10 @@ static herr_t H5A_attr_sort_table(H5A_attr_table_t *atable, H5_index_t idx_type,
* koziol@hdfgroup.org
* Dec 18 2006
*
+ * Modification:Raymond Lu
+ * 24 June 2008
+ * Changed the table of attribute objects to be the table of
+ * pointers to attribute objects for the ease of operation.
*-------------------------------------------------------------------------
*/
static herr_t
@@ -128,11 +134,23 @@ H5A_compact_build_table_cb(H5O_t UNUSED *oh, H5O_mesg_t *mesg/*in,out*/,
/* check args */
HDassert(mesg);
- /* Check for re-allocating table */
+ /* Re-allocate the table if necessary */
if(udata->curr_attr == udata->atable->nattrs) {
+ size_t i;
size_t n = MAX(1, 2 * udata->atable->nattrs);
- H5A_t *table = (H5A_t *)H5MM_realloc(udata->atable->attrs,
- n * sizeof(H5A_t));
+ H5A_t **table = (H5A_t **)H5FL_SEQ_CALLOC(H5A_t_ptr, n);
+
+ /* Use attribute functions for operation */
+ for(i=0; i<udata->atable->nattrs; i++) {
+ table[i] = (H5A_t *)H5FL_CALLOC(H5A_t);
+ if(NULL == H5A_copy(table[i], udata->atable->attrs[i]))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute")
+ if(H5A_close(udata->atable->attrs[i]) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCLOSEOBJ, H5_ITER_ERROR, "can't close attribute")
+ }
+
+ if(udata->atable->nattrs)
+ udata->atable->attrs = (H5A_t **)H5FL_SEQ_FREE(H5A_t_ptr, udata->atable->attrs);
if(!table)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5_ITER_ERROR, "unable to extend attribute table")
@@ -141,12 +159,14 @@ H5A_compact_build_table_cb(H5O_t UNUSED *oh, H5O_mesg_t *mesg/*in,out*/,
} /* end if */
/* Copy attribute into table */
- if(NULL == H5A_copy(&udata->atable->attrs[udata->curr_attr], (const H5A_t *)mesg->native))
+ udata->atable->attrs[udata->curr_attr] = (H5A_t *)H5FL_CALLOC(H5A_t);
+
+ if(NULL == H5A_copy(udata->atable->attrs[udata->curr_attr], (const H5A_t *)mesg->native))
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute")
/* Assign [somewhat arbitrary] creation order value, if requested */
if(udata->bogus_crt_idx)
- udata->atable->attrs[udata->curr_attr].crt_idx = sequence;
+ ((udata->atable->attrs[udata->curr_attr])->shared)->crt_idx = sequence;
/* Increment current attribute */
udata->curr_attr++;
@@ -197,8 +217,8 @@ H5A_compact_build_table(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5_index_t idx_type,
udata.dxpl_id = dxpl_id;
udata.atable = atable;
udata.curr_attr = 0;
- udata.bogus_crt_idx = (oh->version == H5O_VERSION_1 ||
- !(oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED)) ? TRUE : FALSE;
+ udata.bogus_crt_idx = (hbool_t)((oh->version == H5O_VERSION_1 ||
+ !(oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED)) ? TRUE : FALSE);
/* Iterate over existing attributes, checking for attribute with same name */
op.op_type = H5O_MESG_OP_LIB;
@@ -246,8 +266,8 @@ H5A_dense_build_table_cb(const H5A_t *attr, void *_udata)
HDassert(udata);
HDassert(udata->curr_attr < udata->atable->nattrs);
- /* Copy attribute information */
- if(NULL == H5A_copy(&udata->atable->attrs[udata->curr_attr], attr))
+ /* Copy attribute information. Share the attribute object in copying. */
+ if(NULL == H5A_copy(udata->atable->attrs[udata->curr_attr], attr))
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute")
/* Increment number of attributes stored */
@@ -305,11 +325,17 @@ H5A_dense_build_table(H5F_t *f, hid_t dxpl_id, const H5O_ainfo_t *ainfo,
if(atable->nattrs > 0) {
H5A_dense_bt_ud_t udata; /* User data for iteration callback */
H5A_attr_iter_op_t attr_op; /* Attribute operator */
+ unsigned i;
/* Allocate the table to store the attributes */
- if((atable->attrs = (H5A_t *)H5MM_malloc(sizeof(H5A_t) * atable->nattrs)) == NULL)
+ if((atable->attrs = (H5A_t **)H5FL_SEQ_MALLOC(H5A_t_ptr, atable->nattrs)) == NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ /* Allocate pointers for each entry in the table */
+ for(i=0; i<atable->nattrs; i++)
+ if((atable->attrs[i] = (H5A_t *)H5FL_CALLOC(H5A_t)) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
/* Set up user data for iteration */
udata.atable = atable;
udata.curr_attr = 0;
@@ -358,7 +384,8 @@ H5A_attr_cmp_name_inc(const void *attr1, const void *attr2)
{
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_attr_cmp_name_inc)
- FUNC_LEAVE_NOAPI(HDstrcmp(((const H5A_t *)attr1)->name, ((const H5A_t *)attr2)->name))
+ FUNC_LEAVE_NOAPI(HDstrcmp((*(const H5A_t * const *)attr1)->shared->name,
+ (*(const H5A_t * const *)attr2)->shared->name))
} /* end H5A_attr_cmp_name_inc() */
@@ -385,7 +412,8 @@ H5A_attr_cmp_name_dec(const void *attr1, const void *attr2)
{
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_attr_cmp_name_dec)
- FUNC_LEAVE_NOAPI(HDstrcmp(((const H5A_t *)attr2)->name, ((const H5A_t *)attr1)->name))
+ FUNC_LEAVE_NOAPI(HDstrcmp((*(const H5A_t * const *)attr2)->shared->name,
+ (*(const H5A_t * const *)attr1)->shared->name))
} /* end H5A_attr_cmp_name_dec() */
@@ -413,9 +441,9 @@ H5A_attr_cmp_corder_inc(const void *attr1, const void *attr2)
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_attr_cmp_corder_inc)
- if(((const H5A_t *)attr1)->crt_idx < ((const H5A_t *)attr2)->crt_idx)
+ if((*(const H5A_t * const *)attr1)->shared->crt_idx < (*(const H5A_t * const *)attr2)->shared->crt_idx)
ret_value = -1;
- else if(((const H5A_t *)attr1)->crt_idx > ((const H5A_t *)attr2)->crt_idx)
+ else if((*(const H5A_t * const *)attr1)->shared->crt_idx > (*(const H5A_t * const *)attr2)->shared->crt_idx)
ret_value = 1;
else
ret_value = 0;
@@ -448,9 +476,9 @@ H5A_attr_cmp_corder_dec(const void *attr1, const void *attr2)
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_attr_cmp_corder_dec)
- if(((const H5A_t *)attr1)->crt_idx < ((const H5A_t *)attr2)->crt_idx)
+ if((*(const H5A_t * const *)attr1)->shared->crt_idx < (*(const H5A_t * const *)attr2)->shared->crt_idx)
ret_value = 1;
- else if(((const H5A_t *)attr1)->crt_idx > ((const H5A_t *)attr2)->crt_idx)
+ else if((*(const H5A_t * const *)attr1)->shared->crt_idx > (*(const H5A_t * const *)attr2)->shared->crt_idx)
ret_value = -1;
else
ret_value = 0;
@@ -484,18 +512,18 @@ H5A_attr_sort_table(H5A_attr_table_t *atable, H5_index_t idx_type,
/* Pick appropriate comparison routine */
if(idx_type == H5_INDEX_NAME) {
if(order == H5_ITER_INC)
- HDqsort(atable->attrs, atable->nattrs, sizeof(H5A_t), H5A_attr_cmp_name_inc);
+ HDqsort(atable->attrs, atable->nattrs, sizeof(H5A_t*), H5A_attr_cmp_name_inc);
else if(order == H5_ITER_DEC)
- HDqsort(atable->attrs, atable->nattrs, sizeof(H5A_t), H5A_attr_cmp_name_dec);
+ HDqsort(atable->attrs, atable->nattrs, sizeof(H5A_t*), H5A_attr_cmp_name_dec);
else
HDassert(order == H5_ITER_NATIVE);
} /* end if */
else {
HDassert(idx_type == H5_INDEX_CRT_ORDER);
if(order == H5_ITER_INC)
- HDqsort(atable->attrs, atable->nattrs, sizeof(H5A_t), H5A_attr_cmp_corder_inc);
+ HDqsort(atable->attrs, atable->nattrs, sizeof(H5A_t*), H5A_attr_cmp_corder_inc);
else if(order == H5_ITER_DEC)
- HDqsort(atable->attrs, atable->nattrs, sizeof(H5A_t), H5A_attr_cmp_corder_dec);
+ HDqsort(atable->attrs, atable->nattrs, sizeof(H5A_t*), H5A_attr_cmp_corder_dec);
else
HDassert(order == H5_ITER_NATIVE);
} /* end else */
@@ -546,24 +574,31 @@ H5A_attr_iterate_table(const H5A_attr_table_t *atable, hsize_t skip,
H5A_info_t ainfo; /* Info for attribute */
/* Get the attribute information */
- if(H5A_get_info(&atable->attrs[u], &ainfo) < 0)
+ if(H5A_get_info(atable->attrs[u], &ainfo) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, H5_ITER_ERROR, "unable to get attribute info")
/* Make the application callback */
- ret_value = (attr_op->u.app_op2)(loc_id, atable->attrs[u].name, &ainfo, op_data);
+ ret_value = (attr_op->u.app_op2)(loc_id, ((atable->attrs[u])->shared)->name, &ainfo, op_data);
break;
}
#ifndef H5_NO_DEPRECATED_SYMBOLS
case H5A_ATTR_OP_APP:
/* Make the application callback */
- ret_value = (attr_op->u.app_op)(loc_id, atable->attrs[u].name, op_data);
+ ret_value = (attr_op->u.app_op)(loc_id, ((atable->attrs[u])->shared)->name, op_data);
break;
#endif /* H5_NO_DEPRECATED_SYMBOLS */
case H5A_ATTR_OP_LIB:
/* Call the library's callback */
- ret_value = (attr_op->u.lib_op)(&(atable->attrs[u]), op_data);
+ ret_value = (attr_op->u.lib_op)((atable->attrs[u]), op_data);
+ break;
+
+ default:
+ HDassert("unknown attribute op type" && 0);
+#ifdef NDEBUG
+ HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "unsupported attribute op type")
+#endif /* NDEBUG */
} /* end switch */
/* Increment the number of entries passed through */
@@ -581,22 +616,25 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5A_attr_release_table
+ * Function: H5A_attr_release_table
*
- * Purpose: Release table containing a list of attributes for an object
+ * Purpose: Release table containing a list of attributes for an object
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: Success: Non-negative
+ * Failure: Negative
*
- * Programmer: Quincey Koziol
- * Dec 11, 2006
+ * Programmer: Quincey Koziol
+ * Dec 11, 2006
*
+ * Modification: Raymond Lu
+ * 4 June 2008
+ * Changed from H5A_free to H5A_close to release attributes.
*-------------------------------------------------------------------------
*/
herr_t
H5A_attr_release_table(H5A_attr_table_t *atable)
{
- size_t u; /* Local index variable */
+ size_t u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5A_attr_release_table)
@@ -604,19 +642,19 @@ H5A_attr_release_table(H5A_attr_table_t *atable)
/* Sanity check */
HDassert(atable);
- /* Release attribute info, if any */
+ /* Release attribute info, if any. */
if(atable->nattrs > 0) {
/* Free attribute message information */
- for(u = 0; u < atable->nattrs; u++)
- if(H5A_free(&(atable->attrs[u])) < 0)
+ for(u = 0; u < atable->nattrs; u++) {
+ if(H5A_close((atable->attrs[u])) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to release attribute")
-
- /* Free table of attributes */
- H5MM_xfree(atable->attrs);
+ }
} /* end if */
else
HDassert(atable->attrs == NULL);
+ atable->attrs = (H5A_t **)H5FL_SEQ_FREE(H5A_t_ptr, atable->attrs);
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5A_attr_release_table() */
@@ -641,7 +679,7 @@ H5O_ainfo_t *
H5A_get_ainfo(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5O_ainfo_t *ainfo)
{
H5O_ainfo_t *ret_value; /* Return value */
-
+
FUNC_ENTER_NOAPI(H5A_get_ainfo, NULL)
/* check arguments */
@@ -649,7 +687,7 @@ H5A_get_ainfo(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5O_ainfo_t *ainfo)
HDassert(oh);
/* Retrieve the "attribute info" structure */
- if((ret_value = H5O_msg_read_real(f, dxpl_id, oh, H5O_AINFO_ID, ainfo))) {
+ if((ret_value = (H5O_ainfo_t *)H5O_msg_read_real(f, dxpl_id, oh, H5O_AINFO_ID, ainfo))) {
/* Check if we don't know how many attributes there are */
if(ret_value->nattrs == HSIZET_MAX) {
/* Check if we are using "dense" attribute storage */
@@ -693,7 +731,7 @@ H5A_set_version(const H5F_t *f, H5A_t *attr)
{
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 */
-
+
FUNC_ENTER_NOAPI_NOFUNC(H5A_set_version)
/* check arguments */
@@ -704,25 +742,25 @@ H5A_set_version(const H5F_t *f, H5A_t *attr)
use_latest_format = H5F_USE_LATEST_FORMAT(f);
/* Check whether datatype and dataspace are shared */
- if(H5O_msg_is_shared(H5O_DTYPE_ID, attr->dt) > 0)
+ if(H5O_msg_is_shared(H5O_DTYPE_ID, attr->shared->dt) > 0)
type_shared = TRUE;
else
type_shared = FALSE;
- if(H5O_msg_is_shared(H5O_SDSPACE_ID, attr->ds) > 0)
+ if(H5O_msg_is_shared(H5O_SDSPACE_ID, attr->shared->ds) > 0)
space_shared = TRUE;
else
space_shared = FALSE;
/* Check which version to encode attribute with */
if(use_latest_format)
- attr->version = H5O_ATTR_VERSION_LATEST; /* Write out latest version of format */
- else if(attr->encoding != H5T_CSET_ASCII)
- attr->version = H5O_ATTR_VERSION_3; /* Write version which includes the character encoding */
+ attr->shared->version = H5O_ATTR_VERSION_LATEST; /* Write out latest version of format */
+ else if(attr->shared->encoding != H5T_CSET_ASCII)
+ attr->shared->version = H5O_ATTR_VERSION_3; /* Write version which includes the character encoding */
else if(type_shared || space_shared)
- attr->version = H5O_ATTR_VERSION_2; /* Write out version with flag for indicating shared datatype or dataspace */
+ attr->shared->version = H5O_ATTR_VERSION_2; /* Write out version with flag for indicating shared datatype or dataspace */
else
- attr->version = H5O_ATTR_VERSION_1; /* Write out basic version */
+ attr->shared->version = H5O_ATTR_VERSION_1; /* Write out basic version */
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5A_set_version() */
diff --git a/src/H5Apkg.h b/src/H5Apkg.h
index 049877e..a1b5e62 100644
--- a/src/H5Apkg.h
+++ b/src/H5Apkg.h
@@ -72,16 +72,11 @@
/****************************/
/* Package Private Typedefs */
/****************************/
-
-/* Define the main attribute structure */
-struct H5A_t {
- H5O_shared_t sh_loc; /* Shared message info (must be first) */
-
+/* Define the shared attribute structure */
+typedef struct H5A_shared_t {
unsigned version; /* Version to encode attribute with */
hbool_t initialized;/* Indicate whether the attribute has been modified */
- hbool_t obj_opened; /* Object header entry opened? */
H5O_loc_t oloc; /* Object location for object attribute is on */
- H5G_name_t path; /* Group hierarchy path */
char *name; /* Attribute's name */
H5T_cset_t encoding; /* Character encoding of attribute name */
@@ -95,6 +90,15 @@ struct H5A_t {
void *data; /* Attribute data (on a temporary basis) */
size_t data_size; /* Size of data on disk */
H5O_msg_crt_idx_t crt_idx; /* Attribute's creation index in the object header */
+ unsigned nrefs; /* Ref count for times this object is refered */
+} H5A_shared_t;
+
+/* Define the main attribute structure */
+struct H5A_t {
+ H5O_shared_t sh_loc; /* Shared message info (must be first) */
+ hbool_t obj_opened; /* Object header entry opened? */
+ H5G_name_t path; /* Group hierarchy path */
+ H5A_shared_t *shared; /* Shared attribute information */
};
/* Typedefs for "dense" attribute storage */
@@ -152,7 +156,7 @@ typedef struct H5A_bt2_ud_ins_t {
/* Data structure to hold table of attributes for an object */
typedef struct {
size_t nattrs; /* # of attributes in table */
- H5A_t *attrs; /* Pointer to array of attributes */
+ H5A_t **attrs; /* Pointer to array of attribute pointers */
} H5A_attr_table_t;
/* Attribute iteration operator for internal library callbacks */
@@ -184,6 +188,9 @@ struct H5A_attr_iter_op_t {
/* Declare extern the free list for H5A_t's */
H5FL_EXTERN(H5A_t);
+/* Declare the external free lists for H5A_shared_t's */
+H5FL_EXTERN(H5A_shared_t);
+
/* Declare extern a free list to manage blocks of type conversion data */
H5FL_BLK_EXTERN(attr_buf);
@@ -206,6 +213,7 @@ H5_DLL H5A_t * H5A_open_by_name(const H5G_loc_t *loc, const char *obj_name,
const char *attr_name, hid_t lapl_id, hid_t dxpl_id);
H5_DLL H5A_t *H5A_open_by_idx(const H5G_loc_t *loc, const char *obj_name,
H5_index_t idx_type, H5_iter_order_t order, hsize_t n, hid_t lapl_id, hid_t dxpl_id);
+H5_DLL ssize_t H5A_get_name(H5A_t *attr, size_t buf_size, char *buf);
H5_DLL H5A_t *H5A_copy(H5A_t *new_attr, const H5A_t *old_attr);
H5_DLL herr_t H5A_get_info(const H5A_t *attr, H5A_info_t *ainfo);
H5_DLL herr_t H5A_free(H5A_t *attr);
diff --git a/src/H5Apublic.h b/src/H5Apublic.h
index 3586bad..99ca90e 100644
--- a/src/H5Apublic.h
+++ b/src/H5Apublic.h
@@ -48,7 +48,7 @@ H5_DLL hid_t H5Acreate_by_name(hid_t loc_id, const char *obj_name, const char
H5_DLL hid_t H5Aopen(hid_t obj_id, const char *attr_name, hid_t aapl_id);
H5_DLL hid_t H5Aopen_by_name(hid_t loc_id, const char *obj_name,
const char *attr_name, hid_t aapl_id, hid_t lapl_id);
-H5_DLL hid_t H5Aopen_by_idx(hid_t loc_id, const char *obj_name,
+H5_DLL hid_t H5Aopen_by_idx(hid_t loc_id, const char *obj_name,
H5_index_t idx_type, H5_iter_order_t order, hsize_t n, hid_t aapl_id,
hid_t lapl_id);
H5_DLL herr_t H5Awrite(hid_t attr_id, hid_t type_id, const void *buf);
@@ -86,7 +86,7 @@ H5_DLL htri_t H5Aexists_by_name(hid_t obj_id, const char *obj_name,
const char *attr_name, hid_t lapl_id);
/* Symbols defined for compatibility with previous versions of the HDF5 API.
- *
+ *
* Use of these symbols is deprecated.
*/
#ifndef H5_NO_DEPRECATED_SYMBOLS
diff --git a/src/H5Atest.c b/src/H5Atest.c
index df88472..de03a25 100644
--- a/src/H5Atest.c
+++ b/src/H5Atest.c
@@ -139,7 +139,7 @@ H5A_get_shared_rc_test(hid_t attr_id, hsize_t *ref_count)
HDassert(H5O_msg_is_shared(H5O_ATTR_ID, attr));
/* Retrieve ref count for shared or shareable attribute */
- if(H5SM_get_refcount(attr->oloc.file, H5AC_ind_dxpl_id, H5O_ATTR_ID,
+ if(H5SM_get_refcount(attr->shared->oloc.file, H5AC_ind_dxpl_id, H5O_ATTR_ID,
&attr->sh_loc, ref_count) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't retrieve shared message ref count")
diff --git a/src/H5B.c b/src/H5B.c
index 9847b7a..9d317c8 100644
--- a/src/H5B.c
+++ b/src/H5B.c
@@ -98,36 +98,40 @@
/****************/
#define H5B_PACKAGE /*suppress error about including H5Bpkg */
-#define H5F_PACKAGE /*suppress error about including H5Fpkg */
/***********/
/* Headers */
/***********/
#include "H5private.h" /* Generic Functions */
-#include "H5ACprivate.h" /* Metadata cache */
#include "H5Bpkg.h" /* B-link trees */
#include "H5Dprivate.h" /* Datasets */
#include "H5Eprivate.h" /* Error handling */
-#include "H5Fpkg.h" /* File access */
#include "H5Iprivate.h" /* IDs */
#include "H5MFprivate.h" /* File memory management */
-#include "H5MMprivate.h" /* Memory management */
#include "H5Pprivate.h" /* Property lists */
+
/****************/
/* Local Macros */
/****************/
#define H5B_SIZEOF_HDR(F) \
- (H5B_SIZEOF_MAGIC + /*magic number */ \
+ (H5_SIZEOF_MAGIC + /*magic number */ \
4 + /*type, level, num entries */ \
2*H5F_SIZEOF_ADDR(F)) /*left and right sibling addresses */
-#define H5B_NKEY(b,shared,idx) ((b)->native+(shared)->nkey[(idx)])
+
/******************/
/* Local Typedefs */
/******************/
+/* "user data" for iterating over B-tree (collects B-tree metadata size) */
+typedef struct H5B_iter_ud_t {
+ H5B_info_t *bt_info; /* Information about B-tree */
+ void *udata; /* Node type's 'udata' for loading & iterator callback */
+} H5B_info_ud_t;
+
+
/********************/
/* Local Prototypes */
/********************/
@@ -146,10 +150,7 @@ static herr_t H5B_split(H5F_t *f, hid_t dxpl_id, H5B_t *old_bt,
unsigned *old_bt_flags, haddr_t old_addr,
unsigned idx, void *udata, haddr_t *new_addr/*out*/);
static H5B_t * H5B_copy(const H5B_t *old_bt);
-#ifdef H5B_DEBUG
-static herr_t H5B_assert(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type,
- void *udata);
-#endif
+
/*********************/
/* Package Variables */
@@ -164,17 +165,26 @@ H5FL_BLK_DEFINE(native_block);
/* Declare a free list to manage the H5B_t struct */
H5FL_DEFINE(H5B_t);
+
/*****************************/
/* Library Private Variables */
/*****************************/
-/* Declare a free list to manage the H5B_shared_t struct */
-H5FL_DEFINE(H5B_shared_t);
/*******************/
/* Local Variables */
/*******************/
+/* Declare a free list to manage the H5B_shared_t struct */
+H5FL_DEFINE_STATIC(H5B_shared_t);
+
+/* Declare a free list to manage the raw page information */
+H5FL_BLK_DEFINE_STATIC(page);
+
+/* Declare a free list to manage the native key offset sequence information */
+H5FL_SEQ_DEFINE_STATIC(size_t);
+
+
/*-------------------------------------------------------------------------
* Function: H5B_create
@@ -280,9 +290,9 @@ done:
* pointers since it assumes that all nodes can be reached
* from the parent node.
*
- * Return: Non-negative on success (if found, values returned through the
- * UDATA argument). Negative on failure (if not found, UDATA is
- * undefined).
+ * Return: Non-negative (TRUE/FALSE) on success (if found, values returned
+ * through the UDATA argument). Negative on failure (if not found,
+ * UDATA is undefined).
*
* Programmer: Robb Matzke
* matzke@llnl.gov
@@ -293,90 +303,65 @@ done:
* The ADDR argument is passed by value.
*-------------------------------------------------------------------------
*/
-herr_t
+htri_t
H5B_find(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, haddr_t addr, void *udata)
{
H5B_t *bt = NULL;
- H5B_shared_t *shared; /* Pointer to shared B-tree info */
- unsigned idx=0, lt = 0, rt; /* Final, left & right key indices */
+ H5B_shared_t *shared; /* Pointer to shared B-tree info */
+ unsigned idx = 0, lt = 0, rt; /* Final, left & right key indices */
int cmp = 1; /* Key comparison value */
- int ret_value = SUCCEED; /* Return value */
+ htri_t ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5B_find, FAIL)
/*
* Check arguments.
*/
- assert(f);
- assert(type);
- assert(type->decode);
- assert(type->cmp3);
- assert(type->found);
- assert(H5F_addr_defined(addr));
+ HDassert(f);
+ HDassert(type);
+ HDassert(type->decode);
+ HDassert(type->cmp3);
+ HDassert(type->found);
+ HDassert(H5F_addr_defined(addr));
/*
* Perform a binary search to locate the child which contains
* the thing for which we're searching.
*/
- if (NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, type, udata, H5AC_READ)))
+ if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, type, udata, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load B-tree node")
- shared=(H5B_shared_t *)H5RC_GET_OBJ(bt->rc_shared);
+ shared = (H5B_shared_t *)H5RC_GET_OBJ(bt->rc_shared);
HDassert(shared);
- rt = bt->nchildren;
- while (lt < rt && cmp) {
+ rt = bt->nchildren;
+ while(lt < rt && cmp) {
idx = (lt + rt) / 2;
/* compare */
- if ((cmp = (type->cmp3) (f, dxpl_id, H5B_NKEY(bt,shared,idx), udata,
- H5B_NKEY(bt,shared,idx+1))) < 0) {
+ if((cmp = (type->cmp3)(f, dxpl_id, H5B_NKEY(bt, shared, idx), udata, H5B_NKEY(bt, shared, (idx + 1)))) < 0)
rt = idx;
- } else {
- lt = idx+1;
- }
- }
- if (cmp)
- /* Note: don't push error on stack, leave that to next higher level,
- * since many times the B-tree is searched in order to determine
- * if an object exists in the B-tree or not. -QAK
- */
-#ifdef OLD_WAY
- HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "B-tree key not found")
-#else /* OLD_WAY */
- HGOTO_DONE(FAIL)
-#endif /* OLD_WAY */
+ else
+ lt = idx + 1;
+ } /* end while */
+ /* Check if not found */
+ if(cmp)
+ HGOTO_DONE(FALSE)
/*
* Follow the link to the subtree or to the data node.
*/
assert(idx < bt->nchildren);
- if (bt->level > 0) {
- if (H5B_find(f, dxpl_id, type, bt->child[idx], udata) < 0)
- /* Note: don't push error on stack, leave that to next higher level,
- * since many times the B-tree is searched in order to determine
- * if an object exists in the B-tree or not. -QAK
- */
-#ifdef OLD_WAY
- HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "key not found in subtree")
-#else /* OLD_WAY */
- HGOTO_DONE(FAIL)
-#endif /* OLD_WAY */
- } else {
- if ((type->found) (f, dxpl_id, bt->child[idx], H5B_NKEY(bt,shared,idx), udata) < 0)
- /* Note: don't push error on stack, leave that to next higher level,
- * since many times the B-tree is searched in order to determine
- * if an object exists in the B-tree or not. -QAK
- */
-#ifdef OLD_WAY
- HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "key not found in leaf node")
-#else /* OLD_WAY */
- HGOTO_DONE(FAIL)
-#endif /* OLD_WAY */
- }
+ if(bt->level > 0) {
+ if((ret_value = H5B_find(f, dxpl_id, type, bt->child[idx], udata)) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "can't lookup key in subtree")
+ } /* end if */
+ else {
+ if((ret_value = (type->found)(f, dxpl_id, bt->child[idx], H5B_NKEY(bt, shared, idx), udata)) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "can't lookup key in leaf node")
+ } /* end else */
done:
- if (bt && H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, H5AC__NO_FLAGS_SET)
- < 0)
+ if(bt && H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release node")
FUNC_LEAVE_NOAPI(ret_value)
@@ -1143,10 +1128,10 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5B_iterate
+ * Function: H5B_iterate_helper
*
* Purpose: Calls the list callback for each leaf node of the
- * B-tree, passing it the UDATA structure.
+ * B-tree, passing it the caller's UDATA structure.
*
* Return: Non-negative on success/Negative on failure
*
@@ -1154,106 +1139,167 @@ done:
* matzke@llnl.gov
* Jun 23 1997
*
- * Modifications:
- * Robb Matzke, 1999-04-21
- * The key values are passed to the function which is called.
- *
- * Robb Matzke, 1999-07-28
- * The ADDR argument is passed by value.
- *
- * Quincey Koziol, 2002-04-22
- * Changed callback to function pointer from static function
- *
- * John Mainzer, 6/10/05
- * Modified the function to use the new dirtied parameter of
- * of H5AC_unprotect() instead of modifying the is_dirty
- * field of the cache info.
- *
*-------------------------------------------------------------------------
*/
-herr_t
-H5B_iterate(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, H5B_operator_t op, haddr_t addr, void *udata)
+static herr_t
+H5B_iterate_helper(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, haddr_t addr,
+ H5B_operator_t op, void *udata)
{
H5B_t *bt = NULL; /* Pointer to current B-tree node */
+ uint8_t *native = NULL; /* Array of keys in native format */
+ haddr_t *child = NULL; /* Array of child pointers */
herr_t ret_value; /* Return value */
- FUNC_ENTER_NOAPI(H5B_iterate, FAIL)
+ FUNC_ENTER_NOAPI_NOINIT(H5B_iterate_helper)
/*
* Check arguments.
*/
HDassert(f);
HDassert(type);
- HDassert(op);
HDassert(H5F_addr_defined(addr));
+ HDassert(op);
HDassert(udata);
/* Protect the initial/current node */
if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, type, udata, H5AC_READ)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load B-tree node")
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, H5_ITER_ERROR, "unable to load B-tree node")
if(bt->level > 0) {
+ haddr_t left_child = bt->child[0]; /* Address of left-most child in node */
+
+ /* Release current node */
+ if(H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_PROTECT, H5_ITER_ERROR, "unable to release B-tree node")
+ bt = NULL;
+
/* Keep following the left-most child until we reach a leaf node. */
- if((ret_value = H5B_iterate(f, dxpl_id, type, op, bt->child[0], udata)) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTLIST, FAIL, "unable to list B-tree node")
+ if((ret_value = H5B_iterate_helper(f, dxpl_id, type, left_child, op, udata)) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTLIST, H5_ITER_ERROR, "unable to list B-tree node")
} /* end if */
else {
+ H5B_shared_t *shared; /* Pointer to shared B-tree info */
+ unsigned nchildren; /* Number of child pointers */
+ haddr_t next_addr; /* Address of next node to the right */
+
+ /* Get the shared B-tree information */
+ shared = (H5B_shared_t *)H5RC_GET_OBJ(bt->rc_shared);
+ HDassert(shared);
+
+ /* Allocate space for a copy of the native records & child pointers */
+ if(NULL == (native = H5FL_BLK_MALLOC(native_block, shared->sizeof_keys)))
+ HGOTO_ERROR(H5E_BTREE, H5E_NOSPACE, H5_ITER_ERROR, "memory allocation failed for shared B-tree native records")
+ if(NULL == (child = H5FL_SEQ_MALLOC(haddr_t, (size_t)shared->two_k)))
+ HGOTO_ERROR(H5E_BTREE, H5E_NOSPACE, H5_ITER_ERROR, "memory allocation failed for shared B-tree child addresses")
+
+ /* Cache information from this node */
+ nchildren = bt->nchildren;
+ next_addr = bt->right;
+
+ /* Copy the native keys & child pointers into local arrays */
+ HDmemcpy(native, bt->native, shared->sizeof_keys);
+ HDmemcpy(child, bt->child, (nchildren * sizeof(haddr_t)));
+
+ /* Release current node */
+ if(H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_PROTECT, H5_ITER_ERROR, "unable to release B-tree node")
+ bt = NULL;
+
/*
* We've reached the left-most leaf. Now follow the right-sibling
* pointer from leaf to leaf until we've processed all leaves.
*/
ret_value = H5_ITER_CONT;
- while(bt && ret_value == H5_ITER_CONT) {
- haddr_t *child; /* Pointer to node's child addresses */
- uint8_t *key; /* Pointer to node's native keys */
+ while(ret_value == H5_ITER_CONT) {
+ haddr_t *curr_child; /* Pointer to node's child addresses */
+ uint8_t *curr_native; /* Pointer to node's native keys */
unsigned u; /* Local index variable */
/*
* Perform the iteration operator, which might invoke an
* application callback.
*/
- for(u = 0, child = bt->child, key = bt->native; u < bt->nchildren && ret_value == H5_ITER_CONT; u++, child++, key += type->sizeof_nkey) {
- ret_value = (*op)(f, dxpl_id, key, *child, key + type->sizeof_nkey, udata);
+ for(u = 0, curr_child = child, curr_native = native; u < nchildren && ret_value == H5_ITER_CONT; u++, curr_child++, curr_native += type->sizeof_nkey) {
+ ret_value = (*op)(f, dxpl_id, curr_native, *curr_child, curr_native + type->sizeof_nkey, udata);
if(ret_value < 0)
HERROR(H5E_BTREE, H5E_CANTLIST, "iterator function failed");
} /* end for */
/* Check for continuing iteration */
if(ret_value == H5_ITER_CONT) {
- H5B_t *next_bt; /* Pointer to next B-tree node */
- haddr_t next_addr; /* Address of next node to iterate over */
-
- /* Protect the next node to the right, if there is one */
- if(H5F_addr_defined(bt->right)) {
+ /* Check for another node */
+ if(H5F_addr_defined(next_addr)) {
+ /* Protect the next node to the right */
+ addr = next_addr;
+ if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, type, udata, H5AC_READ)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, H5_ITER_ERROR, "B-tree node")
+
+ /* Cache information from this node */
+ nchildren = bt->nchildren;
next_addr = bt->right;
- if(NULL == (next_bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, next_addr, type, udata, H5AC_READ)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "B-tree node")
- } /* end if */
- else {
- next_addr = HADDR_UNDEF;
- next_bt = NULL;
- } /* end if */
- /* Unprotect this node */
- if(H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, H5AC__NO_FLAGS_SET) < 0) {
- if(next_bt) {
- HDassert(H5F_addr_defined(next_addr));
- if(H5AC_unprotect(f, dxpl_id, H5AC_BT, next_addr, next_bt, H5AC__NO_FLAGS_SET) < 0)
- HDONE_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release B-tree node")
- } /* end if */
- HGOTO_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release B-tree node")
- } /* end if */
+ /* Copy the native keys & child pointers into local arrays */
+ HDmemcpy(native, bt->native, shared->sizeof_keys);
+ HDmemcpy(child, bt->child, nchildren * sizeof(haddr_t));
- /* Advance to the next node */
- bt = next_bt;
- addr = next_addr;
+ /* Unprotect node */
+ if(H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_PROTECT, H5_ITER_ERROR, "unable to release B-tree node")
+ bt = NULL;
+ } /* end if */
+ else
+ /* Exit loop */
+ break;
} /* end if */
- } /* end for */
+ } /* end while */
} /* end else */
done:
if(bt && H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, H5AC__NO_FLAGS_SET) < 0)
- HDONE_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release B-tree node")
+ HDONE_ERROR(H5E_BTREE, H5E_PROTECT, H5_ITER_ERROR, "unable to release B-tree node")
+ if(native)
+ (void)H5FL_BLK_FREE(native_block, native);
+ if(child)
+ (void)H5FL_SEQ_FREE(haddr_t, child);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5B_iterate_helper() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B_iterate
+ *
+ * Purpose: Calls the list callback for each leaf node of the
+ * B-tree, passing it the UDATA structure.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Jun 23 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5B_iterate(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, haddr_t addr,
+ H5B_operator_t op, void *udata)
+{
+ herr_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5B_iterate, FAIL)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(type);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(op);
+ HDassert(udata);
+
+ /* Iterate over the B-tree records */
+ if((ret_value = H5B_iterate_helper(f, dxpl_id, type, addr, op, udata)) < 0)
+ HERROR(H5E_BTREE, H5E_BADITER, "B-tree iteration failed");
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5B_iterate() */
@@ -1458,16 +1504,14 @@ H5B_remove_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type
bt->left = HADDR_UNDEF;
bt->right = HADDR_UNDEF;
H5_CHECK_OVERFLOW(shared->sizeof_rnode,size_t,hsize_t);
- if (H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, addr, (hsize_t)shared->sizeof_rnode)<0
- || H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, bt_flags | H5C__DELETED_FLAG)<0) {
+ if(H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, bt_flags | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0) {
bt = NULL;
bt_flags = H5AC__NO_FLAGS_SET;
HGOTO_ERROR(H5E_BTREE, H5E_PROTECT, H5B_INS_ERROR, "unable to free B-tree node")
- }
+ } /* end if */
bt = NULL;
bt_flags = H5AC__NO_FLAGS_SET;
- }
-
+ } /* end if */
} else if (H5B_INS_REMOVE==ret_value && 0==idx) {
/*
* The subtree is the left-most child of this node. We discard the
@@ -1691,12 +1735,8 @@ H5B_delete(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, haddr_t addr, void
} /* end if */
} /* end else */
- /* Delete this node from disk */
- if (H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, addr, (hsize_t)shared->sizeof_rnode)<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree node")
-
done:
- if (bt && H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, H5C__DELETED_FLAG)<0)
+ if(bt && H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG)<0)
HDONE_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release B-tree node in cache")
FUNC_LEAVE_NOAPI(ret_value)
@@ -1704,59 +1744,99 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5B_nodesize
- *
- * Purpose: Returns the number of bytes needed for this type of
- * B-tree node. The size is the size of the header plus
- * enough space for 2t child pointers and 2t+1 keys.
- *
- * If TOTAL_NKEY_SIZE is non-null, what it points to will
- * be initialized with the total number of bytes required to
- * hold all the key values in native order.
+ * Function: H5B_shared_new
*
- * Return: Success: Size of node in file.
+ * Purpose: Allocates & constructs a shared v1 B-tree struct for client.
*
- * Failure: 0
+ * Return: Success: non-NULL pointer to struct allocated
+ * Failure: NULL
*
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Jul 3 1997
- *
- * Modifications:
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * May 27 2008
*
*-------------------------------------------------------------------------
*/
-size_t
-H5B_nodesize(const H5F_t *f, const H5B_shared_t *shared,
- size_t *total_nkey_size/*out*/)
+H5B_shared_t *
+H5B_shared_new(const H5F_t *f, const H5B_class_t *type, size_t sizeof_rkey)
{
- size_t size;
+ H5B_shared_t *shared; /* New shared B-tree struct */
+ size_t u; /* Local index variable */
+ H5B_shared_t *ret_value; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5B_nodesize)
+ FUNC_ENTER_NOAPI(H5B_shared_new, NULL)
/*
* Check arguments.
*/
- assert(f);
- assert(shared);
- assert(shared->two_k > 0);
- assert(shared->sizeof_rkey > 0);
-
- /*
- * Total native key size.
- */
- if (total_nkey_size)
- *total_nkey_size = (shared->two_k + 1) * shared->type->sizeof_nkey;
+ HDassert(type);
- /*
- * Total node size.
- */
- size = (H5B_SIZEOF_HDR(f) + /*node header */
+ /* Allocate space for the shared structure */
+ if(NULL == (shared = H5FL_MALLOC(H5B_shared_t)))
+ HGOTO_ERROR(H5E_BTREE, H5E_NOSPACE, NULL, "memory allocation failed for shared B-tree info")
+
+ /* Set up the "global" information for this file's groups */
+ shared->type = type;
+ shared->two_k = 2 * H5F_KVALUE(f, type);
+ shared->sizeof_rkey = sizeof_rkey;
+ HDassert(shared->sizeof_rkey);
+ shared->sizeof_keys = (shared->two_k + 1) * type->sizeof_nkey;
+ shared->sizeof_rnode = (H5B_SIZEOF_HDR(f) + /*node header */
shared->two_k * H5F_SIZEOF_ADDR(f) + /*child pointers */
(shared->two_k + 1) * shared->sizeof_rkey); /*keys */
+ HDassert(shared->sizeof_rnode);
- FUNC_LEAVE_NOAPI(size)
-}
+ /* Allocate shared buffers */
+ if(NULL == (shared->page = H5FL_BLK_MALLOC(page, shared->sizeof_rnode)))
+ HGOTO_ERROR(H5E_BTREE, H5E_NOSPACE, NULL, "memory allocation failed for B-tree page")
+#ifdef H5_CLEAR_MEMORY
+HDmemset(shared->page, 0, shared->sizeof_rnode);
+#endif /* H5_CLEAR_MEMORY */
+ if(NULL == (shared->nkey = H5FL_SEQ_MALLOC(size_t, (size_t)(shared->two_k + 1))))
+ HGOTO_ERROR(H5E_BTREE, H5E_NOSPACE, NULL, "memory allocation failed for B-tree page")
+
+ /* Initialize the offsets into the native key buffer */
+ for(u = 0; u < (shared->two_k + 1); u++)
+ shared->nkey[u] = u * type->sizeof_nkey;
+
+ /* Set return value */
+ ret_value = shared;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5B_shared_new() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B_shared_free
+ *
+ * Purpose: Free B-tree shared info
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, May 27, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5B_shared_free(void *_shared)
+{
+ H5B_shared_t *shared = (H5B_shared_t *)_shared;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5B_shared_free)
+
+ /* Free the raw B-tree node buffer */
+ (void)H5FL_BLK_FREE(page, shared->page);
+
+ /* Free the B-tree native key offsets buffer */
+ (void)H5FL_SEQ_FREE(size_t, shared->nkey);
+
+ /* Free the shared B-tree info */
+ (void)H5FL_FREE(H5B_shared_t, shared);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5B_shared_free() */
/*-------------------------------------------------------------------------
@@ -1788,68 +1868,70 @@ H5B_copy(const H5B_t *old_bt)
/*
* Check arguments.
*/
- assert(old_bt);
- shared=(H5B_shared_t *)H5RC_GET_OBJ(old_bt->rc_shared);
+ HDassert(old_bt);
+ shared = (H5B_shared_t *)H5RC_GET_OBJ(old_bt->rc_shared);
HDassert(shared);
/* Allocate memory for the new H5B_t object */
- if (NULL==(new_node = H5FL_MALLOC(H5B_t)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for B-tree root node")
+ if(NULL == (new_node = H5FL_MALLOC(H5B_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for B-tree root node")
/* Copy the main structure */
- HDmemcpy(new_node,old_bt,sizeof(H5B_t));
+ HDmemcpy(new_node, old_bt, sizeof(H5B_t));
- if ( NULL==(new_node->native=H5FL_BLK_MALLOC(native_block,shared->sizeof_keys)) ||
- NULL==(new_node->child=H5FL_SEQ_MALLOC(haddr_t,(size_t)shared->two_k)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for B-tree root node")
+ if(NULL == (new_node->native = H5FL_BLK_MALLOC(native_block, shared->sizeof_keys)) ||
+ NULL == (new_node->child = H5FL_SEQ_MALLOC(haddr_t, (size_t)shared->two_k)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for B-tree root node")
/* Copy the other structures */
- HDmemcpy(new_node->native,old_bt->native,shared->sizeof_keys);
- HDmemcpy(new_node->child,old_bt->child,(sizeof(haddr_t)*shared->two_k));
+ HDmemcpy(new_node->native, old_bt->native, shared->sizeof_keys);
+ HDmemcpy(new_node->child, old_bt->child, (sizeof(haddr_t) * shared->two_k));
/* Increment the ref-count on the raw page */
H5RC_INC(new_node->rc_shared);
/* Set return value */
- ret_value=new_node;
+ ret_value = new_node;
done:
- if(ret_value==NULL) {
+ if(NULL == ret_value) {
if(new_node) {
- H5FL_BLK_FREE (native_block,new_node->native);
- H5FL_SEQ_FREE (haddr_t,new_node->child);
- H5FL_FREE (H5B_t,new_node);
+ (void)H5FL_BLK_FREE(native_block, new_node->native);
+ H5FL_SEQ_FREE(haddr_t, new_node->child);
+ (void)H5FL_FREE(H5B_t, new_node);
} /* end if */
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5B_copy */
+} /* end H5B_copy() */
/*-------------------------------------------------------------------------
- * Function: H5B_iterate_size
+ * Function: H5B_get_info_helper
*
- * Purpose: Return the amount of storage used for the btree.
- * Keep following the left-most child until reaching the leaf node.
- * For each level, gather storage for all the nodes on that level.
- * For 0 level, also gather storage for the SNODs.
+ * Purpose: Walks the B-tree nodes, getting information for all of them.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Vailin Choi
- * June 19, 2007
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jun 3 2008
*
*-------------------------------------------------------------------------
*/
-herr_t
-H5B_iterate_size(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type,
- H5B_operator_t op, haddr_t addr, H5B_info_ud_t *bh_udata)
+static herr_t
+H5B_get_info_helper(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, haddr_t addr,
+ const H5B_info_ud_t *info_udata)
{
- H5B_t *bt = NULL; /* Pointer to current B-tree node */
- H5B_shared_t *shared; /* Pointer to shared B-tree info */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5B_t *bt = NULL; /* Pointer to current B-tree node */
+ H5B_shared_t *shared; /* Pointer to shared B-tree info */
+ unsigned level; /* Node level */
+ size_t sizeof_rnode; /* Size of raw (disk) node */
+ haddr_t next_addr; /* Address of next node to the right */
+ haddr_t left_child; /* Address of left-most child in node */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5B_iterate_size, FAIL)
+ FUNC_ENTER_NOAPI_NOINIT(H5B_get_info_helper)
/*
* Check arguments.
@@ -1857,304 +1939,121 @@ H5B_iterate_size(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type,
HDassert(f);
HDassert(type);
HDassert(H5F_addr_defined(addr));
- HDassert(bh_udata);
+ HDassert(info_udata);
+ HDassert(info_udata->bt_info);
+ HDassert(info_udata->udata);
/* Protect the initial/current node */
- if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, type, bh_udata->udata, H5AC_READ)))
+ if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, type, info_udata->udata, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load B-tree node")
- shared = H5RC_GET_OBJ(bt->rc_shared);
+
+ /* Get the shared B-tree information */
+ shared = (H5B_shared_t *)H5RC_GET_OBJ(bt->rc_shared);
HDassert(shared);
- /* Keep following the left-most child until we reach a leaf node. */
- if(bt->level > 0)
- if(H5B_iterate_size(f, dxpl_id, type, op, bt->child[0], bh_udata) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTLIST, FAIL, "unable to list B-tree node")
+ /* Get the raw node size for iteration */
+ sizeof_rnode = shared->sizeof_rnode;
- /* Iterate through all nodes at this level of the tree */
- while(bt) {
- haddr_t next_addr; /* Address of next node to iterate over */
+ /* Cache information from this node */
+ left_child = bt->child[0];
+ next_addr = bt->right;
+ level = bt->level;
- /* for leaf node with callback, add in the space pointed to by each key */
- /* (currently only used for symbol table nodes) */
- if(bt->level == 0 && op) {
- haddr_t *child; /* Pointer to node's child addresses */
- uint8_t *key; /* Pointer to node's native keys */
- unsigned u; /* Local index variable */
+ /* Update B-tree info */
+ info_udata->bt_info->size += sizeof_rnode;
+ info_udata->bt_info->num_nodes++;
- for(u = 0, child = bt->child, key = bt->native; u < bt->nchildren; u++, child++, key += type->sizeof_nkey)
- if((*op)(f, dxpl_id, key, *child, key + type->sizeof_nkey, bh_udata->btree_size) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTLIST, FAIL, "iterator function failed")
- } /* end if */
+ /* Release current node */
+ if(H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release B-tree node")
+ bt = NULL;
- /* count the size of this node */
- *(bh_udata->btree_size) += H5B_nodesize(f, shared, NULL);
+ /*
+ * Follow the right-sibling pointer from node to node until we've
+ * processed all nodes.
+ */
+ while(H5F_addr_defined(next_addr)) {
+ /* Protect the next node to the right */
+ addr = next_addr;
+ if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, type, info_udata->udata, H5AC_READ)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "B-tree node")
- /* Get the address of the next node to the right */
+ /* Cache information from this node */
next_addr = bt->right;
- /* Unprotect current node */
- if(H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, H5AC__NO_FLAGS_SET) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release B-tree node")
+ /* Update B-tree info */
+ info_udata->bt_info->size += sizeof_rnode;
+ info_udata->bt_info->num_nodes++;
- /* Protect bt's next node to the right, if there is one */
- if(H5F_addr_defined(next_addr)) {
- addr = next_addr;
- if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, type, bh_udata->udata, H5AC_READ)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "B-tree node")
- } /* end if */
- else
- bt = NULL;
+ /* Unprotect node */
+ if(H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release B-tree node")
+ bt = NULL;
} /* end while */
+ /* Check for another "row" of B-tree nodes to iterate over */
+ if(level > 0) {
+ /* Keep following the left-most child until we reach a leaf node. */
+ if(H5B_get_info_helper(f, dxpl_id, type, left_child, info_udata) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTLIST, FAIL, "unable to list B-tree node")
+ } /* end if */
+
done:
if(bt && H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release B-tree node")
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5B_iterate_size() */
+} /* end H5B_get_info_helper() */
/*-------------------------------------------------------------------------
- * Function: H5B_debug
+ * Function: H5B_get_info
*
- * Purpose: Prints debugging info about a B-tree.
+ * Purpose: Return the amount of storage used for the btree.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative on success/Negative on failure
*
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Aug 4 1997
+ * Programmer: Vailin Choi
+ * June 19, 2007
*
- * Modifications:
- * Robb Matzke, 1999-07-28
- * The ADDR argument is passed by value.
*-------------------------------------------------------------------------
*/
herr_t
-H5B_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int fwidth,
- const H5B_class_t *type, void *udata)
+H5B_get_info(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, haddr_t addr,
+ H5B_info_t *bt_info, H5B_operator_t op, void *udata)
{
- H5B_t *bt = NULL;
- H5B_shared_t *shared; /* Pointer to shared B-tree info */
- unsigned u; /* Local index variable */
- herr_t ret_value=SUCCEED; /* Return value */
+ H5B_info_ud_t info_udata; /* User-data for B-tree size iteration */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5B_debug, FAIL)
+ FUNC_ENTER_NOAPI(H5B_get_info, FAIL)
/*
* Check arguments.
*/
- assert(f);
- assert(H5F_addr_defined(addr));
- assert(stream);
- assert(indent >= 0);
- assert(fwidth >= 0);
- assert(type);
-
- /*
- * Load the tree node.
- */
- if (NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, type, udata, H5AC_READ)))
- HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load B-tree node")
- shared=(H5B_shared_t *)H5RC_GET_OBJ(bt->rc_shared);
- HDassert(shared);
-
- /*
- * Print the values.
- */
- HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
- "Tree type ID:",
- ((shared->type->id)==H5B_SNODE_ID ? "H5B_SNODE_ID" :
- ((shared->type->id)==H5B_ISTORE_ID ? "H5B_ISTORE_ID" : "Unknown!")));
- HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth,
- "Size of node:",
- shared->sizeof_rnode);
- HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth,
- "Size of raw (disk) key:",
- shared->sizeof_rkey);
- HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
- "Dirty flag:",
- bt->cache_info.is_dirty ? "True" : "False");
- HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
- "Level:",
- bt->level);
-
- HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
- "Address of left sibling:",
- bt->left);
-
- HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
- "Address of right sibling:",
- bt->right);
-
- HDfprintf(stream, "%*s%-*s %u (%u)\n", indent, "", fwidth,
- "Number of children (max):",
- bt->nchildren, shared->two_k);
-
- /*
- * Print the child addresses
- */
- for (u = 0; u < bt->nchildren; u++) {
- HDfprintf(stream, "%*sChild %d...\n", indent, "", u);
- HDfprintf(stream, "%*s%-*s %a\n", indent + 3, "", MAX(0, fwidth - 3),
- "Address:", bt->child[u]);
-
- /* If there is a key debugging routine, use it to display the left & right keys */
- if (type->debug_key) {
- /* Decode the 'left' key & print it */
- HDfprintf(stream, "%*s%-*s\n", indent + 3, "", MAX(0, fwidth - 3),
- "Left Key:");
- assert(H5B_NKEY(bt,shared,u));
- (void)(type->debug_key)(stream, f, dxpl_id, indent+6, MAX (0, fwidth-6),
- H5B_NKEY(bt,shared,u), udata);
-
- /* Decode the 'right' key & print it */
- HDfprintf(stream, "%*s%-*s\n", indent + 3, "", MAX(0, fwidth - 3),
- "Right Key:");
- assert(H5B_NKEY(bt,shared,u+1));
- (void)(type->debug_key)(stream, f, dxpl_id, indent+6, MAX (0, fwidth-6),
- H5B_NKEY(bt,shared,u+1), udata);
- }
- }
-
-done:
- if (bt && H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, H5AC__NO_FLAGS_SET) < 0)
- HDONE_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release B-tree node")
-
- FUNC_LEAVE_NOAPI(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5B_assert
- *
- * Purpose: Verifies that the tree is structured correctly.
- *
- * Return: Success: SUCCEED
- *
- * Failure: aborts if something is wrong.
- *
- * Programmer: Robb Matzke
- * Tuesday, November 4, 1997
- *
- * Modifications:
- * Robb Matzke, 1999-07-28
- * The ADDR argument is passed by value.
- *
- * John Mainzer, 6/8/05
- * Modified the function to use the new dirtied parameter of
- * of H5AC_unprotect() instead of modifying the is_dirty
- * field of the cache info.
- *
- *-------------------------------------------------------------------------
- */
-#ifdef H5B_DEBUG
-static herr_t
-H5B_assert(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type, void *udata)
-{
- H5B_t *bt = NULL;
- H5B_shared_t *shared; /* Pointer to shared B-tree info */
- int i, ncell, cmp;
- static int ncalls = 0;
- herr_t status;
- herr_t ret_value=SUCCEED; /* Return value */
-
- /* A queue of child data */
- struct child_t {
- haddr_t addr;
- unsigned level;
- struct child_t *next;
- } *head = NULL, *tail = NULL, *prev = NULL, *cur = NULL, *tmp = NULL;
-
- FUNC_ENTER_NOAPI(H5B_assert, FAIL)
+ HDassert(f);
+ HDassert(type);
+ HDassert(bt_info);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(udata);
- if (0==ncalls++) {
- if (H5DEBUG(B)) {
- fprintf(H5DEBUG(B), "H5B: debugging B-trees (expensive)\n");
- }
- }
- /* Initialize the queue */
- bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, type, udata, H5AC_READ);
- assert(bt);
- shared=(H5B_shared_t *)H5RC_GET_OBJ(bt->rc_shared);
- HDassert(shared);
- cur = H5MM_calloc(sizeof(struct child_t));
- assert (cur);
- cur->addr = addr;
- cur->level = bt->level;
- head = tail = cur;
-
- status = H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, H5AC__NO_FLAGS_SET);
- assert(status >= 0);
- bt=NULL; /* Make certain future references will be caught */
+ /* Portably initialize B-tree info struct */
+ HDmemset(bt_info, 0, sizeof(*bt_info));
- /*
- * Do a breadth-first search of the tree. New nodes are added to the end
- * of the queue as the `cur' pointer is advanced toward the end. We don't
- * remove any nodes from the queue because we need them in the uniqueness
- * test.
- */
- for (ncell = 0; cur; ncell++) {
- bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, cur->addr, type, udata, H5AC_READ);
- assert(bt);
-
- /* Check node header */
- assert(bt->level == cur->level);
- if (cur->next && cur->next->level == bt->level) {
- assert(H5F_addr_eq(bt->right, cur->next->addr));
- } else {
- assert(!H5F_addr_defined(bt->right));
- }
- if (prev && prev->level == bt->level) {
- assert(H5F_addr_eq(bt->left, prev->addr));
- } else {
- assert(!H5F_addr_defined(bt->left));
- }
+ /* Set up internal user-data for the B-tree 'get info' helper routine */
+ info_udata.bt_info = bt_info;
+ info_udata.udata = udata;
- if (cur->level > 0) {
- for (i = 0; i < bt->nchildren; i++) {
-
- /*
- * Check that child nodes haven't already been seen. If they
- * have then the tree has a cycle.
- */
- for (tmp = head; tmp; tmp = tmp->next) {
- assert(H5F_addr_ne(tmp->addr, bt->child[i]));
- }
-
- /* Add the child node to the end of the queue */
- tmp = H5MM_calloc(sizeof(struct child_t));
- assert (tmp);
- tmp->addr = bt->child[i];
- tmp->level = bt->level - 1;
- tail->next = tmp;
- tail = tmp;
-
- /* Check that the keys are monotonically increasing */
- cmp = (type->cmp2) (f, dxpl_id, H5B_NKEY(bt,shared,i), udata,
- H5B_NKEY(bt,shared,i+1));
- assert(cmp < 0);
- }
- }
- /* Release node */
- status = H5AC_unprotect(f, dxpl_id, H5AC_BT, cur->addr, bt, H5AC__NO_FLAGS_SET);
- assert(status >= 0);
- bt=NULL; /* Make certain future references will be caught */
-
- /* Advance current location in queue */
- prev = cur;
- cur = cur->next;
- }
+ /* Iterate over the B-tree nodes */
+ if(H5B_get_info_helper(f, dxpl_id, type, addr, &info_udata) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_BADITER, FAIL, "B-tree iteration failed")
- /* Free all entries from queue */
- while (head) {
- tmp = head->next;
- H5MM_xfree(head);
- head = tmp;
- }
+ /* Iterate over the B-tree records, making any "leaf" callbacks */
+ /* (Only if operator defined) */
+ if(op)
+ if((ret_value = H5B_iterate_helper(f, dxpl_id, type, addr, op, udata)) < 0)
+ HERROR(H5E_BTREE, H5E_BADITER, "B-tree iteration failed");
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
-#endif /* H5B_DEBUG */
+} /* end H5B_get_info() */
diff --git a/src/H5B2.c b/src/H5B2.c
index 4b7d67c..45bfff0 100644
--- a/src/H5B2.c
+++ b/src/H5B2.c
@@ -314,10 +314,10 @@ done:
* OP_DATA pointer, to allow caller to return information about
* the record.
*
- * If 'OP' is NULL, then this routine just returns "SUCCEED" when
+ * If 'OP' is NULL, then this routine just returns "TRUE" when
* a record is present in the B-tree.
*
- * Return: Non-negative on success, negative on failure.
+ * Return: Non-negative (TRUE/FALSE) on success, negative on failure.
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
@@ -325,7 +325,7 @@ done:
*
*-------------------------------------------------------------------------
*/
-herr_t
+htri_t
H5B2_find(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr,
void *udata, H5B2_found_t op, void *op_data)
{
@@ -337,7 +337,7 @@ H5B2_find(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr,
unsigned depth; /* Current depth of the tree */
int cmp; /* Comparison value of records */
unsigned idx; /* Location of record which matches key */
- herr_t ret_value = SUCCEED;
+ htri_t ret_value = TRUE /* Return value */;
FUNC_ENTER_NOAPI(H5B2_find, FAIL)
@@ -372,7 +372,7 @@ H5B2_find(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr,
/* Check for empty tree */
if(curr_node_ptr.node_nrec == 0)
- HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "B-tree has no records")
+ HGOTO_DONE(FALSE)
/* Walk down B-tree to find record or leaf node where record is located */
cmp = -1;
@@ -404,7 +404,7 @@ H5B2_find(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr,
/* Make callback for current record */
if(op && (op)(H5B2_INT_NREC(internal, shared, idx), op_data) < 0) {
/* Unlock current node */
- if (H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, H5AC__NO_FLAGS_SET) < 0)
+ if(H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "'found' callback failed for B-tree find operation")
@@ -414,7 +414,8 @@ H5B2_find(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr,
if(H5AC_unprotect(f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
- HGOTO_DONE(SUCCEED);
+ /* Indicate record found */
+ HGOTO_DONE(TRUE)
} /* end else */
/* Decrement depth we're at in B-tree */
@@ -436,15 +437,8 @@ H5B2_find(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr,
if(H5AC_unprotect(f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr.addr, leaf, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
- /* Note: don't push error on stack, leave that to next higher level,
- * since many times the B-tree is searched in order to determine
- * if an object exists in the B-tree or not. -QAK
- */
-#ifdef OLD_WAY
- HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "key not found in leaf node")
-#else /* OLD_WAY */
- HGOTO_DONE(FAIL)
-#endif /* OLD_WAY */
+ /* Record not found */
+ HGOTO_DONE(FALSE)
} /* end if */
else {
/* Make callback for current record */
@@ -992,13 +986,9 @@ H5B2_delete(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t addr,
if(H5B2_delete_node(f, dxpl_id, bt2->shared, shared->depth, &bt2->root, op, op_data) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to delete B-tree nodes")
- /* Release space for B-tree node on disk */
- if(H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, addr, (hsize_t)H5B2_HEADER_SIZE(f))<0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree header info")
-
done:
/* Release the B-tree header info */
- if(bt2 && H5AC_unprotect(f, dxpl_id, H5AC_BT2_HDR, addr, bt2, H5AC__DELETED_FLAG) < 0)
+ if(bt2 && H5AC_unprotect(f, dxpl_id, H5AC_BT2_HDR, addr, bt2, H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0)
HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to delete B-tree header info")
FUNC_LEAVE_NOAPI(ret_value)
@@ -1222,7 +1212,7 @@ H5B2_iterate_size(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t add
HDassert(btree_size);
/* Look up the B-tree header */
- if(NULL == (bt2 = H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, addr, type, NULL, H5AC_READ)))
+ if(NULL == (bt2 = (H5B2_t *)H5AC_protect(f, dxpl_id, H5AC_BT2_HDR, addr, type, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree header")
/* Safely grab pointer to reference counted shared B-tree info, so we can release the B-tree header if necessary */
@@ -1231,7 +1221,7 @@ H5B2_iterate_size(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, haddr_t add
incr_rc = TRUE;
/* Get the pointer to the shared B-tree info */
- shared = H5RC_GET_OBJ(bt2->shared);
+ shared = (H5B2_shared_t *)H5RC_GET_OBJ(bt2->shared);
HDassert(shared);
/* Add size of header to B-tree metadata total */
diff --git a/src/H5B2cache.c b/src/H5B2cache.c
index d8679aa..903b4f3 100644
--- a/src/H5B2cache.c
+++ b/src/H5B2cache.c
@@ -30,12 +30,14 @@
#define H5B2_PACKAGE /*suppress error about including H5B2pkg */
+
/***********/
/* Headers */
/***********/
#include "H5private.h" /* Generic Functions */
#include "H5B2pkg.h" /* v2 B-trees */
#include "H5Eprivate.h" /* Error handling */
+#include "H5MFprivate.h" /* File memory management */
#include "H5WBprivate.h" /* Wrapped Buffers */
@@ -80,6 +82,7 @@ static herr_t H5B2_cache_leaf_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, ha
static herr_t H5B2_cache_leaf_clear(H5F_t *f, H5B2_leaf_t *l, hbool_t destroy);
static herr_t H5B2_cache_leaf_size(const H5F_t *f, const H5B2_leaf_t *l, size_t *size_ptr);
+
/*********************/
/* Package Variables */
/*********************/
@@ -114,6 +117,7 @@ const H5AC_class_t H5AC_BT2_LEAF[1] = {{
(H5AC_size_func_t)H5B2_cache_leaf_size,
}};
+
/*****************************/
/* Library Private Variables */
/*****************************/
@@ -177,7 +181,7 @@ H5B2_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_type, vo
size = H5B2_HEADER_SIZE(f);
/* Get a pointer to a buffer that's large enough for header */
- if(NULL == (hdr = H5WB_actual(wb, size)))
+ if(NULL == (hdr = (uint8_t *)H5WB_actual(wb, size)))
HGOTO_ERROR(H5E_BTREE, H5E_NOSPACE, NULL, "can't get actual buffer")
/* Read header from disk */
@@ -188,9 +192,9 @@ H5B2_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_type, vo
p = hdr;
/* Magic number */
- if(HDmemcmp(p, H5B2_HDR_MAGIC, (size_t)H5B2_SIZEOF_MAGIC))
+ if(HDmemcmp(p, H5B2_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC))
HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree header signature")
- p += H5B2_SIZEOF_MAGIC;
+ p += H5_SIZEOF_MAGIC;
/* Version */
if(*p++ != H5B2_HDR_VERSION)
@@ -198,7 +202,7 @@ H5B2_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_type, vo
/* B-tree type */
if(*p++ != (uint8_t)type->id)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "incorrect B-tree type")
+ HGOTO_ERROR(H5E_BTREE, H5E_BADTYPE, NULL, "incorrect B-tree type")
/* Node size (in bytes) */
UINT32DECODE(p, node_size);
@@ -300,15 +304,15 @@ H5B2_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B
size = H5B2_HEADER_SIZE(f);
/* Get a pointer to a buffer that's large enough for header */
- if(NULL == (hdr = H5WB_actual(wb, size)))
+ if(NULL == (hdr = (uint8_t *)H5WB_actual(wb, size)))
HGOTO_ERROR(H5E_BTREE, H5E_NOSPACE, FAIL, "can't get actual buffer")
/* Get temporary pointer to serialized header */
p = hdr;
/* Magic number */
- HDmemcpy(p, H5B2_HDR_MAGIC, (size_t)H5B2_SIZEOF_MAGIC);
- p += H5B2_SIZEOF_MAGIC;
+ HDmemcpy(p, H5B2_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ p += H5_SIZEOF_MAGIC;
/* Version # */
*p++ = H5B2_HDR_VERSION;
@@ -326,8 +330,10 @@ H5B2_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B
UINT16ENCODE(p, shared->depth);
/* Split & merge %s */
- *p++ = shared->split_percent;
- *p++ = shared->merge_percent;
+ H5_CHECK_OVERFLOW(shared->split_percent, /* From: */ unsigned, /* To: */ uint8_t);
+ *p++ = (uint8_t)shared->split_percent;
+ H5_CHECK_OVERFLOW(shared->merge_percent, /* From: */ unsigned, /* To: */ uint8_t);
+ *p++ = (uint8_t)shared->merge_percent;
/* Root node pointer */
H5F_addr_encode(f, &p, bt2->root.addr);
@@ -374,25 +380,38 @@ done:
*
*-------------------------------------------------------------------------
*/
-/* ARGSUSED */
herr_t
-H5B2_cache_hdr_dest(H5F_t UNUSED *f, H5B2_t *bt2)
+H5B2_cache_hdr_dest(H5F_t *f, H5B2_t *bt2)
{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5B2_cache_hdr_dest)
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5B2_cache_hdr_dest)
/*
* Check arguments.
*/
HDassert(bt2);
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!bt2->cache_info.free_file_space_on_destroy || H5F_addr_defined(bt2->cache_info.addr));
+
+ /* Check for freeing file space for B-tree header */
+ if(bt2->cache_info.free_file_space_on_destroy) {
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_BTREE, H5AC_dxpl_id, bt2->cache_info.addr, (hsize_t)H5B2_HEADER_SIZE(f)) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free v2 B-tree header")
+ } /* end if */
+
/* Decrement reference count on shared B-tree info */
if(bt2->shared)
H5RC_DEC(bt2->shared);
/* Free B-tree header info */
- H5FL_FREE(H5B2_t, bt2);
+ (void)H5FL_FREE(H5B2_t, bt2);
- FUNC_LEAVE_NOAPI(SUCCEED)
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5B2_cache_hdr_dest() */
@@ -520,17 +539,17 @@ H5B2_cache_internal_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_uda
p = shared->page;
/* Magic number */
- if(HDmemcmp(p, H5B2_INT_MAGIC, (size_t)H5B2_SIZEOF_MAGIC))
+ if(HDmemcmp(p, H5B2_INT_MAGIC, (size_t)H5_SIZEOF_MAGIC))
HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree internal node signature")
- p += H5B2_SIZEOF_MAGIC;
+ p += H5_SIZEOF_MAGIC;
/* Version */
if(*p++ != H5B2_INT_VERSION)
HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree internal node version")
/* B-tree type */
- if (*p++ != (uint8_t)shared->type->id)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "incorrect B-tree type")
+ if(*p++ != (uint8_t)shared->type->id)
+ HGOTO_ERROR(H5E_BTREE, H5E_BADTYPE, NULL, "incorrect B-tree type")
/* Allocate space for the native keys in memory */
if((internal->int_native = (uint8_t *)H5FL_FAC_MALLOC(shared->node_info[udata->depth].nat_rec_fac)) == NULL)
@@ -639,8 +658,8 @@ H5B2_cache_internal_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr
p = shared->page;
/* Magic number */
- HDmemcpy(p, H5B2_INT_MAGIC, (size_t)H5B2_SIZEOF_MAGIC);
- p += H5B2_SIZEOF_MAGIC;
+ HDmemcpy(p, H5B2_INT_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ p += H5_SIZEOF_MAGIC;
/* Version # */
*p++ = H5B2_INT_VERSION;
@@ -710,23 +729,34 @@ done:
*
*-------------------------------------------------------------------------
*/
-/* ARGSUSED */
herr_t
-H5B2_cache_internal_dest(H5F_t UNUSED *f, H5B2_internal_t *internal)
+H5B2_cache_internal_dest(H5F_t *f, H5B2_internal_t *internal)
{
H5B2_shared_t *shared; /* Shared B-tree information */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5B2_cache_internal_dest)
+ FUNC_ENTER_NOAPI_NOINIT(H5B2_cache_internal_dest)
/*
* Check arguments.
*/
HDassert(internal);
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!internal->cache_info.free_file_space_on_destroy || H5F_addr_defined(internal->cache_info.addr));
+
/* Get the pointer to the shared B-tree info */
shared = (H5B2_shared_t *)H5RC_GET_OBJ(internal->shared);
HDassert(shared);
+ /* Check for freeing file space for B-tree internal node */
+ if(internal->cache_info.free_file_space_on_destroy) {
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_BTREE, H5AC_dxpl_id, internal->cache_info.addr, (hsize_t)shared->node_size) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free v2 B-tree internal node")
+ } /* end if */
+
/* Release internal node's native key buffer */
if(internal->int_native)
H5FL_FAC_FREE(shared->node_info[internal->depth].nat_rec_fac, internal->int_native);
@@ -740,9 +770,10 @@ H5B2_cache_internal_dest(H5F_t UNUSED *f, H5B2_internal_t *internal)
H5RC_DEC(internal->shared);
/* Free B-tree internal node info */
- H5FL_FREE(H5B2_internal_t, internal);
+ (void)H5FL_FREE(H5B2_internal_t, internal);
- FUNC_LEAVE_NOAPI(SUCCEED)
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5B2_cache_internal_dest() */
@@ -875,9 +906,9 @@ H5B2_cache_leaf_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nrec, v
p = shared->page;
/* Magic number */
- if(HDmemcmp(p, H5B2_LEAF_MAGIC, (size_t)H5B2_SIZEOF_MAGIC))
+ if(HDmemcmp(p, H5B2_LEAF_MAGIC, (size_t)H5_SIZEOF_MAGIC))
HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree leaf node signature")
- p += H5B2_SIZEOF_MAGIC;
+ p += H5_SIZEOF_MAGIC;
/* Version */
if(*p++ != H5B2_LEAF_VERSION)
@@ -885,7 +916,7 @@ H5B2_cache_leaf_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nrec, v
/* B-tree type */
if(*p++ != (uint8_t)shared->type->id)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "incorrect B-tree type")
+ HGOTO_ERROR(H5E_BTREE, H5E_BADTYPE, NULL, "incorrect B-tree type")
/* Allocate space for the native keys in memory */
if((leaf->leaf_native = (uint8_t *)H5FL_FAC_MALLOC(shared->node_info[0].nat_rec_fac)) == NULL)
@@ -975,8 +1006,8 @@ H5B2_cache_leaf_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5
p = shared->page;
/* magic number */
- HDmemcpy(p, H5B2_LEAF_MAGIC, (size_t)H5B2_SIZEOF_MAGIC);
- p += H5B2_SIZEOF_MAGIC;
+ HDmemcpy(p, H5B2_LEAF_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ p += H5_SIZEOF_MAGIC;
/* version # */
*p++ = H5B2_LEAF_VERSION;
@@ -1033,23 +1064,34 @@ done:
*
*-------------------------------------------------------------------------
*/
-/* ARGSUSED */
herr_t
-H5B2_cache_leaf_dest(H5F_t UNUSED *f, H5B2_leaf_t *leaf)
+H5B2_cache_leaf_dest(H5F_t *f, H5B2_leaf_t *leaf)
{
H5B2_shared_t *shared; /* Shared B-tree information */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5B2_cache_leaf_dest)
+ FUNC_ENTER_NOAPI_NOINIT(H5B2_cache_leaf_dest)
/*
* Check arguments.
*/
HDassert(leaf);
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!leaf->cache_info.free_file_space_on_destroy || H5F_addr_defined(leaf->cache_info.addr));
+
/* Get the pointer to the shared B-tree info */
shared = (H5B2_shared_t *)H5RC_GET_OBJ(leaf->shared);
HDassert(shared);
+ /* Check for freeing file space for B-tree leaf node */
+ if(leaf->cache_info.free_file_space_on_destroy) {
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_BTREE, H5AC_dxpl_id, leaf->cache_info.addr, (hsize_t)shared->node_size) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free v2 B-tree leaf node")
+ } /* end if */
+
/* Release leaf's native key buffer */
if(leaf->leaf_native)
H5FL_FAC_FREE(shared->node_info[0].nat_rec_fac, leaf->leaf_native);
@@ -1059,9 +1101,10 @@ H5B2_cache_leaf_dest(H5F_t UNUSED *f, H5B2_leaf_t *leaf)
H5RC_DEC(leaf->shared);
/* Free B-tree leaf node info */
- H5FL_FREE(H5B2_leaf_t,leaf);
+ (void)H5FL_FREE(H5B2_leaf_t, leaf);
- FUNC_LEAVE_NOAPI(SUCCEED)
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5B2_cache_leaf_dest() */
diff --git a/src/H5B2int.c b/src/H5B2int.c
index 2625c63..aa1fdca 100644
--- a/src/H5B2int.c
+++ b/src/H5B2int.c
@@ -149,6 +149,8 @@ H5B2_shared_init (H5F_t *f, H5B2_t *bt2, const H5B2_class_t *type,
unsigned split_percent, unsigned merge_percent)
{
H5B2_shared_t *shared = NULL; /* Shared B-tree information */
+ size_t sz_max_nrec; /* Temporary variable for range checking */
+ unsigned u_max_nrec_size; /* Temporary variable for range checking */
unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
@@ -182,7 +184,8 @@ HDmemset(shared->page, 0, shared->node_size);
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Initialize leaf node info */
- shared->node_info[0].max_nrec = H5B2_NUM_LEAF_REC(shared->node_size, shared->rrec_size);
+ sz_max_nrec = H5B2_NUM_LEAF_REC(shared->node_size, shared->rrec_size);
+ H5_ASSIGN_OVERFLOW(/* To: */ shared->node_info[0].max_nrec, /* From: */ sz_max_nrec, /* From: */ size_t, /* To: */ unsigned)
shared->node_info[0].split_nrec = (shared->node_info[0].max_nrec * shared->split_percent) / 100;
shared->node_info[0].merge_nrec = (shared->node_info[0].max_nrec * shared->merge_percent) / 100;
shared->node_info[0].cum_max_nrec = shared->node_info[0].max_nrec;
@@ -203,21 +206,24 @@ HDmemset(shared->page, 0, shared->node_size);
/* Compute size to store # of records in each node */
/* (uses leaf # of records because its the largest) */
- shared->max_nrec_size = (H5V_log2_gen((uint64_t)shared->node_info[0].max_nrec) + 7) / 8;
+ u_max_nrec_size = H5V_limit_enc_size((uint64_t)shared->node_info[0].max_nrec);
+ H5_ASSIGN_OVERFLOW(/* To: */ shared->max_nrec_size, /* From: */ u_max_nrec_size, /* From: */ unsigned, /* To: */ unsigned char)
HDassert(shared->max_nrec_size <= H5B2_SIZEOF_RECORDS_PER_NODE);
/* Initialize internal node info */
if(depth > 0) {
for(u = 1; u < (depth + 1); u++) {
- shared->node_info[u].max_nrec = H5B2_NUM_INT_REC(f, shared, u);
+ sz_max_nrec = H5B2_NUM_INT_REC(f, shared, u);
+ H5_ASSIGN_OVERFLOW(/* To: */ shared->node_info[u].max_nrec, /* From: */ sz_max_nrec, /* From: */ size_t, /* To: */ unsigned)
HDassert(shared->node_info[u].max_nrec <= shared->node_info[u - 1].max_nrec);
shared->node_info[u].split_nrec = (shared->node_info[u].max_nrec * shared->split_percent) / 100;
shared->node_info[u].merge_nrec = (shared->node_info[u].max_nrec * shared->merge_percent) / 100;
- shared->node_info[u].cum_max_nrec = ((shared->node_info[u].max_nrec + 1) *
+ shared->node_info[u].cum_max_nrec = ((shared->node_info[u].max_nrec + 1) *
shared->node_info[u - 1].cum_max_nrec) + shared->node_info[u].max_nrec;
- shared->node_info[u].cum_max_nrec_size = (H5V_log2_gen((uint64_t)shared->node_info[u].cum_max_nrec) + 7) / 8;
+ u_max_nrec_size = H5V_limit_enc_size((uint64_t)shared->node_info[u].cum_max_nrec);
+ H5_ASSIGN_OVERFLOW(/* To: */ shared->node_info[u].cum_max_nrec_size, /* From: */ u_max_nrec_size, /* From: */ unsigned, /* To: */ unsigned char)
if((shared->node_info[u].nat_rec_fac = H5FL_fac_init(shared->type->nrec_size * shared->node_info[u].max_nrec)) == NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create node native key block factory")
@@ -290,7 +296,7 @@ H5B2_shared_free(void *_shared)
} /* end if */
/* Free the shared B-tree info itself */
- H5FL_FREE(H5B2_shared_t, shared);
+ (void)H5FL_FREE(H5B2_shared_t, shared);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -551,6 +557,8 @@ H5B2_split_root(H5F_t *f, hid_t dxpl_id, H5B2_t *bt2, unsigned *bt2_flags_ptr)
H5B2_shared_t *shared; /* Pointer to B-tree's shared information */
unsigned new_root_flags = H5AC__NO_FLAGS_SET; /* Cache flags for new root node */
H5B2_node_ptr_t old_root_ptr; /* Old node pointer to root node in B-tree */
+ size_t sz_max_nrec; /* Temporary variable for range checking */
+ unsigned u_max_nrec_size; /* Temporary variable for range checking */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5B2_split_root)
@@ -571,12 +579,14 @@ H5B2_split_root(H5F_t *f, hid_t dxpl_id, H5B2_t *bt2, unsigned *bt2_flags_ptr)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Update node info for new depth of tree */
- shared->node_info[shared->depth].max_nrec = H5B2_NUM_INT_REC(f, shared, shared->depth);
+ sz_max_nrec = H5B2_NUM_INT_REC(f, shared, shared->depth);
+ H5_ASSIGN_OVERFLOW(/* To: */ shared->node_info[shared->depth].max_nrec, /* From: */ sz_max_nrec, /* From: */ size_t, /* To: */ unsigned)
shared->node_info[shared->depth].split_nrec = (shared->node_info[shared->depth].max_nrec * shared->split_percent) / 100;
shared->node_info[shared->depth].merge_nrec = (shared->node_info[shared->depth].max_nrec * shared->merge_percent) / 100;
- shared->node_info[shared->depth].cum_max_nrec = ((shared->node_info[shared->depth].max_nrec + 1) *
+ shared->node_info[shared->depth].cum_max_nrec = ((shared->node_info[shared->depth].max_nrec + 1) *
shared->node_info[shared->depth - 1].cum_max_nrec) + shared->node_info[shared->depth].max_nrec;
- shared->node_info[shared->depth].cum_max_nrec_size = (H5V_log2_gen((uint64_t)shared->node_info[shared->depth].cum_max_nrec) + 7) / 8;
+ u_max_nrec_size = H5V_limit_enc_size((uint64_t)shared->node_info[shared->depth].cum_max_nrec);
+ H5_ASSIGN_OVERFLOW(/* To: */ shared->node_info[shared->depth].cum_max_nrec_size, /* From: */ u_max_nrec_size, /* From: */ unsigned, /* To: */ unsigned char)
if((shared->node_info[shared->depth].nat_rec_fac = H5FL_fac_init(shared->type->nrec_size * shared->node_info[shared->depth].max_nrec)) == NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create node native key block factory")
if((shared->node_info[shared->depth].node_ptr_fac = H5FL_fac_init(sizeof(H5B2_node_ptr_t) * (shared->node_info[shared->depth].max_nrec + 1))) == NULL)
@@ -731,20 +741,20 @@ H5B2_redistribute2(H5F_t *f, hid_t dxpl_id, unsigned depth, H5B2_internal_t *int
/* Handle node pointers, if we have an internal node */
if(depth>1) {
- hsize_t moved_nrec=move_nrec; /* Total number of records moved, for internal redistrib */
+ hsize_t moved_nrec = move_nrec; /* Total number of records moved, for internal redistrib */
unsigned u; /* Local index variable */
/* Count the number of records being moved */
- for(u=0; u<move_nrec; u++)
+ for(u = 0; u < move_nrec; u++)
moved_nrec += right_node_ptrs[u].all_nrec;
- left_moved_nrec = moved_nrec;
- right_moved_nrec -= moved_nrec;
+ H5_ASSIGN_OVERFLOW(/* To: */ left_moved_nrec, /* From: */ moved_nrec, /* From: */ hsize_t, /* To: */ hssize_t)
+ right_moved_nrec -= (hssize_t)moved_nrec;
/* Copy node pointers from right node to left */
- HDmemcpy(&(left_node_ptrs[*left_nrec+1]),&(right_node_ptrs[0]),sizeof(H5B2_node_ptr_t)*move_nrec);
+ HDmemcpy(&(left_node_ptrs[*left_nrec + 1]), &(right_node_ptrs[0]), sizeof(H5B2_node_ptr_t) * move_nrec);
/* Slide node pointers in right node down */
- HDmemmove(&(right_node_ptrs[0]),&(right_node_ptrs[move_nrec]),sizeof(H5B2_node_ptr_t)*(new_right_nrec+1));
+ HDmemmove(&(right_node_ptrs[0]), &(right_node_ptrs[move_nrec]), sizeof(H5B2_node_ptr_t) * (new_right_nrec + 1));
} /* end if */
/* Update number of records in child nodes */
@@ -786,8 +796,8 @@ H5B2_redistribute2(H5F_t *f, hid_t dxpl_id, unsigned depth, H5B2_internal_t *int
/* Count the number of records being moved */
for(u=0; u<move_nrec; u++)
moved_nrec += right_node_ptrs[u].all_nrec;
- left_moved_nrec -= moved_nrec;
- right_moved_nrec = moved_nrec;
+ left_moved_nrec -= (hssize_t)moved_nrec;
+ H5_ASSIGN_OVERFLOW(/* To: */ right_moved_nrec, /* From: */ moved_nrec, /* From: */ hsize_t, /* To: */ hssize_t)
} /* end if */
/* Update number of records in child nodes */
@@ -1350,9 +1360,7 @@ H5B2_merge2(H5F_t *f, hid_t dxpl_id, unsigned depth,
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
/* Delete right node & remove from cache (marked as dirty) */
- if(H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, right_addr, (hsize_t)shared->node_size) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node")
- if(H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG) < 0)
+ if(H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
done:
@@ -1574,9 +1582,7 @@ H5B2_merge3(H5F_t *f, hid_t dxpl_id, unsigned depth,
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
/* Delete right node & remove from cache (marked as dirty) */
- if (H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, right_addr, (hsize_t)shared->node_size) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node")
- if (H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG) < 0)
+ if(H5AC_unprotect(f, dxpl_id, child_class, right_addr, right_child, H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
done:
@@ -2280,12 +2286,8 @@ H5B2_remove_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
HDmemmove(H5B2_LEAF_NREC(leaf, shared, idx), H5B2_LEAF_NREC(leaf, shared, (idx + 1)), shared->type->nrec_size * (leaf->nrec-idx));
} /* end if */
else {
- /* Release space for B-tree node on disk */
- if(H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, leaf_addr, (hsize_t)shared->node_size) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node")
-
/* Let the cache know that the object is deleted */
- leaf_flags |= H5AC__DELETED_FLAG;
+ leaf_flags |= H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
/* Reset address of parent node pointer */
curr_node_ptr->addr = HADDR_UNDEF;
@@ -2367,12 +2369,8 @@ H5B2_remove_internal(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
parent_cache_info_flags_ptr, internal, &internal_flags, 0) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to merge child node")
- /* Release space for root B-tree node on disk */
- if(H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, internal_addr, (hsize_t)shared->node_size) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node")
-
/* Let the cache know that the object is deleted */
- internal_flags |= H5AC__DELETED_FLAG;
+ internal_flags |= H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
/* Reset information in header's root node pointer */
curr_node_ptr->addr = internal->node_ptrs[0].addr;
@@ -2580,12 +2578,8 @@ H5B2_remove_leaf_by_idx(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
HDmemmove(H5B2_LEAF_NREC(leaf, shared, idx), H5B2_LEAF_NREC(leaf, shared, (idx + 1)), shared->type->nrec_size * (leaf->nrec-idx));
} /* end if */
else {
- /* Release space for B-tree node on disk */
- if(H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, leaf_addr, (hsize_t)shared->node_size) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node")
-
/* Let the cache know that the object is deleted */
- leaf_flags |= H5AC__DELETED_FLAG;
+ leaf_flags |= H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
/* Reset address of parent node pointer */
curr_node_ptr->addr = HADDR_UNDEF;
@@ -2671,12 +2665,8 @@ H5B2_remove_internal_by_idx(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared,
parent_cache_info_flags_ptr, internal, &internal_flags, 0) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTSPLIT, FAIL, "unable to merge child node")
- /* Release space for root B-tree node on disk */
- if(H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, internal_addr, (hsize_t)shared->node_size) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree leaf node")
-
/* Let the cache know that the object is deleted */
- internal_flags |= H5AC__DELETED_FLAG;
+ internal_flags |= H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
/* Reset information in header's root node pointer */
curr_node_ptr->addr = internal->node_ptrs[0].addr;
@@ -3134,15 +3124,10 @@ H5B2_delete_node(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, unsigned depth,
} /* end for */
} /* end if */
- /* Release space for current B-tree node on disk */
- if(H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, curr_node->addr, (hsize_t)shared->node_size) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree node")
-
done:
/* Unlock & delete current node */
- if(node)
- if(H5AC_unprotect(f, dxpl_id, curr_node_class, curr_node->addr, node, H5AC__DELETED_FLAG) < 0)
- HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
+ if(node && H5AC_unprotect(f, dxpl_id, curr_node_class, curr_node->addr, node, H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0)
+ HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
FUNC_LEAVE_NOAPI(ret_value)
} /* H5B2_delete_node() */
@@ -3150,22 +3135,22 @@ done:
/*-------------------------------------------------------------------------
* Function: H5B2_iterate_size_node
- *
+ *
* Purpose: Iterate over all the records from a B-tree node, collecting
* btree storage info.
- *
+ *
* Return: non-negative on success, negative on error
- *
+ *
* Programmer: Vailin Choi
* July 12 2007
- *
+ *
*-------------------------------------------------------------------------
*/
herr_t
H5B2_iterate_size_node(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, unsigned depth,
const H5B2_node_ptr_t *curr_node, hsize_t *btree_size)
{
- H5B2_shared_t *shared; /* Pointer to B-tree's shared information */
+ H5B2_shared_t *shared; /* Pointer to B-tree's shared information */
H5B2_internal_t *internal = NULL; /* Pointer to internal node */
herr_t ret_value = SUCCEED; /* Iterator return value */
@@ -3229,12 +3214,7 @@ H5B2_assert_leaf(H5B2_shared_t *shared, H5B2_leaf_t *leaf)
unsigned u,v; /* Local index variables */
/* General sanity checking on node */
- HDassert(leaf->nrec<=shared->split_leaf_nrec);
-
- /* Sanity checking on records */
- for(u=0; u<leaf->nrec; u++)
- for(v=0; v<u; v++)
- HDassert((shared->type->compare)(H5B2_LEAF_NREC(leaf,shared,u), H5B2_LEAF_NREC(leaf,shared,v))>0);
+ HDassert(leaf->nrec<=shared->node_info->split_nrec);
return(0);
} /* end H5B2_assert_leaf() */
@@ -3259,14 +3239,7 @@ H5B2_assert_leaf2(H5B2_shared_t *shared, H5B2_leaf_t *leaf, H5B2_leaf_t *leaf2)
unsigned u,v; /* Local index variables */
/* General sanity checking on node */
- HDassert(leaf->nrec<=shared->split_leaf_nrec);
-
- /* Sanity checking on records */
- for(u=0; u<leaf->nrec; u++) {
- HDassert((shared->type->compare)(H5B2_LEAF_NREC(leaf2,shared,0), H5B2_LEAF_NREC(leaf,shared,u))>0);
- for(v=0; v<u; v++)
- HDassert((shared->type->compare)(H5B2_LEAF_NREC(leaf,shared,u), H5B2_LEAF_NREC(leaf,shared,v))>0);
- } /* end for */
+ HDassert(leaf->nrec<=shared->node_info->split_nrec);
return(0);
} /* end H5B2_assert_leaf() */
@@ -3292,12 +3265,7 @@ H5B2_assert_internal(hsize_t parent_all_nrec, H5B2_shared_t *shared, H5B2_intern
unsigned u,v; /* Local index variables */
/* General sanity checking on node */
- HDassert(internal->nrec<=shared->split_int_nrec);
-
- /* Sanity checking on records */
- for(u=0; u<internal->nrec; u++)
- for(v=0; v<u; v++)
- HDassert((shared->type->compare)(H5B2_INT_NREC(internal,shared,u), H5B2_INT_NREC(internal,shared,v))>0);
+ HDassert(internal->nrec<=shared->node_info->split_nrec);
/* Sanity checking on node pointers */
tot_all_nrec=internal->nrec;
@@ -3338,12 +3306,7 @@ H5B2_assert_internal2(hsize_t parent_all_nrec, H5B2_shared_t *shared, H5B2_inter
unsigned u,v; /* Local index variables */
/* General sanity checking on node */
- HDassert(internal->nrec<=shared->split_int_nrec);
-
- /* Sanity checking on records */
- for(u=0; u<internal->nrec; u++)
- for(v=0; v<u; v++)
- HDassert((shared->type->compare)(H5B2_INT_NREC(internal,shared,u), H5B2_INT_NREC(internal,shared,v))>0);
+ HDassert(internal->nrec<=shared->node_info->split_nrec);
/* Sanity checking on node pointers */
tot_all_nrec=internal->nrec;
diff --git a/src/H5B2pkg.h b/src/H5B2pkg.h
index 43fab1f..d05220b 100644
--- a/src/H5B2pkg.h
+++ b/src/H5B2pkg.h
@@ -40,14 +40,6 @@
/* Package Private Macros */
/**************************/
-/* Size of signature information (on disk) */
-#define H5B2_SIZEOF_MAGIC 4
-
-/* B-tree signatures */
-#define H5B2_HDR_MAGIC "BTHD" /* Header */
-#define H5B2_INT_MAGIC "BTIN" /* Internal node */
-#define H5B2_LEAF_MAGIC "BTLF" /* Leaf node */
-
/* Size of storage for number of records per node (on disk) */
#define H5B2_SIZEOF_RECORDS_PER_NODE 2
@@ -67,7 +59,7 @@
/* Format overhead for all v2 B-tree metadata in the file */
#define H5B2_METADATA_PREFIX_SIZE ( \
- H5B2_SIZEOF_MAGIC /* Signature */ \
+ H5_SIZEOF_MAGIC /* Signature */ \
+ 1 /* Version */ \
+ 1 /* Tree type */ \
+ H5B2_SIZEOF_CHKSUM /* Metadata checksum */ \
diff --git a/src/H5B2private.h b/src/H5B2private.h
index 6d8172c..0a18604 100644
--- a/src/H5B2private.h
+++ b/src/H5B2private.h
@@ -124,7 +124,7 @@ H5_DLL herr_t H5B2_iterate(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type,
haddr_t addr, H5B2_operator_t op, void *op_data);
H5_DLL herr_t H5B2_iterate_size(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type,
haddr_t addr, hsize_t *op_data);
-H5_DLL herr_t H5B2_find(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type,
+H5_DLL htri_t H5B2_find(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type,
haddr_t addr, void *udata, H5B2_found_t op, void *op_data);
H5_DLL herr_t H5B2_index(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type,
haddr_t addr, H5_iter_order_t order, hsize_t idx, H5B2_found_t op,
diff --git a/src/H5Bcache.c b/src/H5Bcache.c
index 2748963..9765552 100644
--- a/src/H5Bcache.c
+++ b/src/H5Bcache.c
@@ -37,6 +37,7 @@
#include "H5private.h" /* Generic Functions */
#include "H5Bpkg.h" /* B-link trees */
#include "H5Eprivate.h" /* Error handling */
+#include "H5MFprivate.h" /* File memory management */
/****************/
/* Local Macros */
@@ -113,7 +114,7 @@ H5B_serialize(const H5F_t *f, const H5B_t *bt)
p = shared->page;
/* magic number */
- HDmemcpy(p, H5B_MAGIC, (size_t)H5B_SIZEOF_MAGIC);
+ HDmemcpy(p, H5B_MAGIC, (size_t)H5_SIZEOF_MAGIC);
p += 4;
/* node type and level */
@@ -202,7 +203,7 @@ H5B_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_type, void *udata)
p = shared->page;
/* magic number */
- if (HDmemcmp(p, H5B_MAGIC, (size_t)H5B_SIZEOF_MAGIC))
+ if (HDmemcmp(p, H5B_MAGIC, (size_t)H5_SIZEOF_MAGIC))
HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree signature")
p += 4;
@@ -321,24 +322,45 @@ done:
*
*-------------------------------------------------------------------------
*/
-/* ARGSUSED */
herr_t
-H5B_dest(H5F_t UNUSED *f, H5B_t *bt)
+H5B_dest(H5F_t *f, H5B_t *bt)
{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5B_dest)
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5B_dest)
/*
* Check arguments.
*/
+ HDassert(f);
HDassert(bt);
HDassert(bt->rc_shared);
- H5FL_SEQ_FREE(haddr_t,bt->child);
- H5FL_BLK_FREE(native_block,bt->native);
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!bt->cache_info.free_file_space_on_destroy || H5F_addr_defined(bt->cache_info.addr));
+
+ /* Check for freeing file space for B-tree node */
+ if(bt->cache_info.free_file_space_on_destroy) {
+ H5B_shared_t *shared; /* Pointer to shared B-tree info */
+
+ /* Get the pointer to the shared B-tree info */
+ shared = (H5B_shared_t *)H5RC_GET_OBJ(bt->rc_shared);
+ HDassert(shared);
+
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_BTREE, H5AC_dxpl_id, bt->cache_info.addr, (hsize_t)shared->sizeof_rnode) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree node")
+ } /* end if */
+
+ /* Release resources for B-tree node */
+ H5FL_SEQ_FREE(haddr_t, bt->child);
+ (void)H5FL_BLK_FREE(native_block, bt->native);
H5RC_DEC(bt->rc_shared);
- H5FL_FREE(H5B_t,bt);
+ (void)H5FL_FREE(H5B_t, bt);
- FUNC_LEAVE_NOAPI(SUCCEED)
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5B_dest() */
@@ -397,10 +419,8 @@ static herr_t
H5B_compute_size(const H5F_t *f, const H5B_t *bt, size_t *size_ptr)
{
H5B_shared_t *shared; /* Pointer to shared B-tree info */
- size_t size;
- herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5B_compute_size)
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5B_compute_size)
/* check arguments */
HDassert(f);
@@ -411,13 +431,8 @@ H5B_compute_size(const H5F_t *f, const H5B_t *bt, size_t *size_ptr)
HDassert(shared->type);
HDassert(size_ptr);
- /* Check node's size */
- if ((size = H5B_nodesize(f, shared, NULL)) == 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGETSIZE, FAIL, "H5B_nodesize() failed")
-
/* Set size value */
- *size_ptr = size;
+ *size_ptr = shared->sizeof_rnode;
-done:
- FUNC_LEAVE_NOAPI(ret_value)
+ FUNC_LEAVE_NOAPI(SUCCEED)
} /* H5B_compute_size() */
diff --git a/src/H5Bdbg.c b/src/H5Bdbg.c
new file mode 100644
index 0000000..f517daf
--- /dev/null
+++ b/src/H5Bdbg.c
@@ -0,0 +1,284 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5Bdbg.c
+ * Dec 11 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: Debugging routines for B-link tree package.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5B_PACKAGE /*suppress error about including H5Bpkg */
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Bpkg.h" /* B-link trees */
+#include "H5Eprivate.h" /* Error handling */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B_debug
+ *
+ * Purpose: Prints debugging info about a B-tree.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Aug 4 1997
+ *
+ * Modifications:
+ * Robb Matzke, 1999-07-28
+ * The ADDR argument is passed by value.
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5B_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int fwidth,
+ const H5B_class_t *type, void *udata)
+{
+ H5B_t *bt = NULL;
+ H5B_shared_t *shared; /* Pointer to shared B-tree info */
+ unsigned u; /* Local index variable */
+ herr_t ret_value=SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5B_debug, FAIL)
+
+ /*
+ * Check arguments.
+ */
+ assert(f);
+ assert(H5F_addr_defined(addr));
+ assert(stream);
+ assert(indent >= 0);
+ assert(fwidth >= 0);
+ assert(type);
+
+ /*
+ * Load the tree node.
+ */
+ if (NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, type, udata, H5AC_READ)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load B-tree node")
+ shared=(H5B_shared_t *)H5RC_GET_OBJ(bt->rc_shared);
+ HDassert(shared);
+
+ /*
+ * Print the values.
+ */
+ HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
+ "Tree type ID:",
+ ((shared->type->id)==H5B_SNODE_ID ? "H5B_SNODE_ID" :
+ ((shared->type->id)==H5B_CHUNK_ID ? "H5B_CHUNK_ID" : "Unknown!")));
+ HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth,
+ "Size of node:",
+ shared->sizeof_rnode);
+ HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth,
+ "Size of raw (disk) key:",
+ shared->sizeof_rkey);
+ HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
+ "Dirty flag:",
+ bt->cache_info.is_dirty ? "True" : "False");
+ HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
+ "Level:",
+ bt->level);
+
+ HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
+ "Address of left sibling:",
+ bt->left);
+
+ HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
+ "Address of right sibling:",
+ bt->right);
+
+ HDfprintf(stream, "%*s%-*s %u (%u)\n", indent, "", fwidth,
+ "Number of children (max):",
+ bt->nchildren, shared->two_k);
+
+ /*
+ * Print the child addresses
+ */
+ for (u = 0; u < bt->nchildren; u++) {
+ HDfprintf(stream, "%*sChild %d...\n", indent, "", u);
+ HDfprintf(stream, "%*s%-*s %a\n", indent + 3, "", MAX(0, fwidth - 3),
+ "Address:", bt->child[u]);
+
+ /* If there is a key debugging routine, use it to display the left & right keys */
+ if (type->debug_key) {
+ /* Decode the 'left' key & print it */
+ HDfprintf(stream, "%*s%-*s\n", indent + 3, "", MAX(0, fwidth - 3),
+ "Left Key:");
+ assert(H5B_NKEY(bt,shared,u));
+ (void)(type->debug_key)(stream, f, dxpl_id, indent+6, MAX (0, fwidth-6),
+ H5B_NKEY(bt,shared,u), udata);
+
+ /* Decode the 'right' key & print it */
+ HDfprintf(stream, "%*s%-*s\n", indent + 3, "", MAX(0, fwidth - 3),
+ "Right Key:");
+ assert(H5B_NKEY(bt,shared,u+1));
+ (void)(type->debug_key)(stream, f, dxpl_id, indent+6, MAX (0, fwidth-6),
+ H5B_NKEY(bt,shared,u+1), udata);
+ }
+ }
+
+done:
+ if (bt && H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, H5AC__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release B-tree node")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5B_assert
+ *
+ * Purpose: Verifies that the tree is structured correctly.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: aborts if something is wrong.
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, November 4, 1997
+ *
+ * Modifications:
+ * Robb Matzke, 1999-07-28
+ * The ADDR argument is passed by value.
+ *
+ * John Mainzer, 6/8/05
+ * Modified the function to use the new dirtied parameter of
+ * of H5AC_unprotect() instead of modifying the is_dirty
+ * field of the cache info.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifdef H5B_DEBUG
+herr_t
+H5B_assert(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type, void *udata)
+{
+ H5B_t *bt = NULL;
+ H5B_shared_t *shared; /* Pointer to shared B-tree info */
+ int i, ncell, cmp;
+ static int ncalls = 0;
+ herr_t status;
+ herr_t ret_value=SUCCEED; /* Return value */
+
+ /* A queue of child data */
+ struct child_t {
+ haddr_t addr;
+ unsigned level;
+ struct child_t *next;
+ } *head = NULL, *tail = NULL, *prev = NULL, *cur = NULL, *tmp = NULL;
+
+ FUNC_ENTER_NOAPI(H5B_assert, FAIL)
+
+ if (0==ncalls++) {
+ if (H5DEBUG(B)) {
+ fprintf(H5DEBUG(B), "H5B: debugging B-trees (expensive)\n");
+ }
+ }
+ /* Initialize the queue */
+ bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, type, udata, H5AC_READ);
+ assert(bt);
+ shared=(H5B_shared_t *)H5RC_GET_OBJ(bt->rc_shared);
+ HDassert(shared);
+ cur = H5MM_calloc(sizeof(struct child_t));
+ assert (cur);
+ cur->addr = addr;
+ cur->level = bt->level;
+ head = tail = cur;
+
+ status = H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, H5AC__NO_FLAGS_SET);
+ assert(status >= 0);
+ bt=NULL; /* Make certain future references will be caught */
+
+ /*
+ * Do a breadth-first search of the tree. New nodes are added to the end
+ * of the queue as the `cur' pointer is advanced toward the end. We don't
+ * remove any nodes from the queue because we need them in the uniqueness
+ * test.
+ */
+ for (ncell = 0; cur; ncell++) {
+ bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, cur->addr, type, udata, H5AC_READ);
+ assert(bt);
+
+ /* Check node header */
+ assert(bt->level == cur->level);
+ if (cur->next && cur->next->level == bt->level) {
+ assert(H5F_addr_eq(bt->right, cur->next->addr));
+ } else {
+ assert(!H5F_addr_defined(bt->right));
+ }
+ if (prev && prev->level == bt->level) {
+ assert(H5F_addr_eq(bt->left, prev->addr));
+ } else {
+ assert(!H5F_addr_defined(bt->left));
+ }
+
+ if (cur->level > 0) {
+ for (i = 0; i < bt->nchildren; i++) {
+
+ /*
+ * Check that child nodes haven't already been seen. If they
+ * have then the tree has a cycle.
+ */
+ for (tmp = head; tmp; tmp = tmp->next) {
+ assert(H5F_addr_ne(tmp->addr, bt->child[i]));
+ }
+
+ /* Add the child node to the end of the queue */
+ tmp = H5MM_calloc(sizeof(struct child_t));
+ assert (tmp);
+ tmp->addr = bt->child[i];
+ tmp->level = bt->level - 1;
+ tail->next = tmp;
+ tail = tmp;
+
+ /* Check that the keys are monotonically increasing */
+ cmp = (type->cmp2) (f, dxpl_id, H5B_NKEY(bt,shared,i), udata,
+ H5B_NKEY(bt,shared,i+1));
+ assert(cmp < 0);
+ }
+ }
+ /* Release node */
+ status = H5AC_unprotect(f, dxpl_id, H5AC_BT, cur->addr, bt, H5AC__NO_FLAGS_SET);
+ assert(status >= 0);
+ bt=NULL; /* Make certain future references will be caught */
+
+ /* Advance current location in queue */
+ prev = cur;
+ cur = cur->next;
+ }
+
+ /* Free all entries from queue */
+ while (head) {
+ tmp = head->next;
+ H5MM_xfree(head);
+ head = tmp;
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+}
+#endif /* H5B_DEBUG */
+
diff --git a/src/H5Bpkg.h b/src/H5Bpkg.h
index cd79cf7..ddabf52 100644
--- a/src/H5Bpkg.h
+++ b/src/H5Bpkg.h
@@ -32,12 +32,15 @@
#include "H5Bprivate.h"
/* Other private headers needed by this file */
-#include "H5RCprivate.h" /* Reference counted objects */
/**************************/
/* Package Private Macros */
/**************************/
+/* Get the native key at a given index */
+#define H5B_NKEY(b, shared, idx) ((b)->native + (shared)->nkey[(idx)])
+
+
/****************************/
/* Package Private Typedefs */
/****************************/
@@ -74,6 +77,11 @@ H5FL_EXTERN(H5B_t);
/******************************/
/* Package Private Prototypes */
/******************************/
-herr_t H5B_dest(H5F_t *f, H5B_t *b);
+H5_DLL herr_t H5B_dest(H5F_t *f, H5B_t *b);
+#ifdef H5B_DEBUG
+herr_t H5B_assert(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type,
+ void *udata);
+#endif
#endif /*_H5Bpkg_H*/
+
diff --git a/src/H5Bprivate.h b/src/H5Bprivate.h
index 4dfea84..93c2d80 100644
--- a/src/H5Bprivate.h
+++ b/src/H5Bprivate.h
@@ -51,13 +51,22 @@
#ifdef NDEBUG
# undef H5B_DEBUG
#endif
-#define H5B_MAGIC "TREE" /*tree node magic number */
-#define H5B_SIZEOF_MAGIC 4 /*size of magic number */
+
/****************************/
/* Library Private Typedefs */
/****************************/
+/* B-tree IDs for various internal things. */
+/* Note - if more of these are added, any 'K' values (for internal or leaf
+ * nodes) they use will need to be stored in the file somewhere. -QAK
+ */
+typedef enum H5B_subid_t {
+ H5B_SNODE_ID = 0, /*B-tree is for symbol table nodes */
+ H5B_CHUNK_ID = 1, /*B-tree is for chunked dataset storage */
+ H5B_NUM_BTREE_ID /* Number of B-tree key IDs (must be last) */
+} H5B_subid_t;
+
/* Define return values from B-tree insertion callbacks */
typedef enum H5B_ins_t {
H5B_INS_ERROR = -1, /*error return value */
@@ -104,7 +113,7 @@ typedef struct H5B_class_t {
herr_t (*new_node)(H5F_t*, hid_t, H5B_ins_t, void*, void*, void*, haddr_t*);
int (*cmp2)(H5F_t*, hid_t, void*, void*, void*); /*compare 2 keys */
int (*cmp3)(H5F_t*, hid_t, void*, void*, void*); /*compare 3 keys */
- herr_t (*found)(H5F_t*, hid_t, haddr_t, const void*, void*);
+ htri_t (*found)(H5F_t*, hid_t, haddr_t, const void*, void*);
/* insert new data */
H5B_ins_t (*insert)(H5F_t*, hid_t, haddr_t, void*, hbool_t*, void*, void*,
@@ -124,42 +133,40 @@ typedef struct H5B_class_t {
herr_t (*debug_key)(FILE*, H5F_t*, hid_t, int, int, const void*, const void*);
} H5B_class_t;
-/* "user data" for iterating over B-tree when collecting B-tree metadata size */
-typedef struct H5B_info_ud_t {
- void *udata; /* Node type's 'udata' for loading */
- hsize_t *btree_size; /* Accumulated size for B-tree metadata */
-} H5B_info_ud_t;
+/* Information about B-tree */
+typedef struct H5B_info_t {
+ hsize_t size; /* Size of B-tree nodes */
+ hsize_t num_nodes; /* Number of B-tree nodes */
+} H5B_info_t;
+
/*****************************/
/* Library-private Variables */
/*****************************/
-/* Declare a free list to manage the H5B_shared_t struct */
-H5FL_EXTERN(H5B_shared_t);
-
/***************************************/
/* Library-private Function Prototypes */
/***************************************/
-H5_DLL size_t H5B_nodesize(const H5F_t *f, const H5B_shared_t *shared,
- size_t *total_nkey_size);
-H5_DLL herr_t H5B_create(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, void *udata,
- haddr_t *addr_p/*out*/);
-H5_DLL herr_t H5B_find(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, haddr_t addr,
- void *udata);
-H5_DLL herr_t H5B_insert(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, haddr_t addr,
- void *udata);
-H5_DLL herr_t H5B_iterate(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, H5B_operator_t
- op, haddr_t addr, void *udata);
-H5_DLL herr_t H5B_iterate_size(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, H5B_operator_t
- op, haddr_t addr, H5B_info_ud_t *bh_udata);
-H5_DLL herr_t H5B_remove(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, haddr_t addr,
- void *udata);
-H5_DLL herr_t H5B_delete(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, haddr_t addr,
- void *udata);
+H5_DLL herr_t H5B_create(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type,
+ void *udata, haddr_t *addr_p/*out*/);
+H5_DLL herr_t H5B_find(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type,
+ haddr_t addr, void *udata);
+H5_DLL herr_t H5B_insert(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type,
+ haddr_t addr, void *udata);
+H5_DLL herr_t H5B_iterate(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type,
+ haddr_t addr, H5B_operator_t op, void *udata);
+H5_DLL herr_t H5B_get_info(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type,
+ haddr_t addr, H5B_info_t *bt_info, H5B_operator_t op, void *udata);
+H5_DLL herr_t H5B_remove(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type,
+ haddr_t addr, void *udata);
+H5_DLL herr_t H5B_delete(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type,
+ haddr_t addr, void *udata);
+H5_DLL H5B_shared_t *H5B_shared_new(const H5F_t *f, const H5B_class_t *type,
+ size_t sizeof_rkey);
+H5_DLL herr_t H5B_shared_free(void *_shared);
H5_DLL herr_t H5B_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream,
- int indent, int fwidth, const H5B_class_t *type,
- void *udata);
+ int indent, int fwidth, const H5B_class_t *type, void *udata);
#endif /* _H5Bprivate_H */
diff --git a/src/H5Bpublic.h b/src/H5Bpublic.h
index df3861f..0016996 100644
--- a/src/H5Bpublic.h
+++ b/src/H5Bpublic.h
@@ -31,17 +31,6 @@
/* Public headers needed by this file */
#include "H5public.h"
-/* B-tree IDs for various internal things. */
-/* Not really a "public" symbol, but that should be OK -QAK */
-/* Note - if more of these are added, any 'K' values (for internal or leaf
- * nodes) they use will need to be stored in the file somewhere. -QAK
- */
-typedef enum H5B_subid_t {
- H5B_SNODE_ID = 0, /*B-tree is for symbol table nodes */
- H5B_ISTORE_ID = 1, /*B-tree is for indexed object storage */
- H5B_NUM_BTREE_ID /* Number of B-tree key IDs (must be last) */
-} H5B_subid_t;
-
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/src/H5C.c b/src/H5C.c
index 8ac9929..a6a6240 100644
--- a/src/H5C.c
+++ b/src/H5C.c
@@ -538,7 +538,7 @@ if ( ( (entry_ptr) == NULL ) || \
* More pinned entry stats related updates.
*
* JRM -- 3/31/07
- * Updated H5C__UPDATE_STATS_FOR_PROTECT() to keep stats on
+ * Updated H5C__UPDATE_STATS_FOR_PROTECT() to keep stats on
* read and write protects.
*
***********************************************************************/
@@ -1117,12 +1117,12 @@ if ( ( (cache_ptr) == NULL ) || \
* JRM -- 8/25/06
* Added the H5C_DO_SANITY_CHECKS version of the macro.
*
- * This version maintains the slist_len_increase and
+ * This version maintains the slist_len_increase and
* slist_size_increase fields that are used in sanity
* checks in the flush routines.
*
- * All this is needed as the fractal heap needs to be
- * able to dirty, resize and/or rename entries during the
+ * All this is needed as the fractal heap needs to be
+ * able to dirty, resize and/or rename entries during the
* flush.
*
*-------------------------------------------------------------------------
@@ -1209,7 +1209,7 @@ if ( ( (cache_ptr) == NULL ) || \
* Switched over to using skip list routines.
*
* JRM -- 3/28/07
- * Updated sanity checks for the new is_read_only and
+ * Updated sanity checks for the new is_read_only and
* ro_ref_count fields in H5C_cache_entry_t.
*
*-------------------------------------------------------------------------
@@ -1257,11 +1257,11 @@ if ( ( (cache_ptr) == NULL ) || \
* JRM -- 8/27/06
* Added the H5C_DO_SANITY_CHECKS version of the macro.
*
- * This version maintains the slist_size_increase field
+ * This version maintains the slist_size_increase field
* that are used in sanity checks in the flush routines.
*
- * All this is needed as the fractal heap needs to be
- * able to dirty, resize and/or rename entries during the
+ * All this is needed as the fractal heap needs to be
+ * able to dirty, resize and/or rename entries during the
* flush.
*
*-------------------------------------------------------------------------
@@ -1352,7 +1352,7 @@ if ( ( (cache_ptr) == NULL ) || \
* to do if called for such an entry.
*
* JRM -- 3/28/07
- * Added sanity checks using the new is_read_only and
+ * Added sanity checks using the new is_read_only and
* ro_ref_count fields of struct H5C_cache_entry_t.
*
*-------------------------------------------------------------------------
@@ -1494,7 +1494,7 @@ if ( ( (cache_ptr) == NULL ) || \
* be called on a pinned entry. Added assert to verify this.
*
* JRM -- 3/28/07
- * Added sanity checks for the new is_read_only and
+ * Added sanity checks for the new is_read_only and
* ro_ref_count fields of struct H5C_cache_entry_t.
*
*-------------------------------------------------------------------------
@@ -1749,7 +1749,7 @@ if ( ( (cache_ptr) == NULL ) || \
* Inserted an assert to verify this.
*
* JRM - 8/9/06
- * Not any more. We must now allow insertion of pinned
+ * Not any more. We must now allow insertion of pinned
* entries. Updated macro to support this.
*
* JRM - 3/28/07
@@ -1888,7 +1888,7 @@ if ( ( (cache_ptr) == NULL ) || \
* maintained by the replacement policy.
*
* JRM - 3/28/07
- * Added sanity checks based on the new is_read_only and
+ * Added sanity checks based on the new is_read_only and
* ro_ref_count fields of struct H5C_cache_entry_t.
*
*-------------------------------------------------------------------------
@@ -2052,7 +2052,7 @@ if ( ( (cache_ptr) == NULL ) || \
* nothing to be done.
*
* JRM - 3/28/07
- * Added sanity checks using the new is_read_only and
+ * Added sanity checks using the new is_read_only and
* ro_ref_count fields of struct H5C_cache_entry_t.
*
*-------------------------------------------------------------------------
@@ -2174,7 +2174,7 @@ if ( ( (cache_ptr) == NULL ) || \
* To do this, determine if the entry is pinned. If it is,
* update the size of the pinned entry list.
*
- * If it isn't pinned, the entry must handled by the
+ * If it isn't pinned, the entry must handled by the
* replacement policy. Update the appropriate replacement
* policy data structures.
*
@@ -2190,7 +2190,7 @@ if ( ( (cache_ptr) == NULL ) || \
* Modifications:
*
* JRM -- 3/28/07
- * Added sanity checks based on the new is_read_only and
+ * Added sanity checks based on the new is_read_only and
* ro_ref_count fields of struct H5C_cache_entry_t.
*
*-------------------------------------------------------------------------
@@ -2314,7 +2314,7 @@ if ( ( (cache_ptr) == NULL ) || \
* Modifications:
*
* JRM -- 3/28/07
- * Added sanity checks based on the new is_read_only and
+ * Added sanity checks based on the new is_read_only and
* ro_ref_count fields of struct H5C_cache_entry_t.
*
*-------------------------------------------------------------------------
@@ -2596,6 +2596,10 @@ static herr_t H5C__autoadjust__ageout__remove_all_markers(H5C_t * cache_ptr);
static herr_t H5C__autoadjust__ageout__remove_excess_markers(H5C_t * cache_ptr);
+static herr_t H5C__flash_increase_cache_size(H5C_t * cache_ptr,
+ size_t old_entry_size,
+ size_t new_entry_size);
+
static herr_t H5C_flush_single_entry(H5F_t * f,
hid_t primary_dxpl_id,
hid_t secondary_dxpl_id,
@@ -2654,7 +2658,7 @@ static herr_t H5C_verify_not_in_index(H5C_t * cache_ptr,
static void *H5C_epoch_marker_load(H5F_t *f, hid_t dxpl_id, haddr_t addr,
const void *udata1, void *udata2);
static herr_t H5C_epoch_marker_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest,
- haddr_t addr, void *thing,
+ haddr_t addr, void *thing,
unsigned *flags_ptr);
static herr_t H5C_epoch_marker_dest(H5F_t *f, void *thing);
static herr_t H5C_epoch_marker_clear(H5F_t *f, void *thing, hbool_t dest);
@@ -2827,17 +2831,21 @@ done:
*
* JRM -- 8/25/06
* Added initialization for the slist_len_increase and
- * slist_size_increase fields. These fields are used
+ * slist_size_increase fields. These fields are used
* for sanity checking in the flush process, and are not
* compiled in unless H5C_DO_SANITY_CHECKS is TRUE.
*
* JRM -- 3/28/07
- * Added initialization for the new is_read_only and
+ * Added initialization for the new is_read_only and
* ro_ref_count fields.
*
* JRM -- 7/27/07
-* Added initialization for the new evictions_enabled
-* field of H5C_t.
+ * Added initialization for the new evictions_enabled
+ * field of H5C_t.
+ *
+ * JRM -- 12/31/07
+ * Added initialization for the new flash cache size increase
+ * related fields of H5C_t.
*
*-------------------------------------------------------------------------
*/
@@ -2954,6 +2962,8 @@ H5C_create(size_t max_cache_size,
cache_ptr->dLRU_tail_ptr = NULL;
cache_ptr->size_increase_possible = FALSE;
+ cache_ptr->flash_size_increase_possible = FALSE;
+ cache_ptr->flash_size_increase_threshold = 0;
cache_ptr->size_decrease_possible = FALSE;
cache_ptr->resize_enabled = FALSE;
cache_ptr->cache_full = FALSE;
@@ -2974,6 +2984,11 @@ H5C_create(size_t max_cache_size,
(cache_ptr->resize_ctl).apply_max_increment = TRUE;
(cache_ptr->resize_ctl).max_increment = H5C__DEF_AR_MAX_INCREMENT;
+ (cache_ptr->resize_ctl).flash_incr_mode = H5C_flash_incr__off;
+ (cache_ptr->resize_ctl).flash_multiple = 1.0;
+ (cache_ptr->resize_ctl).flash_threshold = 0.25;
+
+
(cache_ptr->resize_ctl).decr_mode = H5C_decr__off;
(cache_ptr->resize_ctl).upper_hr_threshold = H5C__DEF_AR_UPPER_THRESHHOLD;
(cache_ptr->resize_ctl).decrement = H5C__DEF_AR_DECREMENT;
@@ -2993,7 +3008,10 @@ H5C_create(size_t max_cache_size,
for ( i = 0; i < H5C__MAX_EPOCH_MARKERS; i++ )
{
(cache_ptr->epoch_marker_active)[i] = FALSE;
-
+#ifndef NDEBUG
+ ((cache_ptr->epoch_markers)[i]).magic =
+ H5C__H5C_CACHE_ENTRY_T_MAGIC;
+#endif /* NDEBUG */
((cache_ptr->epoch_markers)[i]).addr = (haddr_t)i;
((cache_ptr->epoch_markers)[i]).size = (size_t)0;
((cache_ptr->epoch_markers)[i]).type = &epoch_marker_class;
@@ -3044,7 +3062,7 @@ done:
H5SL_close(cache_ptr->slist_ptr);
cache_ptr->magic = 0;
- H5FL_FREE(H5C_t, cache_ptr);
+ (void)H5FL_FREE(H5C_t, cache_ptr);
cache_ptr = NULL;
} /* end if */
@@ -3079,6 +3097,9 @@ done:
* Updated function for display the new prefix field of
* H5C_t in output.
*
+ * JRM 12/31/07
+ * Updated function to handle flash size increases.
+ *
*-------------------------------------------------------------------------
*/
void
@@ -3125,6 +3146,24 @@ H5C_def_auto_resize_rpt_fcn(H5C_t * cache_ptr,
new_min_clean_size);
break;
+ case flash_increase:
+ HDassert( old_max_cache_size < new_max_cache_size );
+
+ HDfprintf(stdout,
+ "%sflash cache resize(%d) -- size threshold = %Zu.\n",
+ cache_ptr->prefix,
+ (int)((cache_ptr->resize_ctl).flash_incr_mode),
+ cache_ptr->flash_size_increase_threshold);
+
+ HDfprintf(stdout,
+ "%s cache size increased from (%Zu/%Zu) to (%Zu/%Zu).\n",
+ cache_ptr->prefix,
+ old_max_cache_size,
+ old_min_clean_size,
+ new_max_cache_size,
+ new_min_clean_size);
+ break;
+
case decrease:
HDassert( old_max_cache_size > new_max_cache_size );
@@ -3284,7 +3323,7 @@ H5C_dest(H5F_t * f,
cache_ptr->magic = 0;
- H5FL_FREE(H5C_t, cache_ptr);
+ (void)H5FL_FREE(H5C_t, cache_ptr);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -3339,7 +3378,7 @@ H5C_dest_empty(H5C_t * cache_ptr)
cache_ptr->magic = 0;
- H5FL_FREE(H5C_t, cache_ptr);
+ (void)H5FL_FREE(H5C_t, cache_ptr);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -3351,8 +3390,8 @@ done:
*
* Function: H5C_expunge_entry
*
- * Purpose: Use this function to tell the cache to expunge an entry
- * from the cache without writing it to disk even if it is
+ * Purpose: Use this function to tell the cache to expunge an entry
+ * from the cache without writing it to disk even if it is
* dirty. The entry may not be either pinned or protected.
*
* Return: Non-negative on success/Negative on failure
@@ -3373,15 +3412,19 @@ H5C_expunge_entry(H5F_t * f,
hid_t secondary_dxpl_id,
H5C_t * cache_ptr,
const H5C_class_t * type,
- haddr_t addr)
+ haddr_t addr,
+ unsigned flags)
{
herr_t result;
- herr_t ret_value = SUCCEED; /* Return value */
hbool_t first_flush = TRUE;
+ hbool_t free_file_space;
H5C_cache_entry_t * entry_ptr = NULL;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5C_expunge_entry, FAIL)
+ free_file_space = ( (flags & H5C__FREE_FILE_SPACE_FLAG) != 0 );
+
HDassert( H5F_addr_defined(addr) );
HDassert( cache_ptr );
HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
@@ -3420,7 +3463,12 @@ H5C_expunge_entry(H5F_t * f,
"Target entry is pinned.")
}
- /* If we get this far, call H5C_flush_single_entry() with the
+ /* Pass along 'free file space' flag to cache client */
+
+ entry_ptr->free_file_space_on_destroy = free_file_space;
+
+
+ /* If we get this far, call H5C_flush_single_entry() with the
* H5C__FLUSH_INVALIDATE_FLAG and the H5C__FLUSH_CLEAR_ONLY_FLAG.
* This will clear the entry, and then delete it from the cache.
*/
@@ -3431,7 +3479,7 @@ H5C_expunge_entry(H5F_t * f,
cache_ptr,
entry_ptr->type,
entry_ptr->addr,
- H5C__FLUSH_INVALIDATE_FLAG |
+ H5C__FLUSH_INVALIDATE_FLAG |
H5C__FLUSH_CLEAR_ONLY_FLAG,
&first_flush,
TRUE);
@@ -3529,14 +3577,29 @@ done:
* Updated function to handle pinned entries.
*
* JRM -- 8/19/06
- * Added code managing the new flush_in_progress field of
+ * Added code managing the new flush_in_progress field of
* H5C_t.
*
* Also reworked function to allow for the possibility that
* entries will be dirtied, resized, or renamed during flush
- * callbacks. As a result, we may have to make multiple
+ * callbacks. As a result, we may have to make multiple
* passes through the skip list before the cache is flushed.
*
+ * JRM -- 10/13/07
+ * Added code to detect and manage the case in which a
+ * flush callback changes the s-list out from under
+ * the function. The only way I can think of in which this
+ * can happen is if a flush function loads an entry
+ * into the cache that isn't there already. Quincey tells
+ * me that this will never happen, but I'm not sure I
+ * believe him.
+ *
+ * Note that this is a pretty bad scenario if it ever
+ * happens. The code I have added should allow us to
+ * handle the situation under all but the worst conditions,
+ * but one can argue that I should just scream and die if I
+ * ever detect the condidtion.
+ *
*-------------------------------------------------------------------------
*/
herr_t
@@ -3558,6 +3621,7 @@ H5C_flush_cache(H5F_t * f,
int32_t protected_entries = 0;
H5SL_node_t * node_ptr = NULL;
H5C_cache_entry_t * entry_ptr = NULL;
+ H5C_cache_entry_t * next_entry_ptr = NULL;
#if H5C_DO_SANITY_CHECKS
int64_t flushed_entries_count;
size_t flushed_entries_size;
@@ -3620,7 +3684,29 @@ H5C_flush_cache(H5F_t * f,
{
flushed_entries_last_pass = FALSE;
node_ptr = H5SL_first(cache_ptr->slist_ptr);
-
+
+ if ( node_ptr != NULL ) {
+
+ next_entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
+
+ if ( next_entry_ptr == NULL ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "next_entry_ptr == NULL 1 ?!?!");
+ }
+#ifndef NDEBUG
+ HDassert( next_entry_ptr->magic ==
+ H5C__H5C_CACHE_ENTRY_T_MAGIC );
+#endif /* NDEBUG */
+ HDassert( next_entry_ptr->is_dirty );
+ HDassert( next_entry_ptr->in_slist );
+
+ } else {
+
+ next_entry_ptr = NULL;
+
+ }
+
HDassert( node_ptr != NULL );
#if H5C_DO_SANITY_CHECKS
@@ -3635,7 +3721,7 @@ H5C_flush_cache(H5F_t * f,
* fractal heap, the entry flush callback can cause entries
* to be dirtied, resized, and/or renamed.
*
- * To deal with this, we first make note of the initial
+ * To deal with this, we first make note of the initial
* skip list length and size:
*/
initial_slist_len = cache_ptr->slist_len;
@@ -3647,12 +3733,12 @@ H5C_flush_cache(H5F_t * f,
flushed_entries_count = 0;
flushed_entries_size = 0;
- /* As mentioned above, there is the possibility that
+ /* As mentioned above, there is the possibility that
* entries will be dirtied, resized, and/or flushed during
- * our pass through the skip list. To capture the number
- * of entries added, and the skip list size delta,
+ * our pass through the skip list. To capture the number
+ * of entries added, and the skip list size delta,
* zero the slist_len_increase and slist_size_increase of
- * the cache's instance of H5C_t. These fields will be
+ * the cache's instance of H5C_t. These fields will be
* updated elsewhere to account for slist insertions and/or
* dirty entry size changes.
*/
@@ -3667,17 +3753,80 @@ H5C_flush_cache(H5F_t * f,
while ( node_ptr != NULL )
{
- entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
+ entry_ptr = next_entry_ptr;
+
+ /* With the advent of the fractal heap, it is possible
+ * that the flush callback will dirty and/or resize
+ * other entries in the cache. In particular, while
+ * Quincey has promised me that this will never happen,
+ * it is possible that the flush callback for an
+ * entry may protect an entry that is not in the cache,
+ * perhaps causing the cache to flush and possibly
+ * evict the entry associated with node_ptr to make
+ * space for the new entry.
+ *
+ * Thus we do a bit of extra sanity checking on entry_ptr,
+ * and break out of this scan of the skip list if we
+ * detect minor problems. We have a bit of leaway on the
+ * number of passes though the skip list, so this shouldn't
+ * be an issue in the flush in and of itself, as it should
+ * be all but impossible for this to happen more than once
+ * in any flush.
+ *
+ * Observe that that breaking out of the scan early
+ * shouldn't break the sanity checks just after the end
+ * of this while loop.
+ *
+ * If an entry has merely been marked clean and removed from
+ * the s-list, we simply break out of the scan.
+ *
+ * If the entry has been evicted, we flag an error and
+ * exit.
+ */
+#ifndef NDEBUG
+ if ( entry_ptr->magic != H5C__H5C_CACHE_ENTRY_T_MAGIC ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "entry_ptr->magic invalid ?!?!");
+
+ } else
+#endif /* NDEBUG */
+ if ( ( ! entry_ptr->is_dirty ) ||
+ ( ! entry_ptr->in_slist ) ) {
+
+ /* the s-list has been modified out from under us.
+ * set node_ptr to NULL and break out of the loop.
+ */
+ node_ptr = NULL;
+ break;
+ }
/* increment node pointer now, before we delete its target
* from the slist.
*/
node_ptr = H5SL_next(node_ptr);
+ if ( node_ptr != NULL ) {
+ next_entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
+
+ if ( next_entry_ptr == NULL ) {
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "next_entry_ptr == NULL 2 ?!?!");
+ }
+#ifndef NDEBUG
+ HDassert( next_entry_ptr->magic ==
+ H5C__H5C_CACHE_ENTRY_T_MAGIC );
+#endif /* NDEBUG */
+ HDassert( next_entry_ptr->is_dirty );
+ HDassert( next_entry_ptr->in_slist );
+ } else {
+ next_entry_ptr = NULL;
+ }
+
HDassert( entry_ptr != NULL );
HDassert( entry_ptr->in_slist );
- if ( ( ! flush_marked_entries ) ||
+ if ( ( ! flush_marked_entries ) ||
( entry_ptr->flush_marker ) ) {
if ( entry_ptr->is_protected ) {
@@ -3689,6 +3838,40 @@ H5C_flush_cache(H5F_t * f,
tried_to_flush_protected_entry = TRUE;
protected_entries++;
+ } else if ( entry_ptr->is_pinned ) {
+ /* Test to see if we are can flush the entry now.
+ * If we can, go ahead and flush. Note that we
+ * aren't trying to do a destroy here, so that
+ * is not an issue.
+ */
+ if ( TRUE ) { /* When we get to multithreaded cache,
+ * we will need either locking code,
+ * and/or a test to see if the entry
+ * is in flushable condition here.
+ */
+#if H5C_DO_SANITY_CHECKS
+ flushed_entries_count++;
+ flushed_entries_size += entry_ptr->size;
+#endif /* H5C_DO_SANITY_CHECKS */
+ status = H5C_flush_single_entry(f,
+ primary_dxpl_id,
+ secondary_dxpl_id,
+ cache_ptr,
+ NULL,
+ entry_ptr->addr,
+ flags,
+ &first_flush,
+ FALSE);
+ if ( status < 0 ) {
+
+ /* This shouldn't happen -- if it does, we are
+ * toast so just scream and die.
+ */
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
+ "dirty pinned entry flush failed.")
+ }
+ flushed_entries_last_pass = TRUE;
+ }
} else {
#if H5C_DO_SANITY_CHECKS
flushed_entries_count++;
@@ -3705,7 +3888,7 @@ H5C_flush_cache(H5F_t * f,
FALSE);
if ( status < 0 ) {
- /* This shouldn't happen -- if it does, we are
+ /* This shouldn't happen -- if it does, we are
* toast so just scream and die.
*/
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, \
@@ -3719,7 +3902,7 @@ H5C_flush_cache(H5F_t * f,
#if H5C_DO_SANITY_CHECKS
/* Verify that the slist size and length are as expected. */
- HDassert( (initial_slist_len + cache_ptr->slist_len_increase -
+ HDassert( (initial_slist_len + cache_ptr->slist_len_increase -
flushed_entries_count) == cache_ptr->slist_len );
HDassert( (initial_slist_size + cache_ptr->slist_size_increase -
flushed_entries_size) == cache_ptr->slist_size );
@@ -3810,7 +3993,7 @@ done:
* find a case where it helps, lets get rid of it.
*
*
- * Added some sanity checks to the change which verify the
+ * Added some sanity checks to the change which verify the
* expected values of the new is_read_only and ro_ref_count
* fields.
* JRM - 3/29/07
@@ -4317,7 +4500,7 @@ done:
* Purpose: Get the trace_file_ptr field from the cache.
*
* This field will either be NULL (which indicates that trace
- * file logging is turned off), or contain a pointer to the
+ * file logging is turned off), or contain a pointer to the
* open file to which trace file data is to be written.
*
* Return: Non-negative on success/Negative on failure
@@ -4427,13 +4610,20 @@ done:
* destroy_in_progress fields.
*
* JRM -- 3/29/07
- * Added initialization for the new is_read_only and
+ * Added initialization for the new is_read_only and
* ro_ref_count fields.
*
* JRM -- 8/1/07
- * Added code to disable evictions when the new
+ * Added code to disable evictions when the new
* evictions_enabled field is FALSE.
*
+ * JRM -- 12/31/07
+ * Added code supporting flash cache size increases.
+ *
+ * QAK -- 1/31/08
+ * Added initialization for the new free_file_space_on_destroy
+ * field.
+ *
*-------------------------------------------------------------------------
*/
@@ -4447,6 +4637,7 @@ H5C_insert_entry(H5F_t * f,
void * thing,
unsigned int flags)
{
+ /* const char * fcn_name = "H5C_insert_entry()"; */
herr_t result;
herr_t ret_value = SUCCEED; /* Return value */
hbool_t first_flush = TRUE;
@@ -4486,7 +4677,9 @@ H5C_insert_entry(H5F_t * f,
insert_pinned = ( (flags & H5C__PIN_ENTRY_FLAG) != 0 );
entry_ptr = (H5C_cache_entry_t *)thing;
-
+#ifndef NDEBUG
+ entry_ptr->magic = H5C__H5C_CACHE_ENTRY_T_MAGIC;
+#endif /* NDEBUG */
entry_ptr->addr = addr;
entry_ptr->type = type;
@@ -4512,6 +4705,7 @@ H5C_insert_entry(H5F_t * f,
entry_ptr->flush_in_progress = FALSE;
entry_ptr->destroy_in_progress = FALSE;
+ entry_ptr->free_file_space_on_destroy = FALSE;
entry_ptr->ht_next = NULL;
entry_ptr->ht_prev = NULL;
@@ -4524,8 +4718,20 @@ H5C_insert_entry(H5F_t * f,
H5C__RESET_CACHE_ENTRY_STATS(entry_ptr)
+ if ( ( cache_ptr->flash_size_increase_possible ) &&
+ ( entry_ptr->size > cache_ptr->flash_size_increase_threshold ) ) {
+
+ result = H5C__flash_increase_cache_size(cache_ptr, 0, entry_ptr->size);
+
+ if ( result < 0 ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTINS, FAIL, \
+ "H5C__flash_increase_cache_size failed.")
+ }
+ }
+
if ( ( cache_ptr->evictions_enabled ) &&
- ( (cache_ptr->index_size + entry_ptr->size) >
+ ( (cache_ptr->index_size + entry_ptr->size) >
cache_ptr->max_cache_size ) ) {
size_t space_needed;
@@ -4999,7 +5205,9 @@ done:
*
* Modifications:
*
- * None
+ * Added code to do a flash cache size increase if
+ * appropriate.
+ * JRM -- 1/11/08
*
*-------------------------------------------------------------------------
*/
@@ -5010,6 +5218,8 @@ H5C_mark_pinned_entry_dirty(H5C_t * cache_ptr,
size_t new_size)
{
herr_t ret_value = SUCCEED; /* Return value */
+ herr_t result;
+ size_t size_increase;
H5C_cache_entry_t * entry_ptr;
FUNC_ENTER_NOAPI(H5C_mark_pinned_entry_dirty, FAIL)
@@ -5039,6 +5249,29 @@ H5C_mark_pinned_entry_dirty(H5C_t * cache_ptr,
/* update for change in entry size if necessary */
if ( ( size_changed ) && ( entry_ptr->size != new_size ) ) {
+ /* do a flash cache size increase if appropriate */
+ if ( cache_ptr->flash_size_increase_possible ) {
+
+ if ( new_size > entry_ptr->size ) {
+
+ size_increase = new_size - entry_ptr->size;
+
+ if ( size_increase >=
+ cache_ptr->flash_size_increase_threshold ) {
+
+ result = H5C__flash_increase_cache_size(cache_ptr,
+ entry_ptr->size,
+ new_size);
+
+ if ( result < 0 ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \
+ "H5C__flash_increase_cache_size failed.")
+ }
+ }
+ }
+ }
+
/* update the protected entry list */
H5C__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr->pel_len), \
(cache_ptr->pel_size), \
@@ -5275,7 +5508,7 @@ H5C_rename_entry(H5C_t * cache_ptr,
* Since this is a simple re-name, cache size should be unaffected.
*
* Check to see if the target entry is in the process of being destroyed
- * before we delete from the index, etc. If it is, all we do is
+ * before we delete from the index, etc. If it is, all we do is
* change the addr. If the entry is only in the process of being flushed,
* don't mark it as dirty either, lest we confuse the flush call back.
*/
@@ -5319,7 +5552,7 @@ H5C_rename_entry(H5C_t * cache_ptr,
if ( removed_entry_from_slist ) {
- /* we just removed the entry from the slist. Thus we
+ /* we just removed the entry from the slist. Thus we
* must touch up cache_ptr->slist_len_increase and
* cache_ptr->slist_size_increase to keep from skewing
* the sanity checks.
@@ -5360,8 +5593,8 @@ done:
* Purpose: Resize a pinned entry. The target entry MUST be
* be pinned, and MUST not be unprotected.
*
- * Resizing an entry dirties it, so if the entry is not
- * already dirty, the function places the entry on the
+ * Resizing an entry dirties it, so if the entry is not
+ * already dirty, the function places the entry on the
* skip list.
*
* Return: Non-negative on success/Negative on failure
@@ -5371,7 +5604,9 @@ done:
*
* Modifications:
*
- * None
+ * Added code to apply a flash cache size increment if
+ * appropriate.
+ * JRM -- 1/11/08
*
*-------------------------------------------------------------------------
*/
@@ -5380,8 +5615,11 @@ H5C_resize_pinned_entry(H5C_t * cache_ptr,
void * thing,
size_t new_size)
{
+ /* const char * fcn_name = "H5C_resize_pinned_entry()"; */
herr_t ret_value = SUCCEED; /* Return value */
+ herr_t result;
H5C_cache_entry_t * entry_ptr;
+ size_t size_increase;
FUNC_ENTER_NOAPI(H5C_resize_pinned_entry, FAIL)
@@ -5409,14 +5647,37 @@ H5C_resize_pinned_entry(H5C_t * cache_ptr,
"Entry is protected??")
}
- /* resizing dirties entries -- mark the entry as dirty if it
- * isn't already
+ /* resizing dirties entries -- mark the entry as dirty if it
+ * isn't already
*/
entry_ptr->is_dirty = TRUE;
/* update for change in entry size if necessary */
if ( entry_ptr->size != new_size ) {
+ /* do a flash cache size increase if appropriate */
+ if ( cache_ptr->flash_size_increase_possible ) {
+
+ if ( new_size > entry_ptr->size ) {
+
+ size_increase = new_size - entry_ptr->size;
+
+ if ( size_increase >=
+ cache_ptr->flash_size_increase_threshold ) {
+
+ result = H5C__flash_increase_cache_size(cache_ptr,
+ entry_ptr->size,
+ new_size);
+
+ if ( result < 0 ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \
+ "H5C__flash_increase_cache_size failed.")
+ }
+ }
+ }
+ }
+
/* update the protected entry list */
H5C__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr->pel_len), \
(cache_ptr->pel_size), \
@@ -5473,12 +5734,12 @@ done:
* entries.
*
* JRM -- 2/16/07
- * Added conditional compile to avoid unused parameter
+ * Added conditional compile to avoid unused parameter
* warning in production compile.
*
* JRM -- 4/4/07
- * Fixed typo -- canged macro call to
- * H5C__UPDATE_STATS_FOR_UNPIN to call to
+ * Fixed typo -- canged macro call to
+ * H5C__UPDATE_STATS_FOR_UNPIN to call to
* H5C__UPDATE_STATS_FOR_PIN.
*
*-------------------------------------------------------------------------
@@ -5592,21 +5853,25 @@ done:
*
* JRM -- 6/23/06
* Modified code to allow dirty entries to be loaded from
- * disk. This is necessary as a bug fix in the object
+ * disk. This is necessary as a bug fix in the object
* header code requires us to modify a header as it is read.
*
* JRM -- 3/28/07
* Added the flags parameter and supporting code. At least
- * for now, this parameter is used to allow the entry to
+ * for now, this parameter is used to allow the entry to
* be protected read only, thus allowing multiple protects.
*
* Also added code to allow multiple read only protects
* of cache entries.
*
* JRM -- 7/27/07
- * Added code supporting the new evictions_enabled fieled
+ * Added code supporting the new evictions_enabled field
* in H5C_t.
*
+ * JRM -- 1/3/08
+ * Added to do a flash cache size increase if appropriate
+ * when a large entry is loaded.
+ *
*-------------------------------------------------------------------------
*/
@@ -5621,6 +5886,7 @@ H5C_protect(H5F_t * f,
void * udata2,
unsigned flags)
{
+ /* const char * fcn_name = "H5C_protect()"; */
hbool_t hit;
hbool_t first_flush;
hbool_t have_write_permitted = FALSE;
@@ -5678,9 +5944,27 @@ H5C_protect(H5F_t * f,
entry_ptr = (H5C_cache_entry_t *)thing;
- /* try to free up some space if necessary and if evictions are permitted */
+ /* If the entry is very large, and we are configured to allow it,
+ * we may wish to perform a flash cache size increase.
+ */
+ if ( ( cache_ptr->flash_size_increase_possible ) &&
+ ( entry_ptr->size > cache_ptr->flash_size_increase_threshold ) ) {
+
+ result = H5C__flash_increase_cache_size(cache_ptr, 0,
+ entry_ptr->size);
+
+ if ( result < 0 ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTPROTECT, NULL, \
+ "H5C__flash_increase_cache_size failed.")
+ }
+ }
+
+ /* try to free up some space if necessary and if evictions are
+ * permitted
+ */
if ( ( cache_ptr->evictions_enabled ) &&
- ( (cache_ptr->index_size + entry_ptr->size) >
+ ( (cache_ptr->index_size + entry_ptr->size) >
cache_ptr->max_cache_size ) ) {
size_t space_needed;
@@ -5786,7 +6070,7 @@ H5C_protect(H5F_t * f,
if ( entry_ptr->is_protected ) {
if ( ( read_only ) && ( entry_ptr->is_read_only ) ) {
-
+
HDassert( entry_ptr->ro_ref_count > 0 );
(entry_ptr->ro_ref_count)++;
@@ -5978,6 +6262,10 @@ done:
* if the new configuration forces an immediate reduction
* in cache size.
*
+ * JRM -- 12/31/07
+ * Added code supporting the new flash cache size increase
+ * code.
+ *
*-------------------------------------------------------------------------
*/
@@ -5985,6 +6273,7 @@ herr_t
H5C_set_cache_auto_resize_config(H5C_t * cache_ptr,
H5C_auto_size_ctl_t *config_ptr)
{
+ /* const char *fcn_name = "H5C_set_cache_auto_resize_config()"; */
herr_t ret_value = SUCCEED; /* Return value */
herr_t result;
size_t new_max_cache_size;
@@ -6039,8 +6328,10 @@ H5C_set_cache_auto_resize_config(H5C_t * cache_ptr,
"conflicting threshold fields in new config.")
}
- cache_ptr->size_increase_possible = TRUE; /* will set to FALSE if needed */
- cache_ptr->size_decrease_possible = TRUE; /* will set to FALSE if needed */
+ /* will set the increase possible fields to FALSE later if needed */
+ cache_ptr->size_increase_possible = TRUE;
+ cache_ptr->flash_size_increase_possible = TRUE;
+ cache_ptr->size_decrease_possible = TRUE;
switch ( config_ptr->incr_mode )
{
@@ -6062,6 +6353,11 @@ H5C_set_cache_auto_resize_config(H5C_t * cache_ptr,
HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Unknown incr_mode?!?!?.")
}
+ /* logically, this is were configuration for flash cache size increases
+ * should go. However, this configuration depends on max_cache_size, so
+ * we wait until the end of the function, when this field is set.
+ */
+
switch ( config_ptr->decr_mode )
{
case H5C_decr__off:
@@ -6106,9 +6402,13 @@ H5C_set_cache_auto_resize_config(H5C_t * cache_ptr,
if ( config_ptr->max_size == config_ptr->min_size ) {
cache_ptr->size_increase_possible = FALSE;
+ cache_ptr->flash_size_increase_possible = FALSE;
cache_ptr->size_decrease_possible = FALSE;
}
+ /* flash_size_increase_possible is intentionally omitted from the
+ * following:
+ */
cache_ptr->resize_enabled = cache_ptr->size_increase_possible ||
cache_ptr->size_decrease_possible;
@@ -6196,6 +6496,37 @@ H5C_set_cache_auto_resize_config(H5C_t * cache_ptr,
}
}
+ /* configure flash size increase facility. We wait until the
+ * end of the function, as we need the max_cache_size set before
+ * we start to keep things simple.
+ *
+ * If we haven't already ruled out flash cache size increases above,
+ * go ahead and configure it.
+ */
+
+ if ( cache_ptr->flash_size_increase_possible ) {
+
+ switch ( config_ptr->flash_incr_mode )
+ {
+ case H5C_flash_incr__off:
+ cache_ptr->flash_size_increase_possible = FALSE;
+ break;
+
+ case H5C_flash_incr__add_space:
+ cache_ptr->flash_size_increase_possible = TRUE;
+ cache_ptr->flash_size_increase_threshold =
+ (size_t)
+ (((double)(cache_ptr->max_cache_size)) *
+ ((cache_ptr->resize_ctl).flash_threshold));
+ break;
+
+ default: /* should be unreachable */
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "Unknown flash_incr_mode?!?!?.")
+ break;
+ }
+ }
+
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -6206,7 +6537,7 @@ done:
/*-------------------------------------------------------------------------
* Function: H5C_set_evictions_enabled()
*
- * Purpose: Set cache_ptr->evictions_enabled to the value of the
+ * Purpose: Set cache_ptr->evictions_enabled to the value of the
* evictions enabled parameter.
*
* Return: SUCCEED on success, and FAIL on failure.
@@ -6240,9 +6571,9 @@ H5C_set_evictions_enabled(H5C_t * cache_ptr,
"Bad evictions_enabled on entry.")
}
- /* There is no fundamental reason why we should not permit
+ /* There is no fundamental reason why we should not permit
* evictions to be disabled while automatic resize is enabled.
- * However, I can't think of any good reason why one would
+ * However, I can't think of any good reason why one would
* want to, and allowing it would greatly complicate testing
* the feature. Hence the following:
*/
@@ -6426,8 +6757,8 @@ done:
* JRM -- 8/23/06
* Added code supporting new flush related statistics.
*
- * JRM -- 3/31/07
- * Added code supporting the new write_protects,
+ * JRM -- 3/31/07
+ * Added code supporting the new write_protects,
* read_protects, and max_read_protects fields.
*
*-------------------------------------------------------------------------
@@ -6514,9 +6845,9 @@ H5C_stats(H5C_t * cache_ptr,
+= cache_ptr->cache_flush_renames[i];
total_size_increases += cache_ptr->size_increases[i];
total_size_decreases += cache_ptr->size_decreases[i];
- total_entry_flush_size_changes
+ total_entry_flush_size_changes
+= cache_ptr->entry_flush_size_changes[i];
- total_cache_flush_size_changes
+ total_cache_flush_size_changes
+= cache_ptr->cache_flush_size_changes[i];
total_pins += cache_ptr->pins[i];
total_unpins += cache_ptr->unpins[i];
@@ -6658,14 +6989,14 @@ H5C_stats(H5C_t * cache_ptr,
(long)total_flushes,
(long)total_evictions);
- HDfprintf(stdout,
+ HDfprintf(stdout,
"%s Total insertions(pinned) / renames = %ld(%ld) / %ld\n",
cache_ptr->prefix,
(long)total_insertions,
(long)total_pinned_insertions,
(long)total_renames);
- HDfprintf(stdout,
+ HDfprintf(stdout,
"%s Total entry / cache flush renames = %ld / %ld\n",
cache_ptr->prefix,
(long)total_entry_flush_renames,
@@ -6847,7 +7178,7 @@ done:
* JRM - 3/20/06
* Updated for pin / unpin related statistics.
*
- * JRM - 8/9/06
+ * JRM - 8/9/06
* Further updates for pin related statistics.
*
* JRM 8/23/06
@@ -6858,7 +7189,7 @@ done:
* warning in the production build.
*
* JRM 3/31/07
- * Added initialization for the new write_protects,
+ * Added initialization for the new write_protects,
* read_protects, and max_read_protects fields.
*
*-------------------------------------------------------------------------
@@ -7089,12 +7420,23 @@ done:
* equivalent of setting the H5C__DIRTIED_FLAG.
*
* JRM -- 3/29/07
- * Modified function to allow a entry to be protected
+ * Modified function to allow a entry to be protected
* more than once if the entry is protected read only.
*
* Also added sanity checks using the new is_read_only and
* ro_ref_count parameters.
*
+ * JRM -- 12/31/07
+ * Modified function to support flash cache resizes.
+ *
+ * QAK -- 1/31/08
+ * Modified function to support freeing file space in client's
+ * 'dest' callback routine.
+ *
+ * QAK -- 2/07/08
+ * Separated "destroy entry" concept from "remove entry from
+ * cache" concept, by adding the 'take_ownership' flag.
+ *
*-------------------------------------------------------------------------
*/
herr_t
@@ -7108,16 +7450,21 @@ H5C_unprotect(H5F_t * f,
unsigned int flags,
size_t new_size)
{
+ /* const char * fcn_name = "H5C_unprotect()"; */
hbool_t deleted;
hbool_t dirtied;
hbool_t set_flush_marker;
hbool_t size_changed;
hbool_t pin_entry;
hbool_t unpin_entry;
+ hbool_t free_file_space;
+ hbool_t take_ownership;
#ifdef H5_HAVE_PARALLEL
hbool_t clear_entry = FALSE;
#endif /* H5_HAVE_PARALLEL */
herr_t ret_value = SUCCEED; /* Return value */
+ herr_t result;
+ size_t size_increase = 0;
H5C_cache_entry_t * entry_ptr;
H5C_cache_entry_t * test_entry_ptr;
@@ -7129,6 +7476,8 @@ H5C_unprotect(H5F_t * f,
size_changed = ( (flags & H5C__SIZE_CHANGED_FLAG) != 0 );
pin_entry = ( (flags & H5C__PIN_ENTRY_FLAG) != 0 );
unpin_entry = ( (flags & H5C__UNPIN_ENTRY_FLAG) != 0 );
+ free_file_space = ( (flags & H5C__FREE_FILE_SPACE_FLAG) != 0 );
+ take_ownership = ( (flags & H5C__TAKE_OWNERSHIP_FLAG) != 0 );
/* Changing the size of an entry dirties it. Thus, set the
* dirtied flag if the size_changed flag is set.
@@ -7148,6 +7497,9 @@ H5C_unprotect(H5F_t * f,
HDassert( ( ! size_changed ) || ( dirtied ) );
HDassert( ( ! size_changed ) || ( new_size > 0 ) );
HDassert( ! ( pin_entry && unpin_entry ) );
+ HDassert( ( ! free_file_space ) || ( deleted ) ); /* deleted flag must accompany free_file_space */
+ HDassert( ( ! take_ownership ) || ( deleted ) ); /* deleted flag must accompany take_ownership */
+ HDassert( ! ( free_file_space && take_ownership ) ); /* can't have both free_file_space & take_ownership */
entry_ptr = (H5C_cache_entry_t *)thing;
@@ -7265,6 +7617,29 @@ H5C_unprotect(H5F_t * f,
/* update for change in entry size if necessary */
if ( ( size_changed ) && ( entry_ptr->size != new_size ) ) {
+ /* do a flash cache size increase if appropriate */
+ if ( cache_ptr->flash_size_increase_possible ) {
+
+ if ( new_size > entry_ptr->size ) {
+
+ size_increase = new_size - entry_ptr->size;
+
+ if ( size_increase >=
+ cache_ptr->flash_size_increase_threshold ) {
+
+ result = H5C__flash_increase_cache_size(cache_ptr,
+ entry_ptr->size,
+ new_size);
+
+ if ( result < 0 ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \
+ "H5C__flash_increase_cache_size failed.")
+ }
+ }
+ }
+ }
+
/* update the protected list */
H5C__DLL_UPDATE_FOR_SIZE_CHANGE((cache_ptr->pl_len), \
(cache_ptr->pl_size), \
@@ -7350,7 +7725,9 @@ H5C_unprotect(H5F_t * f,
* H5C__FLUSH_CLEAR_ONLY_FLAG and H5C__FLUSH_INVALIDATE_FLAG flags.
* However, it is needed for the function call.
*/
- hbool_t dummy_first_flush = TRUE;
+ hbool_t dummy_first_flush = TRUE;
+ unsigned flush_flags = (H5C__FLUSH_CLEAR_ONLY_FLAG |
+ H5C__FLUSH_INVALIDATE_FLAG);
/* we can't delete a pinned entry */
HDassert ( ! (entry_ptr->is_pinned ) );
@@ -7370,14 +7747,23 @@ H5C_unprotect(H5F_t * f,
"hash table contains multiple entries for addr?!?.")
}
+ /* Pass along 'free file space' flag to cache client */
+
+ entry_ptr->free_file_space_on_destroy = free_file_space;
+
+ /* Set the "take ownership" flag for the flush, if needed */
+ if ( take_ownership) {
+
+ flush_flags |= H5C__TAKE_OWNERSHIP_FLAG;
+ }
+
if ( H5C_flush_single_entry(f,
primary_dxpl_id,
secondary_dxpl_id,
cache_ptr,
type,
addr,
- (H5C__FLUSH_CLEAR_ONLY_FLAG |
- H5C__FLUSH_INVALIDATE_FLAG),
+ flush_flags,
&dummy_first_flush,
TRUE) < 0 ) {
@@ -7388,8 +7774,8 @@ H5C_unprotect(H5F_t * f,
else if ( clear_entry ) {
/* the following first flush flag will never be used as we are
- * calling H5C_flush_single_entry with the
- * H5C__FLUSH_CLEAR_ONLY_FLAG flag. However, it is needed for
+ * calling H5C_flush_single_entry with the
+ * H5C__FLUSH_CLEAR_ONLY_FLAG flag. However, it is needed for
* the function call.
*/
hbool_t dummy_first_flush = TRUE;
@@ -7458,7 +7844,9 @@ done:
*
* Modifications:
*
- * None.
+ * Added validation for the flash increment fields.
+ *
+ * JRM -- 12/31/07
*
*-------------------------------------------------------------------------
*/
@@ -7560,7 +7948,7 @@ H5C_validate_resize_config(H5C_auto_size_ctl_t * config_ptr,
( config_ptr->apply_max_increment != FALSE ) ) {
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, \
- "apply_max_increment must be either TRUE or FALSE");
+ "apply_max_increment must be either TRUE or FALSE");
}
/* no need to check max_increment, as it is a size_t,
@@ -7568,6 +7956,33 @@ H5C_validate_resize_config(H5C_auto_size_ctl_t * config_ptr,
*/
} /* H5C_incr__threshold */
+ switch ( config_ptr->flash_incr_mode )
+ {
+ case H5C_flash_incr__off:
+ /* nothing to do here */
+ break;
+
+ case H5C_flash_incr__add_space:
+ if ( ( config_ptr->flash_multiple < 0.1 ) ||
+ ( config_ptr->flash_multiple > 10.0 ) ) {
+
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, \
+ "flash_multiple must be in the range [0.1, 10.0]");
+ }
+
+ if ( ( config_ptr->flash_threshold < 0.1 ) ||
+ ( config_ptr->flash_threshold > 1.0 ) ) {
+
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, \
+ "flash_threshold must be in the range [0.1, 1.0]");
+ }
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, \
+ "Invalid flash_incr_mode");
+ break;
+ }
} /* H5C_RESIZE_CFG__VALIDATE_INCREMENT */
@@ -7707,6 +8122,9 @@ done:
* reduction, and to adjust to changes in the
* H5C_auto_size_ctl_t structure.
*
+ * JRM -- 1/5/08
+ * Added support for flash cache size increases.
+ *
*-------------------------------------------------------------------------
*/
@@ -7990,6 +8408,30 @@ H5C__auto_adjust_cache_size(H5C_t * cache_ptr,
cache_ptr->size_decreased = TRUE;
}
+
+ /* update flash cache size increase fields as appropriate */
+ if ( cache_ptr->flash_size_increase_possible ) {
+
+ switch ( (cache_ptr->resize_ctl).flash_incr_mode )
+ {
+ case H5C_flash_incr__off:
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "flash_size_increase_possible but H5C_flash_incr__off?!")
+ break;
+
+ case H5C_flash_incr__add_space:
+ cache_ptr->flash_size_increase_threshold =
+ (size_t)
+ (((double)(cache_ptr->max_cache_size)) *
+ ((cache_ptr->resize_ctl).flash_threshold));
+ break;
+
+ default: /* should be unreachable */
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "Unknown flash_incr_mode?!?!?.")
+ break;
+ }
+ }
}
if ( (cache_ptr->resize_ctl).rpt_fcn != NULL ) {
@@ -8308,7 +8750,20 @@ done:
*
* Modifications:
*
- * None.
+ * JRM -- 10/13/07
+ * Added code to detect and manage the case in which a
+ * flush callback changes the LRU-list out from under
+ * the function. The only way I can think of in which this
+ * can happen is if a flush function loads an entry
+ * into the cache that isn't there already. Quincey tells
+ * me that this will never happen, but I'm not sure I
+ * believe him.
+ *
+ * Note that this is a pretty bad scenario if it ever
+ * happens. The code I have added should allow us to
+ * handle the situation under all but the worst conditions,
+ * but one can argue that I should just scream and die if I
+ * ever detect the condidtion.
*
*-------------------------------------------------------------------------
*/
@@ -8325,7 +8780,9 @@ H5C__autoadjust__ageout__evict_aged_out_entries(H5F_t * f,
herr_t result;
size_t eviction_size_limit;
size_t bytes_evicted = 0;
+ hbool_t prev_is_dirty = FALSE;
H5C_cache_entry_t * entry_ptr;
+ H5C_cache_entry_t * next_ptr;
H5C_cache_entry_t * prev_ptr;
FUNC_ENTER_NOAPI_NOINIT(H5C__autoadjust__ageout__evict_aged_out_entries)
@@ -8358,8 +8815,14 @@ H5C__autoadjust__ageout__evict_aged_out_entries(H5F_t * f,
{
HDassert( ! (entry_ptr->is_protected) );
+ next_ptr = entry_ptr->next;
prev_ptr = entry_ptr->prev;
+ if ( prev_ptr != NULL ) {
+
+ prev_is_dirty = prev_ptr->is_dirty;
+ }
+
if ( entry_ptr->is_dirty ) {
result = H5C_flush_single_entry(f,
@@ -8392,8 +8855,41 @@ H5C__autoadjust__ageout__evict_aged_out_entries(H5F_t * f,
"unable to flush entry")
}
- entry_ptr = prev_ptr;
+ if ( prev_ptr != NULL ) {
+#ifndef NDEBUG
+ if ( prev_ptr->magic != H5C__H5C_CACHE_ENTRY_T_MAGIC ) {
+
+ /* something horrible has happened to *prev_ptr --
+ * scream and die.
+ */
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "*prev_ptr corrupt")
+
+ } else
+#endif /* NDEBUG */
+ if ( ( prev_ptr->is_dirty != prev_is_dirty )
+ ||
+ ( prev_ptr->next != next_ptr )
+ ||
+ ( prev_ptr->is_protected )
+ ||
+ ( prev_ptr->is_pinned ) ) {
+
+ /* something has happened to the LRU -- start over
+ * from the tail.
+ */
+ entry_ptr = cache_ptr->LRU_tail_ptr;
+
+ } else {
+ entry_ptr = prev_ptr;
+
+ }
+ } else {
+
+ entry_ptr = NULL;
+
+ }
} /* end while */
/* for now at least, don't bother to maintain the minimum clean size,
@@ -8741,6 +9237,173 @@ done:
} /* H5C__autoadjust__ageout__remove_excess_markers() */
+/*-------------------------------------------------------------------------
+ *
+ * Function: H5C__flash_increase_cache_size
+ *
+ * Purpose: If there is not at least new_entry_size - old_entry_size
+ * bytes of free space in the cache and the current
+ * max_cache_size is less than (cache_ptr->resize_ctl).max_size,
+ * perform a flash increase in the cache size and then reset
+ * the full cache hit rate statistics, and exit.
+ *
+ * Return: Non-negative on success/Negative on failure.
+ *
+ * Programmer: John Mainzer, 12/31/07
+ *
+ * Modifications:
+ *
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static herr_t
+H5C__flash_increase_cache_size(H5C_t * cache_ptr,
+ size_t old_entry_size,
+ size_t new_entry_size)
+{
+ /* const char * fcn_name = "H5C__flash_increase_cache_size()";*/
+ herr_t ret_value = SUCCEED; /* Return value */
+ size_t new_max_cache_size = 0;
+ size_t old_max_cache_size = 0;
+ size_t new_min_clean_size = 0;
+ size_t old_min_clean_size = 0;
+ size_t space_needed;
+ enum H5C_resize_status status = flash_increase; /* may change */
+ double hit_rate;
+
+ FUNC_ENTER_NOAPI_NOINIT(H5C__flash_increase_cache_size)
+ HDassert( cache_ptr );
+ HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC );
+ HDassert( cache_ptr->flash_size_increase_possible );
+ HDassert( new_entry_size > cache_ptr->flash_size_increase_threshold );
+ HDassert( old_entry_size < new_entry_size );
+
+ if ( old_entry_size >= new_entry_size ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "old_entry_size >= new_entry_size")
+ }
+
+ space_needed = new_entry_size - old_entry_size;
+
+ if ( ( (cache_ptr->index_size + space_needed) >
+ cache_ptr->max_cache_size ) &&
+ ( cache_ptr->max_cache_size < (cache_ptr->resize_ctl).max_size ) ) {
+
+ /* we have work to do */
+
+ switch ( (cache_ptr->resize_ctl).flash_incr_mode )
+ {
+ case H5C_flash_incr__off:
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "flash_size_increase_possible but H5C_flash_incr__off?!")
+ break;
+
+ case H5C_flash_incr__add_space:
+ if ( cache_ptr->index_size < cache_ptr->max_cache_size ) {
+
+ HDassert( (cache_ptr->max_cache_size - cache_ptr->index_size)
+ < space_needed );
+ space_needed -= cache_ptr->max_cache_size - cache_ptr->index_size;
+ }
+ space_needed =
+ (size_t)(((double)space_needed) *
+ (cache_ptr->resize_ctl).flash_multiple);
+
+ new_max_cache_size = cache_ptr->max_cache_size + space_needed;
+
+ break;
+
+ default: /* should be unreachable */
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "Unknown flash_incr_mode?!?!?.")
+ break;
+ }
+
+ if ( new_max_cache_size > (cache_ptr->resize_ctl).max_size ) {
+
+ new_max_cache_size = (cache_ptr->resize_ctl).max_size;
+ }
+
+ HDassert( new_max_cache_size > cache_ptr->max_cache_size );
+
+ new_min_clean_size = (size_t)
+ ((double)new_max_cache_size *
+ ((cache_ptr->resize_ctl).min_clean_fraction));
+
+ HDassert( new_min_clean_size <= new_max_cache_size );
+
+ old_max_cache_size = cache_ptr->max_cache_size;
+ old_min_clean_size = cache_ptr->min_clean_size;
+
+ cache_ptr->max_cache_size = new_max_cache_size;
+ cache_ptr->min_clean_size = new_min_clean_size;
+
+ /* update flash cache size increase fields as appropriate */
+ HDassert ( cache_ptr->flash_size_increase_possible );
+
+ switch ( (cache_ptr->resize_ctl).flash_incr_mode )
+ {
+ case H5C_flash_incr__off:
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "flash_size_increase_possible but H5C_flash_incr__off?!")
+ break;
+
+ case H5C_flash_incr__add_space:
+ cache_ptr->flash_size_increase_threshold =
+ (size_t)
+ (((double)(cache_ptr->max_cache_size)) *
+ ((cache_ptr->resize_ctl).flash_threshold));
+ break;
+
+ default: /* should be unreachable */
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "Unknown flash_incr_mode?!?!?.")
+ break;
+ }
+
+ /* note that we don't cycle the epoch markers. We can
+ * argue either way as to whether we should, but for now
+ * we don't.
+ */
+
+ if ( (cache_ptr->resize_ctl).rpt_fcn != NULL ) {
+
+ /* get the hit rate for the reporting function. Should still
+ * be good as we havent reset the hit rate statistics.
+ */
+ if ( H5C_get_cache_hit_rate(cache_ptr, &hit_rate) != SUCCEED ) {
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Can't get hit rate.")
+ }
+
+ (*((cache_ptr->resize_ctl).rpt_fcn))
+ (cache_ptr,
+ H5C__CURR_AUTO_RESIZE_RPT_FCN_VER,
+ hit_rate,
+ status,
+ old_max_cache_size,
+ new_max_cache_size,
+ old_min_clean_size,
+ new_min_clean_size);
+ }
+
+ if ( H5C_reset_cache_hit_rate_stats(cache_ptr) != SUCCEED ) {
+
+ /* this should be impossible... */
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "H5C_reset_cache_hit_rate_stats failed.")
+ }
+ }
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* H5C__flash_increase_cache_size() */
+
/*-------------------------------------------------------------------------
* Function: H5C_flush_invalidate_cache
@@ -8779,12 +9442,28 @@ done:
*
* Modifications:
*
- * To support the fractal heap, the cache must now deal with
- * entries being dirtied, resized, and/or renamed inside
- * flush callbacks. Updated function to support this.
+ * To support the fractal heap, the cache must now deal with
+ * entries being dirtied, resized, and/or renamed inside
+ * flush callbacks. Updated function to support this.
*
* -- JRM 8/27/06
*
+ * Added code to detect and manage the case in which a
+ * flush callback changes the s-list out from under
+ * the function. The only way I can think of in which this
+ * can happen is if a flush function loads an entry
+ * into the cache that isn't there already. Quincey tells
+ * me that this will never happen, but I'm not sure I
+ * believe him.
+ *
+ * Note that this is a pretty bad scenario if it ever
+ * happens. The code I have added should allow us to
+ * handle the situation under all but the worst conditions,
+ * but one can argue that I should just scream and die if I
+ * ever detect the condidtion.
+ *
+ * -- JRM 10/13/07
+ *
*-------------------------------------------------------------------------
*/
herr_t
@@ -8842,29 +9521,29 @@ H5C_flush_invalidate_cache(H5F_t * f,
/* The flush proceedure here is a bit strange.
*
- * In the outer while loop we make at least one pass through the
+ * In the outer while loop we make at least one pass through the
* cache, and then repeat until either all the pinned entries
* unpin themselves, or until the number of pinned entries stops
* declining. In this later case, we scream and die.
*
* Since the fractal heap can dirty, resize, and/or rename entries
* in is flush callback, it is possible that the cache will still
- * contain dirty entries at this point. If so, we must make up to
- * H5C__MAX_PASSES_ON_FLUSH more passes through the skip list
+ * contain dirty entries at this point. If so, we must make up to
+ * H5C__MAX_PASSES_ON_FLUSH more passes through the skip list
* to allow it to empty. If is is not empty at this point, we again
* scream and die.
*
- * Further, since clean entries can be dirtied, resized, and/or renamed
+ * Further, since clean entries can be dirtied, resized, and/or renamed
* as the result of a flush call back (either the entries own, or that
- * for some other cache entry), we can no longer promise to flush
+ * for some other cache entry), we can no longer promise to flush
* the cache entries in increasing address order.
*
* Instead, we just do the best we can -- making a pass through
- * the skip list, and then a pass through the "clean" entries, and
- * then repeating as needed. Thus it is quite possible that an
+ * the skip list, and then a pass through the "clean" entries, and
+ * then repeating as needed. Thus it is quite possible that an
* entry will be evicted from the cache only to be re-loaded later
- * in the flush process (From what Quincey tells me, the pin
- * mechanism makes this impossible, but even it it is true now,
+ * in the flush process (From what Quincey tells me, the pin
+ * mechanism makes this impossible, but even it it is true now,
* we shouldn't count on it in the future.)
*
* The bottom line is that entries will probably be flushed in close
@@ -8881,10 +9560,10 @@ H5C_flush_invalidate_cache(H5F_t * f,
have_pinned_entries = ( cur_pel_len > 0 );
/* first, try to flush-destroy any dirty entries. Do this by
- * making a scan through the slist. Note that new dirty entries
+ * making a scan through the slist. Note that new dirty entries
* may be created by the flush call backs. Thus it is possible
* that the slist will not be empty after we finish the scan.
- */
+ */
if ( cache_ptr->slist_len == 0 ) {
@@ -8895,6 +9574,23 @@ H5C_flush_invalidate_cache(H5F_t * f,
node_ptr = H5SL_first(cache_ptr->slist_ptr);
+ if ( node_ptr == NULL ) {
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "slist_len != 0 && node_ptr == NULL");
+ }
+
+ next_entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
+
+ if ( next_entry_ptr == NULL ) {
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "next_entry_ptr == NULL 1 ?!?!");
+ }
+#ifndef NDEBUG
+ HDassert( next_entry_ptr->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC );
+#endif /* NDEBUG */
+ HDassert( next_entry_ptr->is_dirty );
+ HDassert( next_entry_ptr->in_slist );
+
}
#if H5C_DO_SANITY_CHECKS
/* Depending on circumstances, H5C_flush_single_entry() will
@@ -8927,23 +9623,88 @@ H5C_flush_invalidate_cache(H5F_t * f,
while ( node_ptr != NULL )
{
- /* Note that we now remove nodes from the slist as we flush
- * the associated entries, instead of leaving them there
- * until we are done, and then destroying all nodes in
- * the slist.
+ entry_ptr = next_entry_ptr;
+
+ /* With the advent of the fractal heap, it is possible
+ * that the flush callback will dirty and/or resize
+ * other entries in the cache. In particular, while
+ * Quincey has promised me that this will never happen,
+ * it is possible that the flush callback for an
+ * entry may protect an entry that is not in the cache,
+ * perhaps causing the cache to flush and possibly
+ * evict the entry associated with node_ptr to make
+ * space for the new entry.
*
- * While this optimization used to be easy, with the possibility
- * of new entries being added to the slist in the midst of the
- * flush, we must keep the slist in cannonical form at all
- * times.
+ * Thus we do a bit of extra sanity checking on entry_ptr,
+ * and break out of this scan of the skip list if we
+ * detect major problems. We have a bit of leaway on the
+ * number of passes though the skip list, so this shouldn't
+ * be an issue in the flush in and of itself, as it should
+ * be all but impossible for this to happen more than once
+ * in any flush.
+ *
+ * Observe that that breaking out of the scan early
+ * shouldn't break the sanity checks just after the end
+ * of this while loop.
+ *
+ * If an entry has merely been marked clean and removed from
+ * the s-list, we simply break out of the scan.
+ *
+ * If the entry has been evicted, we flag an error and
+ * exit.
*/
+#ifndef NDEBUG
+ if ( entry_ptr->magic != H5C__H5C_CACHE_ENTRY_T_MAGIC ) {
- entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "entry_ptr->magic is invalid ?!?!");
+
+ } else
+#endif /* NDEBUG */
+ if ( ( ! entry_ptr->is_dirty ) ||
+ ( ! entry_ptr->in_slist ) ) {
+
+ /* the s-list has been modified out from under us.
+ * break out of the loop.
+ */
+ break;
+ }
/* increment node pointer now, before we delete its target
* from the slist.
*/
+
node_ptr = H5SL_next(node_ptr);
+ if ( node_ptr != NULL ) {
+
+ next_entry_ptr = (H5C_cache_entry_t *)H5SL_item(node_ptr);
+
+ if ( next_entry_ptr == NULL ) {
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "next_entry_ptr == NULL 2 ?!?!");
+ }
+#ifndef NDEBUG
+ HDassert( next_entry_ptr->magic ==
+ H5C__H5C_CACHE_ENTRY_T_MAGIC );
+#endif /* NDEBUG */
+ HDassert( next_entry_ptr->is_dirty );
+ HDassert( next_entry_ptr->in_slist );
+
+ } else {
+
+ next_entry_ptr = NULL;
+ }
+
+ /* Note that we now remove nodes from the slist as we flush
+ * the associated entries, instead of leaving them there
+ * until we are done, and then destroying all nodes in
+ * the slist.
+ *
+ * While this optimization used to be easy, with the possibility
+ * of new entries being added to the slist in the midst of the
+ * flush, we must keep the slist in cannonical form at all
+ * times.
+ */
HDassert( entry_ptr != NULL );
HDassert( entry_ptr->in_slist );
@@ -8957,7 +9718,7 @@ H5C_flush_invalidate_cache(H5F_t * f,
* cache_ptr->slist_size_increase.
*
* Note that we include pinned entries in this count, even
- * though we will not actually flush them.
+ * though we will not actually flush them.
*/
actual_slist_len++;
actual_slist_size += entry_ptr->size;
@@ -8978,7 +9739,7 @@ H5C_flush_invalidate_cache(H5F_t * f,
* as pinned entries can't be evicted.
*/
if ( TRUE ) { /* When we get to multithreaded cache,
- * we will need either locking code, and/or
+ * we will need either locking code, and/or
* a test to see if the entry is in flushable
* condition here.
*/
@@ -9030,19 +9791,26 @@ H5C_flush_invalidate_cache(H5F_t * f,
/* It is possible that entries were added to the slist during
* the scan, either before or after scan pointer. The following
* asserts take this into account.
- */
+ *
+ * Don't bother with the sanity checks if node_ptr != NULL, as
+ * in this case we broke out of the loop because it got changed
+ * out from under us.
+ */
+
+ if ( node_ptr == NULL ) {
- HDassert( (actual_slist_len + cache_ptr->slist_len) ==
- (initial_slist_len + cache_ptr->slist_len_increase) );
- HDassert( (actual_slist_size + cache_ptr->slist_size) ==
- (initial_slist_size + cache_ptr->slist_size_increase) );
+ HDassert( (actual_slist_len + cache_ptr->slist_len) ==
+ (initial_slist_len + cache_ptr->slist_len_increase) );
+ HDassert( (actual_slist_size + cache_ptr->slist_size) ==
+ (initial_slist_size + cache_ptr->slist_size_increase) );
+ }
#endif /* H5C_DO_SANITY_CHECKS */
/* Since we are doing a destroy, we must make a pass through
* the hash table and try to flush - destroy all entries that
- * remain.
+ * remain.
*
- * It used to be that all entries remaining in the cache at
+ * It used to be that all entries remaining in the cache at
* this point had to be clean, but with the fractal heap mods
* this may not be the case. If so, we will flush entries out
* of increasing address order.
@@ -9056,8 +9824,13 @@ H5C_flush_invalidate_cache(H5F_t * f,
while ( next_entry_ptr != NULL )
{
entry_ptr = next_entry_ptr;
- next_entry_ptr = entry_ptr->ht_next;
+ next_entry_ptr = entry_ptr->ht_next;
+#ifndef NDEBUG
+ HDassert ( ( next_entry_ptr == NULL ) ||
+ ( next_entry_ptr->magic ==
+ H5C__H5C_CACHE_ENTRY_T_MAGIC ) );
+#endif /* NDEBUG */
if ( entry_ptr->is_protected ) {
/* we have major problems -- but lets flush and destroy
@@ -9099,6 +9872,28 @@ H5C_flush_invalidate_cache(H5F_t * f,
* of pinned entries from pass to pass. If it stops
* shrinking before it hits zero, we scream and die.
*/
+ /* if the flush function on the entry we last evicted
+ * loaded an entry into cache (as Quincey has promised me
+ * it never will), and if the cache was full, it is
+ * possible that *next_entry_ptr was flushed or evicted.
+ *
+ * Test to see if this happened here. Note that if this
+ * test is triggred, we are accessing a deallocated piece
+ * of dynamically allocated memory, so we just scream and
+ * die.
+ */
+#ifndef NDEBUG
+ if ( ( next_entry_ptr != NULL ) &&
+ ( next_entry_ptr->magic !=
+ H5C__H5C_CACHE_ENTRY_T_MAGIC ) ) {
+
+ /* Something horrible has happened to
+ * *next_entry_ptr -- scream and die.
+ */
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "next_entry_ptr->magic is invalid?!?!?.")
+ }
+#endif /* NDEBUG */
} /* end while loop scanning hash table bin */
} /* end for loop scanning hash table */
@@ -9117,7 +9912,7 @@ H5C_flush_invalidate_cache(H5F_t * f,
} else if ( ( cur_pel_len == 0 ) && ( old_pel_len == 0 ) ) {
/* increment the pass count */
- passes++;
+ passes++;
}
if ( passes >= H5C__MAX_PASSES_ON_FLUSH ) {
@@ -9239,21 +10034,25 @@ done:
* as there is no write to file in this case.
*
* JRM -- 8/21/06
- * Added code maintaining the flush_in_progress and
- * destroy_in_progress fields in H5C_cache_entry_t.
- *
- * Also added flush_flags parameter to the call to
- * type_ptr->flush() so that the flush routine can report
- * whether the entry has been resized or renamed. Added
- * code using the flush_flags variable to detect the case
- * in which the target entry is resized during flush, and
+ * Added code maintaining the flush_in_progress and
+ * destroy_in_progress fields in H5C_cache_entry_t.
+ *
+ * Also added flush_flags parameter to the call to
+ * type_ptr->flush() so that the flush routine can report
+ * whether the entry has been resized or renamed. Added
+ * code using the flush_flags variable to detect the case
+ * in which the target entry is resized during flush, and
* update the caches data structures accordingly.
*
- *
* JRM -- 3/29/07
- * Added sanity checks on the new is_read_only and
+ * Added sanity checks on the new is_read_only and
* ro_ref_count fields.
*
+ * QAK -- 2/07/08
+ * Separated "destroy entry" concept from "remove entry from
+ * cache" concept, by adding the 'take_ownership' flag and
+ * the "destroy_entry" variable.
+ *
*-------------------------------------------------------------------------
*/
static herr_t
@@ -9269,12 +10068,14 @@ H5C_flush_single_entry(H5F_t * f,
{
hbool_t destroy;
hbool_t clear_only;
+ hbool_t take_ownership;
hbool_t was_dirty;
- herr_t ret_value = SUCCEED; /* Return value */
+ hbool_t destroy_entry;
herr_t status;
int type_id;
unsigned flush_flags = H5C_CALLBACK__NO_FLAGS_SET;
H5C_cache_entry_t * entry_ptr = NULL;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5C_flush_single_entry)
@@ -9287,6 +10088,15 @@ H5C_flush_single_entry(H5F_t * f,
destroy = ( (flags & H5C__FLUSH_INVALIDATE_FLAG) != 0 );
clear_only = ( (flags & H5C__FLUSH_CLEAR_ONLY_FLAG) != 0);
+ take_ownership = ( (flags & H5C__TAKE_OWNERSHIP_FLAG) != 0);
+
+ /* Set the flag for destroying the entry, based on the 'take ownership'
+ * and 'destroy' flags
+ */
+ if(take_ownership)
+ destroy_entry = FALSE;
+ else
+ destroy_entry = destroy;
/* attempt to find the target entry in the hash table */
H5C__SEARCH_INDEX(cache_ptr, addr, entry_ptr, FAIL)
@@ -9412,8 +10222,8 @@ H5C_flush_single_entry(H5F_t * f,
* entry if destroy is true.
*
* Note that it is possible that the entry will be renamed during
- * its call to flush. This will upset H5C_rename_entry() if we
- * don't tell it that it doesn't have to worry about updating the
+ * its call to flush. This will upset H5C_rename_entry() if we
+ * don't tell it that it doesn't have to worry about updating the
* index and SLIST. Use the destroy_in_progress field for this
* purpose.
*/
@@ -9541,8 +10351,19 @@ H5C_flush_single_entry(H5F_t * f,
/* Clear the dirty flag only, if requested */
if ( clear_only ) {
+#ifndef NDEBUG
+ if ( destroy ) {
+ /* we are about to call the clear callback with the
+ * destroy flag set -- this will result in *entry_ptr
+ * being freed. Set the magic field to bad magic
+ * so we can detect a freed cache entry if we see
+ * one.
+ */
+ entry_ptr->magic = H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC;
+ }
+#endif /* NDEBUG */
/* Call the callback routine to clear all dirty flags for object */
- if ( (entry_ptr->type->clear)(f, entry_ptr, destroy) < 0 ) {
+ if ( (entry_ptr->type->clear)(f, entry_ptr, destroy_entry) < 0 ) {
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "can't clear entry")
}
@@ -9558,12 +10379,24 @@ H5C_flush_single_entry(H5F_t * f,
}
#endif /* H5C_DO_SANITY_CHECKS */
+#ifndef NDEBUG
+ if ( destroy ) {
+ /* we are about to call the flush callback with the
+ * destroy flag set -- this will result in *entry_ptr
+ * being freed. Set the magic field to bad magic
+ * so we can detect a freed cache entry if we see
+ * one.
+ */
+ entry_ptr->magic = H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC;
+ }
+#endif /* NDEBUG */
+
/* Only block for all the processes on the first piece of metadata
*/
if ( *first_flush_ptr && entry_ptr->is_dirty ) {
- status = (entry_ptr->type->flush)(f, primary_dxpl_id, destroy,
+ status = (entry_ptr->type->flush)(f, primary_dxpl_id, destroy_entry,
entry_ptr->addr, entry_ptr,
&flush_flags);
*first_flush_ptr = FALSE;
@@ -9571,7 +10404,7 @@ H5C_flush_single_entry(H5F_t * f,
} else {
status = (entry_ptr->type->flush)(f, secondary_dxpl_id,
- destroy, entry_ptr->addr,
+ destroy_entry, entry_ptr->addr,
entry_ptr, &flush_flags);
}
@@ -9588,21 +10421,21 @@ H5C_flush_single_entry(H5F_t * f,
* die.
*
* At present, in the parallel case, the aux_ptr
- * will only be set if there is more than one
- * process. Thus we can use this to detect
+ * will only be set if there is more than one
+ * process. Thus we can use this to detect
* the parallel case.
*
- * This works for now, but if we start using the
- * aux_ptr for other purposes, we will have to
+ * This works for now, but if we start using the
+ * aux_ptr for other purposes, we will have to
* change this test accordingly.
*
* NB: While this test detects entryies that attempt
* to resize or rename themselves during a flush
* in the parallel case, it will not detect an
- * entry that dirties, resizes, and/or renames
+ * entry that dirties, resizes, and/or renames
* other entries during its flush.
*
- * From what Quincey tells me, this test is
+ * From what Quincey tells me, this test is
* sufficient for now, as any flush routine that
* does the latter will also do the former.
*
@@ -9637,7 +10470,7 @@ H5C_flush_single_entry(H5F_t * f,
/* The entry size changed as a result of the flush.
*
- * Most likely, the entry was compressed, and the
+ * Most likely, the entry was compressed, and the
* new version is of a different size than the old.
*
* In any case, we must update entry and cache size
@@ -9645,7 +10478,7 @@ H5C_flush_single_entry(H5F_t * f,
*/
size_t new_size;
- if ( (entry_ptr->type->size)(f, (void *)entry_ptr, &new_size)
+ if ( (entry_ptr->type->size)(f, (void *)entry_ptr, &new_size)
< 0 ) {
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGETSIZE, FAIL, \
@@ -9662,14 +10495,14 @@ H5C_flush_single_entry(H5F_t * f,
(new_size));
/* The entry can't be protected since we just flushed it.
- * Thus we must update the replacement policy data
- * structures for the size change. The macro deals
+ * Thus we must update the replacement policy data
+ * structures for the size change. The macro deals
* with the pinned case.
*/
H5C__UPDATE_RP_FOR_SIZE_CHANGE(cache_ptr, entry_ptr, \
new_size)
- /* The entry can't be in the slist, so no need to update
+ /* The entry can't be in the slist, so no need to update
* the slist for the size change.
*/
@@ -9687,12 +10520,12 @@ H5C_flush_single_entry(H5F_t * f,
/* The entry was renamed as the result of the flush.
*
- * Most likely, the entry was compressed, and the
- * new version is larger than the old and thus had
+ * Most likely, the entry was compressed, and the
+ * new version is larger than the old and thus had
* to be relocated.
*
- * At preset, all processing for this case is
- * handled elsewhere. But lets keep the if statement
+ * At preset, all processing for this case is
+ * handled elsewhere. But lets keep the if statement
* around just in case.
*/
@@ -9744,7 +10577,7 @@ done:
*
* JRM - 6/23/06
* Deleted assertion that verified that a newly loaded
- * entry is clean. Due to a bug fix, this need not be
+ * entry is clean. Due to a bug fix, this need not be
* the case, as our code will attempt to repair errors
* on load.
*
@@ -9753,9 +10586,13 @@ done:
* destroy in progress fields.
*
* JRM - 3/29/07
- * Added initialization for the new is_read_only and
+ * Added initialization for the new is_read_only and
* ro_ref_count fields.
*
+ * QAK -- 1/31/08
+ * Added initialization for the new free_file_space_on_destroy
+ * field.
+ *
*-------------------------------------------------------------------------
*/
@@ -9793,10 +10630,10 @@ H5C_load_entry(H5F_t * f,
entry_ptr = (H5C_cache_entry_t *)thing;
/* In general, an entry should be clean just after it is loaded.
- *
+ *
* However, when this code is used in the metadata cache, it is
- * possible that object headers will be dirty at this point, as
- * the load function will alter object headers if necessary to
+ * possible that object headers will be dirty at this point, as
+ * the load function will alter object headers if necessary to
* fix an old bug.
*
* To support this bug fix, I have replace the old assert:
@@ -9810,13 +10647,15 @@ H5C_load_entry(H5F_t * f,
* Note that type id 4 is associated with object headers in the metadata
* cache.
*
- * When we get to using H5C for other purposes, we may wish to
+ * When we get to using H5C for other purposes, we may wish to
* tighten up the assert so that the loophole only applies to the
* metadata cache.
*/
HDassert( ( entry_ptr->is_dirty == FALSE ) || ( type->id == 4 ) );
-
+#ifndef NDEBUG
+ entry_ptr->magic = H5C__H5C_CACHE_ENTRY_T_MAGIC;
+#endif /* NDEBUG */
entry_ptr->addr = addr;
entry_ptr->type = type;
entry_ptr->is_protected = FALSE;
@@ -9829,6 +10668,7 @@ H5C_load_entry(H5F_t * f,
#endif /* H5_HAVE_PARALLEL */
entry_ptr->flush_in_progress = FALSE;
entry_ptr->destroy_in_progress = FALSE;
+ entry_ptr->free_file_space_on_destroy = FALSE;
if ( (type->size)(f, thing, &(entry_ptr->size)) < 0 ) {
@@ -9911,9 +10751,24 @@ done:
* min clean size before the cache has filled.
*
* JRM -- 3/29/07
- * Added sanity checks using the new is_read_only and
+ * Added sanity checks using the new is_read_only and
* ro_ref_count fields.
*
+ * JRM -- 10/13/07
+ * Added code to detect and manage the case in which a
+ * flush callback changes the LRU-list out from under
+ * the function. The only way I can think of in which this
+ * can happen is if a flush function loads an entry
+ * into the cache that isn't there already. Quincey tells
+ * me that this will never happen, but I'm not sure I
+ * believe him.
+ *
+ * Note that this is a pretty bad scenario if it ever
+ * happens. The code I have added should allow us to
+ * handle the situation under all but the worst conditions,
+ * but one can argue that I should just scream and die if I
+ * ever detect the condidtion.
+ *
*-------------------------------------------------------------------------
*/
@@ -9933,7 +10788,10 @@ H5C_make_space_in_cache(H5F_t * f,
#if H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS
size_t empty_space;
#endif /* H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */
+ hbool_t prev_is_dirty = FALSE;
+ hbool_t entry_is_epoch_maker = FALSE;
H5C_cache_entry_t * entry_ptr;
+ H5C_cache_entry_t * next_ptr;
H5C_cache_entry_t * prev_ptr;
FUNC_ENTER_NOAPI_NOINIT(H5C_make_space_in_cache)
@@ -9962,10 +10820,18 @@ H5C_make_space_in_cache(H5F_t * f,
HDassert( ! (entry_ptr->is_read_only) );
HDassert( (entry_ptr->ro_ref_count) == 0 );
- prev_ptr = entry_ptr->prev;
+ next_ptr = entry_ptr->next;
+ prev_ptr = entry_ptr->prev;
+
+ if ( prev_ptr != NULL ) {
+
+ prev_is_dirty = prev_ptr->is_dirty;
+ }
if ( (entry_ptr->type)->id != H5C__EPOCH_MARKER_TYPE ) {
+ entry_is_epoch_maker = FALSE;
+
if ( entry_ptr->is_dirty ) {
result = H5C_flush_single_entry(f,
@@ -9994,6 +10860,7 @@ H5C_make_space_in_cache(H5F_t * f,
/* Skip epoch markers. Set result to SUCCEED to avoid
* triggering the error code below.
*/
+ entry_is_epoch_maker = TRUE;
result = SUCCEED;
}
@@ -10003,11 +10870,54 @@ H5C_make_space_in_cache(H5F_t * f,
"unable to flush entry")
}
- entry_ptr = prev_ptr;
- }
+ if ( prev_ptr != NULL ) {
+#ifndef NDEBUG
+ if ( prev_ptr->magic != H5C__H5C_CACHE_ENTRY_T_MAGIC ) {
+
+ /* something horrible has happened to *prev_ptr --
+ * scream and die.
+ */
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "*prev_ptr corrupt 1")
+
+ }
+#endif /* NDEBUG */
+ if ( entry_is_epoch_maker ) {
+
+ entry_ptr = prev_ptr;
+
+ } else if ( ( prev_ptr->is_dirty != prev_is_dirty )
+ ||
+ ( prev_ptr->next != next_ptr )
+ ||
+ ( prev_ptr->is_protected )
+ ||
+ ( prev_ptr->is_pinned ) ) {
+
+ /* something has happened to the LRU -- start over
+ * from the tail.
+ */
+
+ entry_ptr = cache_ptr->LRU_tail_ptr;
+
+ } else {
+
+ entry_ptr = prev_ptr;
+
+ }
+ } else {
+
+ entry_ptr = NULL;
+
+ }
+
+ entries_examined++;
+
+ }
#if H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS
+ entries_examined = 0;
initial_list_len = cache_ptr->dLRU_list_len;
entry_ptr = cache_ptr->dLRU_tail_ptr;
@@ -10034,6 +10944,13 @@ H5C_make_space_in_cache(H5F_t * f,
prev_ptr = entry_ptr->aux_prev;
+ next_ptr = entry_ptr->aux_next;
+
+ if ( prev_ptr != NULL ) {
+
+ HDassert( prev_ptr->is_dirty );
+ }
+
result = H5C_flush_single_entry(f,
primary_dxpl_id,
secondary_dxpl_id,
@@ -10050,7 +10967,66 @@ H5C_make_space_in_cache(H5F_t * f,
"unable to flush entry")
}
- entry_ptr = prev_ptr;
+ if ( prev_ptr != NULL ) {
+#ifndef NDEBUG
+ if (prev_ptr->magic != H5C__H5C_CACHE_ENTRY_T_MAGIC) {
+
+ /* something horrible has happened to *prev_ptr --
+ * scream and die.
+ */
+
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \
+ "*prev_ptr corrupt 2")
+
+ } else
+#endif /* #ifndef NDEBUG */
+ if ( ( ! ( prev_ptr->is_dirty ) )
+ ||
+ ( prev_ptr->aux_next != next_ptr )
+ ||
+ ( prev_ptr->is_protected )
+ ||
+ ( prev_ptr->is_pinned ) ) {
+
+ /* something has happened to the dirty LRU -- start over
+ * from the tail.
+ */
+
+#if 0 /* This debuging code may be useful in the future -- keep it for now. */
+ if ( ! ( prev_ptr->is_dirty ) ) {
+ HDfprintf(stdout, "%s: ! prev_ptr->is_dirty\n",
+ fcn_name);
+ }
+ if ( prev_ptr->aux_next != next_ptr ) {
+ HDfprintf(stdout, "%s: prev_ptr->next != next_ptr\n",
+ fcn_name);
+ }
+ if ( prev_ptr->is_protected ) {
+ HDfprintf(stdout, "%s: prev_ptr->is_protected\n",
+ fcn_name);
+ }
+ if ( prev_ptr->is_pinned ) {
+ HDfprintf(stdout, "%s:prev_ptr->is_pinned\n",
+ fcn_name);
+ }
+
+ HDfprintf(stdout, "%s: re-starting scan of dirty list\n",
+ fcn_name);
+#endif /* JRM */
+ entry_ptr = cache_ptr->dLRU_tail_ptr;
+
+ } else {
+
+ entry_ptr = prev_ptr;
+
+ }
+ } else {
+
+ entry_ptr = NULL;
+
+ }
+
+ entries_examined++;
}
#endif /* H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */
@@ -10096,6 +11072,7 @@ H5C_make_space_in_cache(H5F_t * f,
}
entry_ptr = prev_ptr;
+ entries_examined++;
}
}
diff --git a/src/H5CS.c b/src/H5CS.c
index 6e485cc..dd80671 100644
--- a/src/H5CS.c
+++ b/src/H5CS.c
@@ -135,7 +135,7 @@ H5CS_print_stack(const H5CS_t *fstack, FILE *stream)
HDfprintf (stream, "HDF5-DIAG: Function stack from %s ", H5_lib_vers_info_g);
/* try show the process or thread id in multiple processes cases*/
#ifdef H5_HAVE_THREADSAFE
- HDfprintf (stream, "thread %d.", (int)pthread_self());
+ HDfprintf (stream, "thread %lu.", HDpthread_self_ulong());
#else /* H5_HAVE_THREADSAFE */
HDfprintf (stream, "thread 0.");
#endif /* H5_HAVE_THREADSAFE */
diff --git a/src/H5Cpkg.h b/src/H5Cpkg.h
index 949f923..bdbb25e 100644
--- a/src/H5Cpkg.h
+++ b/src/H5Cpkg.h
@@ -43,12 +43,12 @@
/* Get needed headers */
#include "H5SLprivate.h" /* Skip lists */
-/* With the introduction of the fractal heap, it is now possible for
+/* With the introduction of the fractal heap, it is now possible for
* entries to be dirtied, resized, and/or renamed in the flush callbacks.
* As a result, on flushes, it may be necessary to make multiple passes
* through the slist before it is empty. The H5C__MAX_PASSES_ON_FLUSH
* #define is used to set an upper limit on the number of passes.
- * The current value was obtained via personal communication with
+ * The current value was obtained via personal communication with
* Quincey. I have applied a fudge factor of 2.
*/
@@ -99,7 +99,7 @@
* magic: Unsigned 32 bit integer always set to H5C__H5C_T_MAGIC. This
* field is used to validate pointers to instances of H5C_t.
*
- * flush_in_progress: Boolean flag indicating whether a flush is in
+ * flush_in_progress: Boolean flag indicating whether a flush is in
* progress.
*
* trace_file_ptr: File pointer pointing to the trace file, which is used
@@ -108,7 +108,7 @@
* no trace file should be recorded.
*
* Since much of the code supporting the parallel metadata
- * cache is in H5AC, we don't write the trace file from
+ * cache is in H5AC, we don't write the trace file from
* H5C. Instead, H5AC reads the trace_file_ptr as needed.
*
* When we get to using H5C in other places, we may add
@@ -181,10 +181,10 @@
* writes. The following field is used to implement this.
*
* evictions_enabled: Boolean flag that is initialized to TRUE. When
- * this flag is set to FALSE, the metadata cache will not
+ * this flag is set to FALSE, the metadata cache will not
* attempt to evict entries to make space for newly protected
* entries, and instead the will grow without limit.
- *
+ *
* Needless to say, this feature must be used with care.
*
*
@@ -255,7 +255,7 @@
* following two fields have been added. They are only compiled in when
* H5C_DO_SANITY_CHECKS is TRUE.
*
- * slist_len_increase: Number of entries that have been added to the
+ * slist_len_increase: Number of entries that have been added to the
* slist since the last time this field was set to zero.
*
* slist_size_increase: Total size of all entries that have been added
@@ -465,6 +465,18 @@
* all the ways this can happen, we simply set this flag when
* we receive a new configuration.
*
+ * flash_size_increase_possible: Depending on the configuration data given
+ * in the resize_ctl field, it may or may not be possible
+ * for a flash size increase to occur. We set this flag
+ * whenever we receive a new configuration so as to avoid
+ * repeated calculations.
+ *
+ * flash_size_increase_threshold: If a flash cache size increase is possible,
+ * this field is used to store the minimum size of a new entry
+ * or size increase needed to trigger a flash cache size
+ * increase. Note that this field must be updated whenever
+ * the size of the cache is changed.
+ *
* size_decrease_possible: Depending on the configuration data given
* in the resize_ctl field, it may or may not be possible
* to decrease the size of the cache. Rather than test for
@@ -580,10 +592,10 @@
* equal to the array index has not been in cache when
* requested in the current epoch.
*
- * write_protects: Array of int64 of length H5C__MAX_NUM_TYPE_IDS + 1. The cells
- * are used to record the number of times an entry with type id
- * equal to the array index has been write protected in the
- * current epoch.
+ * write_protects: Array of int64 of length H5C__MAX_NUM_TYPE_IDS + 1. The
+ * cells are used to record the number of times an entry with
+ * type id equal to the array index has been write protected
+ * in the current epoch.
*
* Observe that (hits + misses) = (write_protects + read_protects).
*
@@ -594,9 +606,9 @@
*
* Observe that (hits + misses) = (write_protects + read_protects).
*
- * max_read_protects: Array of int32 of length H5C__MAX_NUM_TYPE_IDS + 1.
- * The cells are used to maximum number of simultaneous read
- * protects on any entry with type id equal to the array index
+ * max_read_protects: Array of int32 of length H5C__MAX_NUM_TYPE_IDS + 1.
+ * The cells are used to maximum number of simultaneous read
+ * protects on any entry with type id equal to the array index
* in the current epoch.
*
* insertions: Array of int64 of length H5C__MAX_NUM_TYPE_IDS + 1. The cells
@@ -604,9 +616,9 @@
* id equal to the array index has been inserted into the
* cache in the current epoch.
*
- * pinned_insertions: Array of int64 of length H5C__MAX_NUM_TYPE_IDS + 1.
- * The cells are used to record the number of times an entry
- * with type id equal to the array index has been inserted
+ * pinned_insertions: Array of int64 of length H5C__MAX_NUM_TYPE_IDS + 1.
+ * The cells are used to record the number of times an entry
+ * with type id equal to the array index has been inserted
* pinned into the cache in the current epoch.
*
* clears: Array of int64 of length H5C__MAX_NUM_TYPE_IDS + 1. The cells
@@ -629,13 +641,13 @@
* id equal to the array index has been renamed in the current
* epoch.
*
- * entry_flush_renames: Array of int64 of length H5C__MAX_NUM_TYPE_IDS + 1.
- * The cells are used to record the number of times an entry
+ * entry_flush_renames: Array of int64 of length H5C__MAX_NUM_TYPE_IDS + 1.
+ * The cells are used to record the number of times an entry
* with type id equal to the array index has been renamed
* during its flush callback in the current epoch.
*
- * cache_flush_renames: Array of int64 of length H5C__MAX_NUM_TYPE_IDS + 1.
- * The cells are used to record the number of times an entry
+ * cache_flush_renames: Array of int64 of length H5C__MAX_NUM_TYPE_IDS + 1.
+ * The cells are used to record the number of times an entry
* with type id equal to the array index has been renamed
* during a cache flush in the current epoch.
*
@@ -674,14 +686,14 @@
* with type id equal to the array index has decreased in
* size in the current epoch.
*
- * entry_flush_size_changes: Array of int64 of length
- * H5C__MAX_NUM_TYPE_IDS + 1. The cells are used to record
- * the number of times an entry with type id equal to the
+ * entry_flush_size_changes: Array of int64 of length
+ * H5C__MAX_NUM_TYPE_IDS + 1. The cells are used to record
+ * the number of times an entry with type id equal to the
* array index has changed size while in its flush callback.
*
- * cache_flush_size_changes: Array of int64 of length
- * H5C__MAX_NUM_TYPE_IDS + 1. The cells are used to record
- * the number of times an entry with type id equal to the
+ * cache_flush_size_changes: Array of int64 of length
+ * H5C__MAX_NUM_TYPE_IDS + 1. The cells are used to record
+ * the number of times an entry with type id equal to the
* array index has changed size during a cache flush
*
* total_ht_insertions: Number of times entries have been inserted into the
@@ -790,7 +802,7 @@
****************************************************************************/
#define H5C__H5C_T_MAGIC 0x005CAC0E
-#define H5C__MAX_NUM_TYPE_IDS 16
+#define H5C__MAX_NUM_TYPE_IDS 21
#define H5C__PREFIX_LEN 32
struct H5C_t
@@ -855,6 +867,8 @@ struct H5C_t
H5C_cache_entry_t * dLRU_tail_ptr;
hbool_t size_increase_possible;
+ hbool_t flash_size_increase_possible;
+ size_t flash_size_increase_threshold;
hbool_t size_decrease_possible;
hbool_t resize_enabled;
hbool_t cache_full;
diff --git a/src/H5Cprivate.h b/src/H5Cprivate.h
index d365755..4ce321c 100644
--- a/src/H5Cprivate.h
+++ b/src/H5Cprivate.h
@@ -202,6 +202,27 @@ typedef herr_t (*H5C_log_flush_func_t)(H5C_t * cache_ptr,
*
* JRM - 4/26/04
*
+ * magic: Unsigned 32 bit integer that must always be set to
+ * H5C__H5C_CACHE_ENTRY_T_MAGIC when the entry is valid.
+ * The field must be set to H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC
+ * just before the entry is freed.
+ *
+ * This is necessary, as the LRU list can be changed out
+ * from under H5C_make_space_in_cache() by the flush
+ * callback which may change the size of an existing entry,
+ * and/or load a new entry while serializing the target entry.
+ *
+ * This in turn can cause a recursive call to
+ * H5C_make_space_in_cache() which may either flush or evict
+ * the next entry that the first invocation of that function
+ * was about to examine.
+ *
+ * The magic field allows H5C_make_space_in_cache() to
+ * detect this case, and re-start its scan from the bottom
+ * of the LRU when this situation occurs.
+ *
+ * This field is only compiled in debug mode.
+ *
* addr: Base address of the cache entry on disk.
*
* size: Length of the cache entry on disk. Note that unlike normal
@@ -265,20 +286,20 @@ typedef herr_t (*H5C_log_flush_func_t)(H5C_t * cache_ptr,
* Note that protected entries are removed from the LRU lists
* and inserted on the protected list.
*
- * is_read_only: Boolean flag that is only meaningful if is_protected is
- * TRUE. In this circumstance, it indicates whether the
+ * is_read_only: Boolean flag that is only meaningful if is_protected is
+ * TRUE. In this circumstance, it indicates whether the
* entry has been protected read only, or read/write.
*
* If the entry has been protected read only (i.e. is_protected
- * and is_read_only are both TRUE), we allow the entry to be
+ * and is_read_only are both TRUE), we allow the entry to be
* protected more than once.
*
- * In this case, the number of readers is maintained in the
+ * In this case, the number of readers is maintained in the
* ro_ref_count field (see below), and unprotect calls simply
* decrement that field until it drops to zero, at which point
* the entry is actually unprotected.
*
- * ro_ref_count: Integer field used to maintain a count of the number of
+ * ro_ref_count: Integer field used to maintain a count of the number of
* outstanding read only protects on this entry. This field
* must be zero whenever either is_protected or is_read_only
* are TRUE.
@@ -340,9 +361,14 @@ typedef herr_t (*H5C_log_flush_func_t)(H5C_t * cache_ptr,
* is in the process of being flushed. This allows the cache
* to detect when a call is the result of a flush callback.
*
- * destroy_in_progress: Boolean flag that is set to true iff the entry
+ * destroy_in_progress: Boolean flag that is set to true iff the entry
* is in the process of being flushed and destroyed.
*
+ * free_file_space_on_destroy: Boolean flag that is set to true iff the entry
+ * is in the process of being flushed and destroyed and the file
+ * space used by the object should be freed by the cache client's
+ * 'dest' callback routine.
+ *
*
* Fields supporting the hash table:
*
@@ -442,8 +468,16 @@ typedef herr_t (*H5C_log_flush_func_t)(H5C_t * cache_ptr,
*
****************************************************************************/
+#ifndef NDEBUG
+#define H5C__H5C_CACHE_ENTRY_T_MAGIC 0x005CAC0A
+#define H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC 0xDeadBeef
+#endif /* NDEBUG */
+
typedef struct H5C_cache_entry_t
{
+#ifndef NDEBUG
+ uint32_t magic;
+#endif /* NDEBUG */
haddr_t addr;
size_t size;
const H5C_class_t * type;
@@ -460,6 +494,7 @@ typedef struct H5C_cache_entry_t
#endif /* H5_HAVE_PARALLEL */
hbool_t flush_in_progress;
hbool_t destroy_in_progress;
+ hbool_t free_file_space_on_destroy;
/* fields supporting the hash table: */
@@ -587,6 +622,57 @@ typedef struct H5C_cache_entry_t
* above, this field contains the maximum number of bytes by which the
* cache size can be increased in a single re-size.
*
+ * flash_incr_mode: Instance of the H5C_cache_flash_incr_mode enumerated
+ * type whose value indicates whether and by what algorithm we should
+ * make flash increases in the size of the cache to accomodate insertion
+ * of large entries and large increases in the size of a single entry.
+ *
+ * The addition of the flash increment mode was occasioned by performance
+ * problems that appear when a local heap is increased to a size in excess
+ * of the current cache size. While the existing re-size code dealt with
+ * this eventually, performance was very bad for the remainder of the
+ * epoch.
+ *
+ * At present, there are two possible values for the flash_incr_mode:
+ *
+ * H5C_flash_incr__off: Don't perform flash increases in the size of
+ * the cache.
+ *
+ * H5C_flash_incr__add_space: Let x be either the size of a newly
+ * newly inserted entry, or the number of bytes by which the
+ * size of an existing entry has been increased.
+ *
+ * If
+ * x > flash_threshold * current max cache size,
+ *
+ * increase the current maximum cache size by x * flash_multiple
+ * less any free space in the cache, and start a new epoch. For
+ * now at least, pay no attention to the maximum increment.
+ *
+ *
+ * With a little thought, it should be obvious that the above flash
+ * cache size increase algorithm is not sufficient for all circumstances --
+ * for example, suppose the user round robins through
+ * (1/flash_threshold) +1 groups, adding one data set to each on each
+ * pass. Then all will increase in size at about the same time, requiring
+ * the max cache size to at least double to maintain acceptable
+ * performance, however the above flash increment algorithm will not be
+ * triggered.
+ *
+ * Hopefully, the add space algorithm detailed above will be sufficient
+ * for the performance problems encountered to date. However, we should
+ * expect to revisit the issue.
+ *
+ * flash_multiple: Double containing the multiple described above in the
+ * H5C_flash_incr__add_space section of the discussion of the
+ * flash_incr_mode section. This field is ignored unless flash_incr_mode
+ * is H5C_flash_incr__add_space.
+ *
+ * flash_threshold: Double containing the factor by which current max cache size
+ * is multiplied to obtain the size threshold for the add_space flash
+ * increment algorithm. The field is ignored unless flash_incr_mode is
+ * H5C_flash_incr__add_space.
+ *
*
* Cache size decrease control fields:
*
@@ -701,6 +787,8 @@ typedef struct H5C_cache_entry_t
#define H5C__DEF_AR_MIN_CLEAN_FRAC 0.5
#define H5C__DEF_AR_INCREMENT 2.0
#define H5C__DEF_AR_MAX_INCREMENT ((size_t)( 2 * 1024 * 1024))
+#define H5C__DEF_AR_FLASH_MULTIPLE 1.0
+#define H5C__DEV_AR_FLASH_THRESHOLD 0.25
#define H5C__DEF_AR_DECREMENT 0.9
#define H5C__DEF_AR_MAX_DECREMENT ((size_t)( 1 * 1024 * 1024))
#define H5C__DEF_AR_EPCHS_B4_EVICT 3
@@ -713,6 +801,7 @@ enum H5C_resize_status
{
in_spec,
increase,
+ flash_increase,
decrease,
at_max_size,
at_min_size,
@@ -733,45 +822,48 @@ typedef void (*H5C_auto_resize_rpt_fcn)(H5C_t * cache_ptr,
typedef struct H5C_auto_size_ctl_t
{
/* general configuration fields: */
- int32_t version;
- H5C_auto_resize_rpt_fcn rpt_fcn;
+ int32_t version;
+ H5C_auto_resize_rpt_fcn rpt_fcn;
- hbool_t set_initial_size;
- size_t initial_size;
+ hbool_t set_initial_size;
+ size_t initial_size;
- double min_clean_fraction;
+ double min_clean_fraction;
- size_t max_size;
- size_t min_size;
+ size_t max_size;
+ size_t min_size;
- int64_t epoch_length;
+ int64_t epoch_length;
/* size increase control fields: */
- enum H5C_cache_incr_mode incr_mode;
+ enum H5C_cache_incr_mode incr_mode;
- double lower_hr_threshold;
+ double lower_hr_threshold;
- double increment;
+ double increment;
- hbool_t apply_max_increment;
- size_t max_increment;
+ hbool_t apply_max_increment;
+ size_t max_increment;
+ enum H5C_cache_flash_incr_mode flash_incr_mode;
+ double flash_multiple;
+ double flash_threshold;
/* size decrease control fields: */
- enum H5C_cache_decr_mode decr_mode;
+ enum H5C_cache_decr_mode decr_mode;
- double upper_hr_threshold;
+ double upper_hr_threshold;
- double decrement;
+ double decrement;
- hbool_t apply_max_decrement;
- size_t max_decrement;
+ hbool_t apply_max_decrement;
+ size_t max_decrement;
- int32_t epochs_before_eviction;
+ int32_t epochs_before_eviction;
- hbool_t apply_empty_reserve;
- double empty_reserve;
+ hbool_t apply_empty_reserve;
+ double empty_reserve;
} H5C_auto_size_ctl_t;
@@ -807,7 +899,12 @@ typedef struct H5C_auto_size_ctl_t
* H5C__SIZE_CHANGED_FLAG
* H5C__PIN_ENTRY_FLAG
* H5C__UNPIN_ENTRY_FLAG
+ * H5C__FREE_FILE_SPACE_FLAG
+ * H5C__TAKE_OWNERSHIP_FLAG
+ *
+ * These flags apply to H5C_expunge_entry():
*
+ * H5C__FREE_FILE_SPACE_FLAG
*
* These flags apply to H5C_flush_cache():
*
@@ -822,6 +919,7 @@ typedef struct H5C_auto_size_ctl_t
* H5C__FLUSH_INVALIDATE_FLAG
* H5C__FLUSH_CLEAR_ONLY_FLAG
* H5C__FLUSH_MARKED_ENTRIES_FLAG
+ * H5C__TAKE_OWNERSHIP_FLAG
*/
#define H5C__NO_FLAGS_SET 0x0000
@@ -836,6 +934,8 @@ typedef struct H5C_auto_size_ctl_t
#define H5C__FLUSH_MARKED_ENTRIES_FLAG 0x0100
#define H5C__FLUSH_IGNORE_PROTECTED_FLAG 0x0200
#define H5C__READ_ONLY_FLAG 0x0400
+#define H5C__FREE_FILE_SPACE_FLAG 0x0800
+#define H5C__TAKE_OWNERSHIP_FLAG 0x1000
H5_DLL H5C_t * H5C_create(size_t max_cache_size,
@@ -868,7 +968,8 @@ H5_DLL herr_t H5C_expunge_entry(H5F_t * f,
hid_t secondary_dxpl_id,
H5C_t * cache_ptr,
const H5C_class_t * type,
- haddr_t addr);
+ haddr_t addr,
+ unsigned flags);
H5_DLL herr_t H5C_flush_cache(H5F_t * f,
hid_t primary_dxpl_id,
diff --git a/src/H5Cpublic.h b/src/H5Cpublic.h
index 082d512..7ef959a 100644
--- a/src/H5Cpublic.h
+++ b/src/H5Cpublic.h
@@ -41,6 +41,12 @@ enum H5C_cache_incr_mode
H5C_incr__threshold
};
+enum H5C_cache_flash_incr_mode
+{
+ H5C_flash_incr__off,
+ H5C_flash_incr__add_space
+};
+
enum H5C_cache_decr_mode
{
H5C_decr__off,
diff --git a/src/H5D.c b/src/H5D.c
index 98a3003..9c552c2 100644
--- a/src/H5D.c
+++ b/src/H5D.c
@@ -169,7 +169,7 @@ H5Dcreate2(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id,
if(NULL == (dset = H5D_create_named(&loc, name, type_id, space, lcpl_id,
dcpl_id, dapl_id, H5AC_dxpl_id)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create dataset")
- if((ret_value = H5I_register(H5I_DATASET, dset)) < 0)
+ if((ret_value = H5I_register(H5I_DATASET, dset, TRUE)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register dataset")
done:
@@ -249,11 +249,11 @@ H5Dcreate_anon(hid_t loc_id, hid_t type_id, hid_t space_id, hid_t dcpl_id,
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not dataset access property list")
/* build and open the new dataset */
- if(NULL == (dset = H5D_create(loc.oloc->file, type_id, space, dcpl_id, H5AC_dxpl_id)))
+ if(NULL == (dset = H5D_create(loc.oloc->file, type_id, space, dcpl_id, dapl_id, H5AC_dxpl_id)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create dataset")
/* Register the new dataset to get an ID for it */
- if((ret_value = H5I_register(H5I_DATASET, dset)) < 0)
+ if((ret_value = H5I_register(H5I_DATASET, dset, TRUE)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register dataset")
done:
@@ -328,11 +328,11 @@ H5Dopen2(hid_t loc_id, const char *name, hid_t dapl_id)
HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, FAIL, "not a dataset")
/* Open the dataset */
- if((dset = H5D_open(&dset_loc, dxpl_id)) == NULL)
+ if((dset = H5D_open(&dset_loc, dapl_id, dxpl_id)) == NULL)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't open dataset")
/* Register an atom for the dataset */
- if((ret_value = H5I_register(H5I_DATASET, dset)) < 0)
+ if((ret_value = H5I_register(H5I_DATASET, dset, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "can't register dataset atom")
done:
@@ -382,7 +382,7 @@ H5Dclose(hid_t dset_id)
* Decrement the counter on the dataset. It will be freed if the count
* reaches zero.
*/
- if(H5I_dec_ref(dset_id) < 0)
+ if(H5I_dec_ref(dset_id, TRUE) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't free")
done:
@@ -417,15 +417,15 @@ H5Dget_space(hid_t dset_id)
H5TRACE1("i", "i", dset_id);
/* Check args */
- if(NULL==(dset=(H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
+ if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
/* Read the data space message and return a data space object */
- if(NULL==(space=H5S_copy (dset->shared->space, FALSE)))
+ if(NULL == (space = H5S_copy(dset->shared->space, FALSE, TRUE)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to get data space")
/* Create an atom */
- if((ret_value=H5I_register (H5I_DATASPACE, space)) < 0)
+ if((ret_value = H5I_register (H5I_DATASPACE, space, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register data space")
done:
@@ -496,43 +496,41 @@ hid_t
H5Dget_type(hid_t dset_id)
{
- H5D_t *dset = NULL;
- H5T_t *copied_type = NULL;
- hid_t ret_value = FAIL;
+ H5D_t *dset; /* Dataset */
+ H5T_t *dt = NULL; /* Datatype to return */
+ hid_t ret_value; /* Return value */
FUNC_ENTER_API(H5Dget_type, FAIL)
H5TRACE1("i", "i", dset_id);
/* Check args */
- if(NULL==(dset=(H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
+ if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
- /* Copy the datatype and mark it read-only */
- if(NULL==(copied_type=H5T_copy (dset->shared->type, H5T_COPY_REOPEN)))
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to copy the datatype")
+ /* Copy the dataset's datatype */
+ if(NULL == (dt = H5T_copy(dset->shared->type, H5T_COPY_REOPEN)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to copy datatype")
/* Mark any datatypes as being in memory now */
- if(H5T_set_loc(copied_type, NULL, H5T_LOC_MEMORY) < 0)
+ if(H5T_set_loc(dt, NULL, H5T_LOC_MEMORY) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location")
- /* Unlock copied type */
- if(H5T_lock (copied_type, FALSE) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to lock transient datatype")
+ /* Lock copied type */
+ if(H5T_lock(dt, FALSE) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to lock transient datatype")
/* Create an atom */
- if((ret_value=H5I_register (H5I_DATATYPE, copied_type)) < 0)
+ if((ret_value = H5I_register(H5I_DATATYPE, dt, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register datatype")
done:
if(ret_value < 0) {
- if(copied_type!=NULL) {
- if(H5T_close (copied_type) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release datatype")
- } /* end if */
+ if(dt && H5T_close(dt) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release datatype")
} /* end if */
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5Dget_type() */
/*-------------------------------------------------------------------------
@@ -571,7 +569,7 @@ H5Dget_create_plist(hid_t dset_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list")
/* Copy the creation property list */
- if((new_dcpl_id = H5P_copy_plist(dcpl_plist)) < 0)
+ if((new_dcpl_id = H5P_copy_plist(dcpl_plist, TRUE)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to copy the creation property list")
if(NULL == (new_plist = (H5P_genplist_t *)H5I_object(new_dcpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list")
@@ -603,37 +601,37 @@ H5Dget_create_plist(hid_t dset_id)
size_t bkg_size; /* Size of background buffer */
/* Wrap copies of types to convert */
- dst_id = H5I_register(H5I_DATATYPE, H5T_copy(copied_fill.type, H5T_COPY_TRANSIENT));
+ dst_id = H5I_register(H5I_DATATYPE, H5T_copy(copied_fill.type, H5T_COPY_TRANSIENT), FALSE);
if(dst_id < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy/register datatype")
- src_id = H5I_register(H5I_DATATYPE, H5T_copy(dset->shared->type, H5T_COPY_ALL));
+ src_id = H5I_register(H5I_DATATYPE, H5T_copy(dset->shared->type, H5T_COPY_ALL), FALSE);
if(src_id < 0) {
- H5I_dec_ref(dst_id);
+ H5I_dec_ref(dst_id, FALSE);
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy/register datatype")
} /* end if */
/* Allocate a background buffer */
- bkg_size = MAX(H5T_get_size(copied_fill.type), H5T_get_size(dset->shared->type));
+ bkg_size = MAX(H5T_GET_SIZE(copied_fill.type), H5T_GET_SIZE(dset->shared->type));
if(H5T_path_bkg(tpath) && NULL == (bkg_buf = H5FL_BLK_CALLOC(type_conv, bkg_size))) {
- H5I_dec_ref(src_id);
- H5I_dec_ref(dst_id);
+ H5I_dec_ref(src_id, FALSE);
+ H5I_dec_ref(dst_id, FALSE);
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
} /* end if */
/* Convert fill value */
if(H5T_convert(tpath, src_id, dst_id, (size_t)1, (size_t)0, (size_t)0, copied_fill.buf, bkg_buf, H5AC_ind_dxpl_id) < 0) {
- H5I_dec_ref(src_id);
- H5I_dec_ref(dst_id);
+ H5I_dec_ref(src_id, FALSE);
+ H5I_dec_ref(dst_id, FALSE);
if(bkg_buf)
- H5FL_BLK_FREE(type_conv, bkg_buf);
+ (void)H5FL_BLK_FREE(type_conv, bkg_buf);
HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "datatype conversion failed")
} /* end if */
/* Release local resources */
- H5I_dec_ref(src_id);
- H5I_dec_ref(dst_id);
+ H5I_dec_ref(src_id, FALSE);
+ H5I_dec_ref(dst_id, FALSE);
if(bkg_buf)
- H5FL_BLK_FREE(type_conv, bkg_buf);
+ (void)H5FL_BLK_FREE(type_conv, bkg_buf);
} /* end if */
} /* end if */
@@ -647,13 +645,92 @@ H5Dget_create_plist(hid_t dset_id)
done:
if(ret_value < 0)
if(new_dcpl_id > 0)
- (void)H5I_dec_ref(new_dcpl_id);
+ (void)H5I_dec_ref(new_dcpl_id, TRUE);
FUNC_LEAVE_API(ret_value)
} /* end H5Dget_create_plist() */
/*-------------------------------------------------------------------------
+ * Function: H5Dget_access_plist
+ *
+ * Purpose: Returns a copy of the dataset creation property list.
+ *
+ * Description: H5Dget_access_plist returns the dataset access property
+ * list identifier of the specified dataset.
+ *
+ * The chunk cache parameters in the returned property lists will be
+ * those used by the dataset. If the properties in the file access
+ * property list were used to determine the dataset’s chunk cache
+ * configuration, then those properties will be present in the
+ * returned dataset access property list. If the dataset does not
+ * use a chunked layout, then the chunk cache properties will be set
+ * to the default. The chunk cache properties in the returned list
+ * are considered to be “setâ€, and any use of this list will override
+ * the corresponding properties in the file’s file access property
+ * list.
+ *
+ * All link access properties in the returned list will be set to the
+ * default values.
+ *
+ * Return: Success: ID for a copy of the dataset access
+ * property list. The template should be
+ * released by calling H5Pclose().
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Neil Fortner
+ * Wednesday, October 29, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5Dget_access_plist(hid_t dset_id)
+{
+ H5D_t *dset; /* Dataset structure */
+ H5P_genplist_t *old_plist; /* Default DAPL */
+ H5P_genplist_t *new_plist; /* New DAPL */
+ hid_t new_dapl_id = FAIL;
+ hid_t ret_value; /* Return value */
+
+ FUNC_ENTER_API(H5Dget_access_plist, FAIL)
+ H5TRACE1("i", "i", dset_id);
+
+ /* Check args */
+ if (NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
+
+ /* Make a copy of the default dataset access property list */
+ if (NULL == (old_plist = (H5P_genplist_t *)H5I_object(H5P_LST_DATASET_ACCESS_g)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
+ if ((new_dapl_id = H5P_copy_plist(old_plist, TRUE)) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_CANTINIT, FAIL, "can't copy dataset access property list")
+ if (NULL == (new_plist = (H5P_genplist_t *)H5I_object(new_dapl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
+
+ /* If the dataset is chunked then copy the rdcc parameters */
+ if (dset->shared->layout.type == H5D_CHUNKED) {
+ if (H5P_set(new_plist, H5D_ACS_DATA_CACHE_NUM_SLOTS_NAME, &(dset->shared->cache.chunk.nslots)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set data cache number of slots")
+ if (H5P_set(new_plist, H5D_ACS_DATA_CACHE_BYTE_SIZE_NAME, &(dset->shared->cache.chunk.nbytes)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set data cache byte size")
+ if (H5P_set(new_plist, H5D_ACS_PREEMPT_READ_CHUNKS_NAME, &(dset->shared->cache.chunk.w0)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set preempt read chunks")
+ } /* end if */
+
+ /* Set the return value */
+ ret_value = new_dapl_id;
+
+done:
+ if(ret_value < 0)
+ if(new_dapl_id >= 0)
+ (void)H5I_dec_ref(new_dapl_id, TRUE);
+
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Dget_access_plist() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5Dget_storage_size
*
* Purpose: Returns the amount of storage that is required for the
@@ -674,22 +751,22 @@ done:
hsize_t
H5Dget_storage_size(hid_t dset_id)
{
- H5D_t *dset=NULL;
+ H5D_t *dset; /* Dataset to query */
hsize_t ret_value; /* Return value */
FUNC_ENTER_API(H5Dget_storage_size, 0)
H5TRACE1("h", "i", dset_id);
/* Check args */
- if(NULL==(dset=(H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
+ if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a dataset")
/* Set return value */
- ret_value = H5D_get_storage_size(dset,H5AC_ind_dxpl_id);
+ ret_value = H5D_get_storage_size(dset, H5AC_ind_dxpl_id);
done:
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5Dget_storage_size() */
/*-------------------------------------------------------------------------
@@ -709,14 +786,14 @@ done:
haddr_t
H5Dget_offset(hid_t dset_id)
{
- H5D_t *dset=NULL;
+ H5D_t *dset; /* Dataset to query */
haddr_t ret_value; /* Return value */
FUNC_ENTER_API(H5Dget_offset, HADDR_UNDEF)
H5TRACE1("a", "i", dset_id);
/* Check args */
- if(NULL==(dset=(H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
+ if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, HADDR_UNDEF, "not a dataset")
/* Set return value */
@@ -724,7 +801,7 @@ H5Dget_offset(hid_t dset_id)
done:
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5Dget_offset() */
/*-------------------------------------------------------------------------
@@ -790,22 +867,22 @@ herr_t
H5Diterate(void *buf, hid_t type_id, hid_t space_id, H5D_operator_t op,
void *operator_data)
{
- H5S_t *space = NULL;
- herr_t ret_value;
+ H5S_t *space; /* Dataspace for iteration */
+ herr_t ret_value; /* Return value */
FUNC_ENTER_API(H5Diterate, FAIL)
H5TRACE5("e", "*xiix*x", buf, type_id, space_id, op, operator_data);
/* Check args */
- if(NULL==op)
+ if(NULL == op)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid operator")
- if(buf==NULL)
+ if(NULL == buf)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid buffer")
if(H5I_DATATYPE != H5I_get_type(type_id))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid datatype")
if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataspace")
- if(!(H5S_has_extent(space)) )
+ if(!(H5S_has_extent(space)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspace does not have extent set")
ret_value = H5D_iterate(buf, type_id, space, op, operator_data);
@@ -833,8 +910,8 @@ done:
herr_t
H5Dvlen_reclaim(hid_t type_id, hid_t space_id, hid_t plist_id, void *buf)
{
- H5S_t *space = NULL;
- herr_t ret_value;
+ H5S_t *space; /* Dataspace for iteration */
+ herr_t ret_value; /* Return value */
FUNC_ENTER_API(H5Dvlen_reclaim, FAIL)
H5TRACE4("e", "iii*x", type_id, space_id, plist_id, buf);
@@ -891,18 +968,18 @@ H5Dvlen_get_buf_size(hid_t dataset_id, hid_t type_id, hid_t space_id,
hsize_t *size)
{
H5D_vlen_bufsize_t vlen_bufsize = {0, 0, 0, 0, 0, 0, 0};
- char bogus; /* bogus value to pass to H5Diterate() */
- H5S_t *space = NULL;
+ char bogus; /* bogus value to pass to H5Diterate() */
+ H5S_t *space; /* Dataspace for iteration */
H5P_genclass_t *pclass; /* Property class */
H5P_genplist_t *plist; /* Property list */
- herr_t ret_value=FAIL;
+ herr_t ret_value; /* Return value */
FUNC_ENTER_API(H5Dvlen_get_buf_size, FAIL)
H5TRACE4("e", "iii*h", dataset_id, type_id, space_id, size);
/* Check args */
- if(H5I_DATASET!=H5I_get_type(dataset_id) ||
- H5I_DATATYPE!=H5I_get_type(type_id) || size==NULL)
+ if(H5I_DATASET != H5I_get_type(dataset_id) ||
+ H5I_DATATYPE != H5I_get_type(type_id) || size == NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid argument")
if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataspace")
@@ -910,10 +987,10 @@ H5Dvlen_get_buf_size(hid_t dataset_id, hid_t type_id, hid_t space_id,
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspace does not have extent set")
/* Save the dataset ID */
- vlen_bufsize.dataset_id=dataset_id;
+ vlen_bufsize.dataset_id = dataset_id;
/* Get a copy of the dataspace ID */
- if((vlen_bufsize.fspace_id=H5Dget_space(dataset_id)) < 0)
+ if((vlen_bufsize.fspace_id = H5Dget_space(dataset_id)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy dataspace")
/* Create a scalar for the memory dataspace */
@@ -921,9 +998,9 @@ H5Dvlen_get_buf_size(hid_t dataset_id, hid_t type_id, hid_t space_id,
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't create dataspace")
/* Grab the temporary buffers required */
- if((vlen_bufsize.fl_tbuf = H5FL_BLK_MALLOC(vlen_fl_buf, (size_t)1)) == NULL)
+ if(NULL == (vlen_bufsize.fl_tbuf = H5FL_BLK_MALLOC(vlen_fl_buf, (size_t)1)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "no temporary buffers available")
- if((vlen_bufsize.vl_tbuf = H5FL_BLK_MALLOC(vlen_vl_buf, (size_t)1)) == NULL)
+ if(NULL == (vlen_bufsize.vl_tbuf = H5FL_BLK_MALLOC(vlen_vl_buf, (size_t)1)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "no temporary buffers available")
/* Get the pointer to the dataset transfer class */
@@ -931,7 +1008,7 @@ H5Dvlen_get_buf_size(hid_t dataset_id, hid_t type_id, hid_t space_id,
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list class")
/* Change to the custom memory allocation routines for reading VL data */
- if((vlen_bufsize.xfer_pid=H5P_create_id(pclass)) < 0)
+ if((vlen_bufsize.xfer_pid = H5P_create_id(pclass, FALSE)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTCREATE, FAIL, "no dataset xfer plists available")
/* Get the property list struct */
@@ -943,7 +1020,7 @@ H5Dvlen_get_buf_size(hid_t dataset_id, hid_t type_id, hid_t space_id,
HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "can't set VL data allocation routine")
/* Set the initial number of bytes required */
- vlen_bufsize.size=0;
+ vlen_bufsize.size = 0;
/* Call H5D_iterate with args, etc. */
ret_value = H5D_iterate(&bogus, type_id, space, H5D_vlen_get_buf_size, &vlen_bufsize);
@@ -954,11 +1031,11 @@ H5Dvlen_get_buf_size(hid_t dataset_id, hid_t type_id, hid_t space_id,
done:
if(vlen_bufsize.fspace_id > 0) {
- if(H5I_dec_ref(vlen_bufsize.fspace_id) < 0)
+ if(H5I_dec_ref(vlen_bufsize.fspace_id, FALSE) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataspace")
} /* end if */
if(vlen_bufsize.mspace_id > 0) {
- if(H5I_dec_ref(vlen_bufsize.mspace_id) < 0)
+ if(H5I_dec_ref(vlen_bufsize.mspace_id, FALSE) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataspace")
} /* end if */
if(vlen_bufsize.fl_tbuf != NULL)
@@ -966,7 +1043,7 @@ done:
if(vlen_bufsize.vl_tbuf != NULL)
(void)H5FL_BLK_FREE(vlen_vl_buf, vlen_bufsize.vl_tbuf);
if(vlen_bufsize.xfer_pid > 0) {
- if(H5I_dec_ref(vlen_bufsize.xfer_pid) < 0)
+ if(H5I_dec_ref(vlen_bufsize.xfer_pid, FALSE) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "unable to decrement ref count on property list")
} /* end if */
@@ -988,25 +1065,25 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5Dset_extent(hid_t dset_id, const hsize_t *size)
+H5Dset_extent(hid_t dset_id, const hsize_t size[])
{
H5D_t *dset; /* Dataset for this operation */
herr_t ret_value = SUCCEED; /* Return value */
-
+
FUNC_ENTER_API(H5Dset_extent, FAIL)
H5TRACE2("e", "i*h", dset_id, size);
-
+
/* Check args */
if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
if(!size)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no size specified")
-
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no size specified")
+
/* Private function */
if(H5D_set_extent(dset, size, H5AC_dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set extend dataset")
-
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set extend dataset")
+
done:
- FUNC_LEAVE_API(ret_value)
+ FUNC_LEAVE_API(ret_value)
} /* end H5Dset_extent() */
diff --git a/src/H5Dbtree.c b/src/H5Dbtree.c
new file mode 100644
index 0000000..baa4c6b
--- /dev/null
+++ b/src/H5Dbtree.c
@@ -0,0 +1,1385 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/* Programmer: Robb Matzke <matzke@llnl.gov>
+ * Wednesday, October 8, 1997
+ *
+ * Purpose: v1 B-tree indexed (chunked) I/O functions. The logical
+ * multi-dimensional data space is regularly partitioned into
+ * same-sized "chunks", the first of which is aligned with the
+ * logical origin. The chunks are given a multi-dimensional
+ * index which is used as a lookup key in a B-tree that maps
+ * chunk index to disk address. Each chunk can be compressed
+ * independently and the chunks may move around in the file as
+ * their storage requirements change.
+ *
+ * Cache: Disk I/O is performed in units of chunks and H5MF_alloc()
+ * contains code to optionally align chunks on disk block
+ * boundaries for performance.
+ *
+ * The chunk cache is an extendible hash indexed by a function
+ * of storage B-tree address and chunk N-dimensional offset
+ * within the dataset. Collisions are not resolved -- one of
+ * the two chunks competing for the hash slot must be preempted
+ * from the cache. All entries in the hash also participate in
+ * a doubly-linked list and entries are penalized by moving them
+ * toward the front of the list. When a new chunk is about to
+ * be added to the cache the heap is pruned by preempting
+ * entries near the front of the list to make room for the new
+ * entry which is added to the end of the list.
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5B_PACKAGE /*suppress error about including H5Bpkg */
+#define H5D_PACKAGE /*suppress error about including H5Dpkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Bpkg.h" /* B-link trees */
+#include "H5Dpkg.h" /* Datasets */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fprivate.h" /* Files */
+#include "H5FDprivate.h" /* File drivers */
+#include "H5FLprivate.h" /* Free Lists */
+#include "H5Iprivate.h" /* IDs */
+#include "H5MFprivate.h" /* File space management */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5Oprivate.h" /* Object headers */
+#include "H5Pprivate.h" /* Property lists */
+#include "H5Sprivate.h" /* Dataspaces */
+#include "H5SLprivate.h" /* Skip lists */
+#include "H5Vprivate.h" /* Vector and array functions */
+
+/****************/
+/* Local Macros */
+/****************/
+
+/*
+ * Given a B-tree node return the dimensionality of the chunks pointed to by
+ * that node.
+ */
+#define H5D_BTREE_NDIMS(X) (((X)->sizeof_rkey-8)/8)
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+/*
+ * B-tree key. A key contains the minimum logical N-dimensional coordinates and
+ * the logical size of the chunk to which this key refers. The
+ * fastest-varying dimension is assumed to reference individual bytes of the
+ * array, so a 100-element 1-d array of 4-byte integers would really be a 2-d
+ * array with the slow varying dimension of size 100 and the fast varying
+ * dimension of size 4 (the storage dimensionality has very little to do with
+ * the real dimensionality).
+ *
+ * Only the first few values of the OFFSET and SIZE fields are actually
+ * stored on disk, depending on the dimensionality.
+ *
+ * The chunk's file address is part of the B-tree and not part of the key.
+ */
+typedef struct H5D_btree_key_t {
+ uint32_t nbytes; /*size of stored data */
+ hsize_t offset[H5O_LAYOUT_NDIMS]; /*logical offset to start*/
+ unsigned filter_mask; /*excluded filters */
+} H5D_btree_key_t;
+
+/*
+ * Data exchange structure for indexed storage nodes. This structure is
+ * passed through the B-link tree layer to the methods for the objects
+ * to which the B-link tree points for operations which require no
+ * additional information.
+ *
+ * (Just an alias for the "common" info).
+ */
+typedef H5D_chunk_common_ud_t H5D_btree_ud0_t;
+
+/* B-tree callback info for iteration over chunks */
+typedef struct H5D_btree_it_ud_t {
+ H5D_chunk_common_ud_t common; /* Common info for B-tree user data (must be first) */
+ H5D_chunk_cb_func_t cb; /* Chunk callback routine */
+ void *udata; /* User data for chunk callback routine */
+} H5D_btree_it_ud_t;
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+static herr_t H5D_btree_shared_create(const H5F_t *f, H5O_layout_t *layout);
+
+/* B-tree iterator callbacks */
+static int H5D_btree_idx_iterate_cb(H5F_t *f, hid_t dxpl_id, const void *left_key,
+ haddr_t addr, const void *right_key, void *_udata);
+
+/* B-tree callbacks */
+static H5RC_t *H5D_btree_get_shared(const H5F_t *f, const void *_udata);
+static herr_t H5D_btree_new_node(H5F_t *f, hid_t dxpl_id, H5B_ins_t, void *_lt_key,
+ void *_udata, void *_rt_key, haddr_t *addr_p /*out*/);
+static int H5D_btree_cmp2(H5F_t *f, hid_t dxpl_id, void *_lt_key, void *_udata,
+ void *_rt_key);
+static int H5D_btree_cmp3(H5F_t *f, hid_t dxpl_id, void *_lt_key, void *_udata,
+ void *_rt_key);
+static htri_t H5D_btree_found(H5F_t *f, hid_t dxpl_id, haddr_t addr,
+ const void *_lt_key, void *_udata);
+static H5B_ins_t H5D_btree_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr,
+ void *_lt_key, hbool_t *lt_key_changed, void *_md_key, void *_udata,
+ void *_rt_key, hbool_t *rt_key_changed, haddr_t *new_node/*out*/);
+static H5B_ins_t H5D_btree_remove( H5F_t *f, hid_t dxpl_id, haddr_t addr,
+ void *_lt_key, hbool_t *lt_key_changed, void *_udata, void *_rt_key,
+ hbool_t *rt_key_changed);
+static herr_t H5D_btree_decode_key(const H5F_t *f, const H5B_t *bt,
+ const uint8_t *raw, void *_key);
+static herr_t H5D_btree_encode_key(const H5F_t *f, const H5B_t *bt,
+ uint8_t *raw, void *_key);
+static herr_t H5D_btree_debug_key(FILE *stream, H5F_t *f, hid_t dxpl_id,
+ int indent, int fwidth, const void *key, const void *udata);
+
+/* Chunked layout indexing callbacks */
+static herr_t H5D_btree_idx_init(const H5D_chk_idx_info_t *idx_info);
+static herr_t H5D_btree_idx_create(const H5D_chk_idx_info_t *idx_info);
+static herr_t H5D_btree_idx_insert(const H5D_chk_idx_info_t *idx_info,
+ H5D_chunk_ud_t *udata);
+static herr_t H5D_btree_idx_get_addr(const H5D_chk_idx_info_t *idx_info,
+ H5D_chunk_ud_t *udata);
+static int H5D_btree_idx_iterate(const H5D_chk_idx_info_t *idx_info,
+ H5D_chunk_cb_func_t chunk_cb, void *chunk_udata);
+static herr_t H5D_btree_idx_remove(const H5D_chk_idx_info_t *idx_info,
+ H5D_chunk_common_ud_t *udata);
+static herr_t H5D_btree_idx_delete(const H5D_chk_idx_info_t *idx_info);
+static herr_t H5D_btree_idx_copy_setup(const H5D_chk_idx_info_t *idx_info_src,
+ const H5D_chk_idx_info_t *idx_info_dst);
+static herr_t H5D_btree_idx_copy_shutdown(H5O_layout_t *layout_src,
+ H5O_layout_t *layout_dst);
+static herr_t H5D_btree_idx_size(const H5D_chk_idx_info_t *idx_info,
+ hsize_t *size);
+static herr_t H5D_btree_idx_dest(const H5D_chk_idx_info_t *idx_info);
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+/* v1 B-tree indexed chunk I/O ops */
+const H5D_chunk_ops_t H5D_COPS_BTREE[1] = {{
+ H5D_btree_idx_init,
+ H5D_btree_idx_create,
+ H5D_btree_idx_insert,
+ H5D_btree_idx_get_addr,
+ H5D_btree_idx_iterate,
+ H5D_btree_idx_remove,
+ H5D_btree_idx_delete,
+ H5D_btree_idx_copy_setup,
+ H5D_btree_idx_copy_shutdown,
+ H5D_btree_idx_size,
+ H5D_btree_idx_dest
+}};
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+/* inherits B-tree like properties from H5B */
+H5B_class_t H5B_BTREE[1] = {{
+ H5B_CHUNK_ID, /*id */
+ sizeof(H5D_btree_key_t), /*sizeof_nkey */
+ H5D_btree_get_shared, /*get_shared */
+ H5D_btree_new_node, /*new */
+ H5D_btree_cmp2, /*cmp2 */
+ H5D_btree_cmp3, /*cmp3 */
+ H5D_btree_found, /*found */
+ H5D_btree_insert, /*insert */
+ FALSE, /*follow min branch? */
+ FALSE, /*follow max branch? */
+ H5D_btree_remove, /*remove */
+ H5D_btree_decode_key, /*decode */
+ H5D_btree_encode_key, /*encode */
+ H5D_btree_debug_key, /*debug */
+}};
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_btree_get_shared
+ *
+ * Purpose: Returns the shared B-tree info for the specified UDATA.
+ *
+ * Return: Success: Pointer to the raw B-tree page for this dataset
+ *
+ * Failure: Can't fail
+ *
+ * Programmer: Quincey Koziol
+ * Monday, July 5, 2004
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static H5RC_t *
+H5D_btree_get_shared(const H5F_t UNUSED *f, const void *_udata)
+{
+ const H5D_btree_ud0_t *udata = (const H5D_btree_ud0_t *) _udata;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_btree_get_shared)
+
+ HDassert(udata);
+ HDassert(udata->mesg);
+ HDassert(udata->mesg->u.chunk.btree_shared);
+
+ /* Increment reference count on B-tree info */
+ H5RC_INC(udata->mesg->u.chunk.btree_shared);
+
+ /* Return the pointer to the ref-count object */
+ FUNC_LEAVE_NOAPI(udata->mesg->u.chunk.btree_shared)
+} /* end H5D_btree_get_shared() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_btree_new_node
+ *
+ * Purpose: Adds a new entry to an i-storage B-tree. We can assume that
+ * the domain represented by UDATA doesn't intersect the domain
+ * already represented by the B-tree.
+ *
+ * Return: Success: Non-negative. The address of leaf is returned
+ * through the ADDR argument. It is also added
+ * to the UDATA.
+ *
+ * Failure: Negative
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, October 14, 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_btree_new_node(H5F_t *f, hid_t dxpl_id, H5B_ins_t op,
+ void *_lt_key, void *_udata, void *_rt_key,
+ haddr_t *addr_p/*out*/)
+{
+ H5D_btree_key_t *lt_key = (H5D_btree_key_t *) _lt_key;
+ H5D_btree_key_t *rt_key = (H5D_btree_key_t *) _rt_key;
+ H5D_chunk_ud_t *udata = (H5D_chunk_ud_t *) _udata;
+ unsigned u;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_btree_new_node)
+
+ /* check args */
+ HDassert(f);
+ HDassert(lt_key);
+ HDassert(rt_key);
+ HDassert(udata);
+ HDassert(udata->common.mesg->u.chunk.ndims > 0 && udata->common.mesg->u.chunk.ndims < H5O_LAYOUT_NDIMS);
+ HDassert(addr_p);
+
+ /* Allocate new storage */
+ HDassert(udata->nbytes > 0);
+ H5_CHECK_OVERFLOW(udata->nbytes, uint32_t, hsize_t);
+ if(HADDR_UNDEF == (*addr_p = H5MF_alloc(f, H5FD_MEM_DRAW, dxpl_id, (hsize_t)udata->nbytes)))
+ HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "couldn't allocate new file storage")
+ udata->addr = *addr_p;
+
+ /*
+ * The left key describes the storage of the UDATA chunk being
+ * inserted into the tree.
+ */
+ lt_key->nbytes = udata->nbytes;
+ lt_key->filter_mask = udata->filter_mask;
+ for(u = 0; u < udata->common.mesg->u.chunk.ndims; u++)
+ lt_key->offset[u] = udata->common.offset[u];
+
+ /*
+ * The right key might already be present. If not, then add a zero-width
+ * chunk.
+ */
+ if(H5B_INS_LEFT != op) {
+ rt_key->nbytes = 0;
+ rt_key->filter_mask = 0;
+ for(u = 0; u < udata->common.mesg->u.chunk.ndims; u++) {
+ HDassert(udata->common.offset[u] + udata->common.mesg->u.chunk.dim[u] >
+ udata->common.offset[u]);
+ rt_key->offset[u] = udata->common.offset[u] + udata->common.mesg->u.chunk.dim[u];
+ } /* end if */
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_btree_new_node() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_btree_cmp2
+ *
+ * Purpose: Compares two keys sort of like strcmp(). The UDATA pointer
+ * is only to supply extra information not carried in the keys
+ * (in this case, the dimensionality) and is not compared
+ * against the keys.
+ *
+ * Return: Success: -1 if LT_KEY is less than RT_KEY;
+ * 1 if LT_KEY is greater than RT_KEY;
+ * 0 if LT_KEY and RT_KEY are equal.
+ *
+ * Failure: FAIL (same as LT_KEY<RT_KEY)
+ *
+ * Programmer: Robb Matzke
+ * Thursday, November 6, 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+H5D_btree_cmp2(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, void *_lt_key, void *_udata,
+ void *_rt_key)
+{
+ H5D_btree_key_t *lt_key = (H5D_btree_key_t *) _lt_key;
+ H5D_btree_key_t *rt_key = (H5D_btree_key_t *) _rt_key;
+ H5D_btree_ud0_t *udata = (H5D_btree_ud0_t *) _udata;
+ int ret_value;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_btree_cmp2)
+
+ HDassert(lt_key);
+ HDassert(rt_key);
+ HDassert(udata);
+ HDassert(udata->mesg->u.chunk.ndims > 0 && udata->mesg->u.chunk.ndims <= H5O_LAYOUT_NDIMS);
+
+ /* Compare the offsets but ignore the other fields */
+ ret_value = H5V_vector_cmp_u(udata->mesg->u.chunk.ndims, lt_key->offset, rt_key->offset);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_btree_cmp2() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_btree_cmp3
+ *
+ * Purpose: Compare the requested datum UDATA with the left and right
+ * keys of the B-tree.
+ *
+ * Return: Success: negative if the min_corner of UDATA is less
+ * than the min_corner of LT_KEY.
+ *
+ * positive if the min_corner of UDATA is
+ * greater than or equal the min_corner of
+ * RT_KEY.
+ *
+ * zero otherwise. The min_corner of UDATA is
+ * not necessarily contained within the address
+ * space represented by LT_KEY, but a key that
+ * would describe the UDATA min_corner address
+ * would fall lexicographically between LT_KEY
+ * and RT_KEY.
+ *
+ * Failure: FAIL (same as UDATA < LT_KEY)
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, October 8, 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+H5D_btree_cmp3(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, void *_lt_key, void *_udata,
+ void *_rt_key)
+{
+ H5D_btree_key_t *lt_key = (H5D_btree_key_t *) _lt_key;
+ H5D_btree_key_t *rt_key = (H5D_btree_key_t *) _rt_key;
+ H5D_btree_ud0_t *udata = (H5D_btree_ud0_t *) _udata;
+ int ret_value = 0;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_btree_cmp3)
+
+ HDassert(lt_key);
+ HDassert(rt_key);
+ HDassert(udata);
+ HDassert(udata->mesg->u.chunk.ndims > 0 && udata->mesg->u.chunk.ndims <= H5O_LAYOUT_NDIMS);
+
+ /* Special case for faster checks on 1-D chunks */
+ /* (Checking for ndims==2 because last dimension is the datatype size) */
+ /* The additional checking for the right key is necessary due to the */
+ /* slightly odd way the library initializes the right-most node in the */
+ /* indexed storage B-tree... */
+ /* (Dump the B-tree with h5debug to look at it) -QAK */
+ if(udata->mesg->u.chunk.ndims == 2) {
+ if(udata->offset[0] > rt_key->offset[0])
+ ret_value = 1;
+ else if(udata->offset[0] == rt_key->offset[0] &&
+ udata->offset[1] >= rt_key->offset[1])
+ ret_value = 1;
+ else if(udata->offset[0] < lt_key->offset[0])
+ ret_value = (-1);
+ } /* end if */
+ else {
+ if(H5V_vector_ge_u(udata->mesg->u.chunk.ndims, udata->offset, rt_key->offset))
+ ret_value = 1;
+ else if(H5V_vector_lt_u(udata->mesg->u.chunk.ndims, udata->offset, lt_key->offset))
+ ret_value = (-1);
+ } /* end else */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_btree_cmp3() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_btree_found
+ *
+ * Purpose: This function is called when the B-tree search engine has
+ * found the leaf entry that points to a chunk of storage that
+ * contains the beginning of the logical address space
+ * represented by UDATA. The LT_KEY is the left key (the one
+ * that describes the chunk) and RT_KEY is the right key (the
+ * one that describes the next or last chunk).
+ *
+ * Note: It's possible that the chunk isn't really found. For
+ * instance, in a sparse dataset the requested chunk might fall
+ * between two stored chunks in which case this function is
+ * called with the maximum stored chunk indices less than the
+ * requested chunk indices.
+ *
+ * Return: Non-negative (TRUE/FALSE) on success with information about the
+ * chunk returned through the UDATA argument. Negative on failure.
+ *
+ * Programmer: Robb Matzke
+ * Thursday, October 9, 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static htri_t
+H5D_btree_found(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, haddr_t addr, const void *_lt_key,
+ void *_udata)
+{
+ H5D_chunk_ud_t *udata = (H5D_chunk_ud_t *) _udata;
+ const H5D_btree_key_t *lt_key = (const H5D_btree_key_t *) _lt_key;
+ unsigned u;
+ htri_t ret_value = TRUE; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_btree_found)
+
+ /* Check arguments */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(udata);
+ HDassert(lt_key);
+
+ /* Is this *really* the requested chunk? */
+ for(u = 0; u < udata->common.mesg->u.chunk.ndims; u++)
+ if(udata->common.offset[u] >= lt_key->offset[u] + udata->common.mesg->u.chunk.dim[u])
+ HGOTO_DONE(FALSE)
+
+ /* Initialize return values */
+ HDassert(lt_key->nbytes > 0);
+ udata->addr = addr;
+ udata->nbytes = lt_key->nbytes;
+ udata->filter_mask = lt_key->filter_mask;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_btree_found() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_btree_insert
+ *
+ * Purpose: This function is called when the B-tree insert engine finds
+ * the node to use to insert new data. The UDATA argument
+ * points to a struct that describes the logical addresses being
+ * added to the file. This function allocates space for the
+ * data and returns information through UDATA describing a
+ * file chunk to receive (part of) the data.
+ *
+ * The LT_KEY is always the key describing the chunk of file
+ * memory at address ADDR. On entry, UDATA describes the logical
+ * addresses for which storage is being requested (through the
+ * `offset' and `size' fields). On return, UDATA describes the
+ * logical addresses contained in a chunk on disk.
+ *
+ * Return: Success: An insertion command for the caller, one of
+ * the H5B_INS_* constants. The address of the
+ * new chunk is returned through the NEW_NODE
+ * argument.
+ *
+ * Failure: H5B_INS_ERROR
+ *
+ * Programmer: Robb Matzke
+ * Thursday, October 9, 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static H5B_ins_t
+H5D_btree_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key,
+ hbool_t *lt_key_changed,
+ void *_md_key, void *_udata, void *_rt_key,
+ hbool_t UNUSED *rt_key_changed,
+ haddr_t *new_node_p/*out*/)
+{
+ H5D_btree_key_t *lt_key = (H5D_btree_key_t *) _lt_key;
+ H5D_btree_key_t *md_key = (H5D_btree_key_t *) _md_key;
+ H5D_btree_key_t *rt_key = (H5D_btree_key_t *) _rt_key;
+ H5D_chunk_ud_t *udata = (H5D_chunk_ud_t *) _udata;
+ int cmp;
+ unsigned u;
+ H5B_ins_t ret_value;
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_btree_insert)
+
+ /* check args */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(lt_key);
+ HDassert(lt_key_changed);
+ HDassert(md_key);
+ HDassert(udata);
+ HDassert(rt_key);
+ HDassert(new_node_p);
+
+ cmp = H5D_btree_cmp3(f, dxpl_id, lt_key, udata, rt_key);
+ HDassert(cmp <= 0);
+
+ if(cmp < 0) {
+ /* Negative indices not supported yet */
+ HGOTO_ERROR(H5E_STORAGE, H5E_UNSUPPORTED, H5B_INS_ERROR, "internal error")
+
+ } else if(H5V_vector_eq_u(udata->common.mesg->u.chunk.ndims,
+ udata->common.offset, lt_key->offset) &&
+ lt_key->nbytes > 0) {
+ /*
+ * Already exists. If the new size is not the same as the old size
+ * then we should reallocate storage.
+ */
+ if(lt_key->nbytes != udata->nbytes) {
+/* Currently, the old chunk data is "thrown away" after the space is reallocated,
+ * so avoid data copy in H5MF_realloc() call by just free'ing the space and
+ * allocating new space.
+ *
+ * This should keep the file smaller also, by freeing the space and then
+ * allocating new space, instead of vice versa (in H5MF_realloc).
+ *
+ * QAK - 11/19/2002
+ */
+#ifdef OLD_WAY
+ if(HADDR_UNDEF == (*new_node_p = H5MF_realloc(f, H5FD_MEM_DRAW, addr,
+ (hsize_t)lt_key->nbytes, (hsize_t)udata->nbytes)))
+ HGOTO_ERROR(H5E_STORAGE, H5E_NOSPACE, H5B_INS_ERROR, "unable to reallocate chunk storage")
+#else /* OLD_WAY */
+ H5_CHECK_OVERFLOW(lt_key->nbytes, uint32_t, hsize_t);
+ if(H5MF_xfree(f, H5FD_MEM_DRAW, dxpl_id, addr, (hsize_t)lt_key->nbytes) < 0)
+ HGOTO_ERROR(H5E_STORAGE, H5E_CANTFREE, H5B_INS_ERROR, "unable to free chunk")
+ H5_CHECK_OVERFLOW(udata->nbytes, uint32_t, hsize_t);
+ if(HADDR_UNDEF == (*new_node_p = H5MF_alloc(f, H5FD_MEM_DRAW, dxpl_id, (hsize_t)udata->nbytes)))
+ HGOTO_ERROR(H5E_STORAGE, H5E_NOSPACE, H5B_INS_ERROR, "unable to reallocate chunk")
+#endif /* OLD_WAY */
+ lt_key->nbytes = udata->nbytes;
+ lt_key->filter_mask = udata->filter_mask;
+ *lt_key_changed = TRUE;
+ udata->addr = *new_node_p;
+ ret_value = H5B_INS_CHANGE;
+ } else {
+ udata->addr = addr;
+ ret_value = H5B_INS_NOOP;
+ }
+
+ } else if (H5V_hyper_disjointp(udata->common.mesg->u.chunk.ndims,
+ lt_key->offset, udata->common.mesg->u.chunk.dim,
+ udata->common.offset, udata->common.mesg->u.chunk.dim)) {
+ HDassert(H5V_hyper_disjointp(udata->common.mesg->u.chunk.ndims,
+ rt_key->offset, udata->common.mesg->u.chunk.dim,
+ udata->common.offset, udata->common.mesg->u.chunk.dim));
+ /*
+ * Split this node, inserting the new new node to the right of the
+ * current node. The MD_KEY is where the split occurs.
+ */
+ md_key->nbytes = udata->nbytes;
+ md_key->filter_mask = udata->filter_mask;
+ for(u = 0; u < udata->common.mesg->u.chunk.ndims; u++) {
+ HDassert(0 == udata->common.offset[u] % udata->common.mesg->u.chunk.dim[u]);
+ md_key->offset[u] = udata->common.offset[u];
+ } /* end for */
+
+ /*
+ * Allocate storage for the new chunk
+ */
+ H5_CHECK_OVERFLOW(udata->nbytes, uint32_t, hsize_t);
+ if(HADDR_UNDEF == (*new_node_p = H5MF_alloc(f, H5FD_MEM_DRAW, dxpl_id, (hsize_t)udata->nbytes)))
+ HGOTO_ERROR(H5E_STORAGE, H5E_NOSPACE, H5B_INS_ERROR, "file allocation failed")
+ udata->addr = *new_node_p;
+ ret_value = H5B_INS_RIGHT;
+
+ } else {
+ HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, H5B_INS_ERROR, "internal error")
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_btree_insert() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_btree_remove
+ *
+ * Purpose: Removes chunks that are no longer necessary in the B-tree.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * Pedro Vicente, pvn@ncsa.uiuc.edu
+ * March 28, 2002
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static H5B_ins_t
+H5D_btree_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key /*in,out */ ,
+ hbool_t *lt_key_changed /*out */ ,
+ void UNUSED * _udata /*in,out */ ,
+ void UNUSED * _rt_key /*in,out */ ,
+ hbool_t *rt_key_changed /*out */ )
+{
+ H5D_btree_key_t *lt_key = (H5D_btree_key_t *)_lt_key;
+ H5B_ins_t ret_value=H5B_INS_REMOVE; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_btree_remove)
+
+ /* Remove raw data chunk from file */
+ H5_CHECK_OVERFLOW(lt_key->nbytes, uint32_t, hsize_t);
+ if(H5MF_xfree(f, H5FD_MEM_DRAW, dxpl_id, addr, (hsize_t)lt_key->nbytes) < 0)
+ HGOTO_ERROR(H5E_STORAGE, H5E_CANTFREE, H5B_INS_ERROR, "unable to free chunk")
+
+ /* Mark keys as unchanged */
+ *lt_key_changed = FALSE;
+ *rt_key_changed = FALSE;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_btree_remove() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_btree_decode_key
+ *
+ * Purpose: Decodes a raw key into a native key for the B-tree
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * Friday, October 10, 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_btree_decode_key(const H5F_t UNUSED *f, const H5B_t *bt, const uint8_t *raw, void *_key)
+{
+ H5D_btree_key_t *key = (H5D_btree_key_t *) _key;
+ H5B_shared_t *shared; /* Pointer to shared B-tree info */
+ size_t ndims;
+ unsigned u;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_btree_decode_key)
+
+ /* check args */
+ HDassert(f);
+ HDassert(bt);
+ shared = (H5B_shared_t *)H5RC_GET_OBJ(bt->rc_shared);
+ HDassert(shared);
+ HDassert(raw);
+ HDassert(key);
+ ndims = H5D_BTREE_NDIMS(shared);
+ HDassert(ndims <= H5O_LAYOUT_NDIMS);
+
+ /* decode */
+ UINT32DECODE(raw, key->nbytes);
+ UINT32DECODE(raw, key->filter_mask);
+ for(u = 0; u < ndims; u++)
+ UINT64DECODE(raw, key->offset[u]);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5D_btree_decode_key() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_btree_encode_key
+ *
+ * Purpose: Encode a key from native format to raw format.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * Friday, October 10, 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_btree_encode_key(const H5F_t UNUSED *f, const H5B_t *bt, uint8_t *raw, void *_key)
+{
+ H5D_btree_key_t *key = (H5D_btree_key_t *) _key;
+ H5B_shared_t *shared; /* Pointer to shared B-tree info */
+ size_t ndims;
+ unsigned u;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_btree_encode_key)
+
+ /* check args */
+ HDassert(f);
+ HDassert(bt);
+ shared = (H5B_shared_t *)H5RC_GET_OBJ(bt->rc_shared);
+ HDassert(shared);
+ HDassert(raw);
+ HDassert(key);
+ ndims = H5D_BTREE_NDIMS(shared);
+ HDassert(ndims <= H5O_LAYOUT_NDIMS);
+
+ /* encode */
+ UINT32ENCODE(raw, key->nbytes);
+ UINT32ENCODE(raw, key->filter_mask);
+ for(u = 0; u < ndims; u++)
+ UINT64ENCODE(raw, key->offset[u]);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5D_btree_encode_key() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_btree_debug_key
+ *
+ * Purpose: Prints a key.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * Thursday, April 16, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static herr_t
+H5D_btree_debug_key(FILE *stream, H5F_t UNUSED *f, hid_t UNUSED dxpl_id, int indent, int fwidth,
+ const void *_key, const void *_udata)
+{
+ const H5D_btree_key_t *key = (const H5D_btree_key_t *)_key;
+ const H5D_btree_ud0_t *udata = (const H5D_btree_ud0_t *)_udata;
+ unsigned u;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_btree_debug_key)
+
+ HDassert(key);
+
+ HDfprintf(stream, "%*s%-*s %u bytes\n", indent, "", fwidth, "Chunk size:", (unsigned)key->nbytes);
+ HDfprintf(stream, "%*s%-*s 0x%08x\n", indent, "", fwidth, "Filter mask:", key->filter_mask);
+ HDfprintf(stream, "%*s%-*s {", indent, "", fwidth, "Logical offset:");
+ for(u = 0; u < udata->mesg->u.chunk.ndims; u++)
+ HDfprintf(stream, "%s%Hd", u?", ":"", key->offset[u]);
+ HDfputs("}\n", stream);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5D_btree_debug_key() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_btree_shared_create
+ *
+ * Purpose: Create & initialize B-tree shared info
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Monday, September 27, 2004
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_btree_shared_create(const H5F_t *f, H5O_layout_t *layout)
+{
+ H5B_shared_t *shared; /* Shared B-tree node info */
+ size_t sizeof_rkey; /* Size of raw (disk) key */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_btree_shared_create)
+
+ /* Set the raw key size */
+ sizeof_rkey = 4 + /*storage size */
+ 4 + /*filter mask */
+ layout->u.chunk.ndims * 8; /*dimension indices */
+
+ /* Allocate & initialize global info for the shared structure */
+ if(NULL == (shared = H5B_shared_new(f, H5B_BTREE, sizeof_rkey)))
+ HGOTO_ERROR(H5E_BTREE, H5E_NOSPACE, FAIL, "memory allocation failed for shared B-tree info")
+
+ /* Set up the "local" information for this dataset's chunks */
+ /* <none> */
+
+ /* Make shared B-tree info reference counted */
+ if(NULL == (layout->u.chunk.btree_shared = H5RC_create(shared, H5B_shared_free)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create ref-count wrapper for shared B-tree info")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_btree_shared_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_btree_idx_init
+ *
+ * Purpose: Initialize the indexing information for a dataset.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * Monday, May 18, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_btree_idx_init(const H5D_chk_idx_info_t *idx_info)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_btree_idx_init)
+
+ /* Check args */
+ HDassert(idx_info);
+ HDassert(idx_info->f);
+ HDassert(idx_info->layout);
+
+ /* Allocate the shared structure */
+ if(H5D_btree_shared_create(idx_info->f, idx_info->layout) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create wrapper for shared B-tree info")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_btree_idx_init() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_btree_idx_create
+ *
+ * Purpose: Creates a new indexed-storage B-tree and initializes the
+ * layout struct with information about the storage. The
+ * struct should be immediately written to the object header.
+ *
+ * This function must be called before passing LAYOUT to any of
+ * the other indexed storage functions!
+ *
+ * Return: Non-negative on success (with the LAYOUT argument initialized
+ * and ready to write to an object header). Negative on failure.
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, October 21, 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_btree_idx_create(const H5D_chk_idx_info_t *idx_info)
+{
+ H5D_btree_ud0_t udata; /* User data for B-tree callback */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_btree_idx_create)
+
+ /* Check args */
+ HDassert(idx_info);
+ HDassert(idx_info->f);
+ HDassert(idx_info->layout);
+
+ /* Initialize "user" data for B-tree callbacks, etc. */
+ udata.mesg = idx_info->layout;
+
+ /* Create the v1 B-tree for the chunk index */
+ if(H5B_create(idx_info->f, idx_info->dxpl_id, H5B_BTREE, &udata, &(idx_info->layout->u.chunk.addr)/*out*/) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't create B-tree")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_btree_idx_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_btree_idx_insert
+ *
+ * Purpose: Create the chunk it if it doesn't exist, or reallocate the
+ * chunk if its size changed.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * Thursday, May 21, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_btree_idx_insert(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_btree_idx_insert)
+
+ HDassert(idx_info);
+ HDassert(idx_info->f);
+ HDassert(idx_info->layout);
+ HDassert(udata);
+
+ /*
+ * Create the chunk it if it doesn't exist, or reallocate the chunk if
+ * its size changed.
+ */
+ if(H5B_insert(idx_info->f, idx_info->dxpl_id, H5B_BTREE, idx_info->layout->u.chunk.addr, udata) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to allocate chunk")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D_btree_idx_insert() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_btree_idx_get_addr
+ *
+ * Purpose: Get the file address of a chunk if file space has been
+ * assigned. Save the retrieved information in the udata
+ * supplied.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Albert Cheng
+ * June 27, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_btree_idx_get_addr(const H5D_chk_idx_info_t *idx_info, H5D_chunk_ud_t *udata)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_btree_idx_get_addr)
+
+ HDassert(idx_info);
+ HDassert(idx_info->f);
+ HDassert(idx_info->layout);
+ HDassert(idx_info->layout->u.chunk.ndims > 0);
+ HDassert(udata);
+
+ /* Go get the chunk information from the B-tree */
+ if(H5B_find(idx_info->f, idx_info->dxpl_id, H5B_BTREE, idx_info->layout->u.chunk.addr, udata) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk info")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D_btree_idx_get_addr() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_btree_idx_iterate_cb
+ *
+ * Purpose: Translate the B-tree specific chunk record into a generic
+ * form and make the callback to the generic chunk callback
+ * routine.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, May 20, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+H5D_btree_idx_iterate_cb(H5F_t UNUSED *f, hid_t UNUSED dxpl_id,
+ const void *_lt_key, haddr_t addr, const void UNUSED *_rt_key,
+ void *_udata)
+{
+ H5D_btree_it_ud_t *udata = (H5D_btree_it_ud_t *)_udata; /* User data */
+ const H5D_btree_key_t *lt_key = (const H5D_btree_key_t *)_lt_key; /* B-tree key for chunk */
+ H5D_chunk_rec_t chunk_rec; /* Generic chunk record for callback */
+ int ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_btree_idx_iterate_cb)
+
+ /* Sanity check for memcpy() */
+ HDcompile_assert(offsetof(H5D_chunk_rec_t, nbytes) == offsetof(H5D_btree_key_t, nbytes));
+ HDcompile_assert(sizeof(chunk_rec.nbytes) == sizeof(lt_key->nbytes));
+ HDcompile_assert(offsetof(H5D_chunk_rec_t, offset) == offsetof(H5D_btree_key_t, offset));
+ HDcompile_assert(sizeof(chunk_rec.offset) == sizeof(lt_key->offset));
+ HDcompile_assert(offsetof(H5D_chunk_rec_t, filter_mask) == offsetof(H5D_btree_key_t, filter_mask));
+ HDcompile_assert(sizeof(chunk_rec.filter_mask) == sizeof(lt_key->filter_mask));
+
+ /* Compose generic chunk record for callback */
+ HDmemcpy(&chunk_rec, lt_key, sizeof(*lt_key));
+ chunk_rec.chunk_addr = addr;
+
+ /* Make "generic chunk" callback */
+ if((ret_value = (udata->cb)(&chunk_rec, udata->udata)) < 0)
+ HERROR(H5E_DATASET, H5E_CALLBACK, "failure in generic chunk iterator callback");
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D_btree_idx_iterate_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_btree_idx_iterate
+ *
+ * Purpose: Iterate over the chunks in the B-tree index, making a callback
+ * for each one.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, May 20, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+H5D_btree_idx_iterate(const H5D_chk_idx_info_t *idx_info,
+ H5D_chunk_cb_func_t chunk_cb, void *chunk_udata)
+{
+ H5D_btree_it_ud_t udata; /* User data for B-tree iterator callback */
+ int ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_btree_idx_iterate)
+
+ HDassert(idx_info);
+ HDassert(idx_info->f);
+ HDassert(idx_info->layout);
+ HDassert(chunk_cb);
+ HDassert(chunk_udata);
+
+ /* Initialize userdata */
+ HDmemset(&udata, 0, sizeof udata);
+ udata.common.mesg = idx_info->layout;
+ udata.cb = chunk_cb;
+ udata.udata = chunk_udata;
+
+ /* Iterate over existing chunks */
+ if((ret_value = H5B_iterate(idx_info->f, idx_info->dxpl_id, H5B_BTREE, idx_info->layout->u.chunk.addr, H5D_btree_idx_iterate_cb, &udata)) < 0)
+ HERROR(H5E_DATASET, H5E_BADITER, "unable to iterate over chunk B-tree");
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_btree_idx_iterate() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_btree_idx_remove
+ *
+ * Purpose: Remove chunk from v1 B-tree index.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, May 22, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_btree_idx_remove(const H5D_chk_idx_info_t *idx_info, H5D_chunk_common_ud_t *udata)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_btree_idx_remove)
+
+ HDassert(idx_info);
+ HDassert(idx_info->f);
+ HDassert(idx_info->layout);
+ HDassert(udata);
+
+ /* Remove the chunk from the v1 B-tree index and release the space for the
+ * chunk (in the B-tree callback).
+ */
+ if(H5B_remove(idx_info->f, idx_info->dxpl_id, H5B_BTREE, idx_info->layout->u.chunk.addr, udata) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTDELETE, FAIL, "unable to remove chunk entry")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D_btree_idx_remove() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_btree_idx_delete
+ *
+ * Purpose: Delete v1 B-tree index and raw data storage for entire dataset
+ * (i.e. all chunks)
+ *
+ * Return: Success: Non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, March 20, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_btree_idx_delete(const H5D_chk_idx_info_t *idx_info)
+{
+ H5O_layout_t tmp_layout; /* Local copy of layout info */
+ H5D_btree_ud0_t udata; /* User data for B-tree iterator call */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_btree_idx_delete)
+
+ /* Sanity checks */
+ HDassert(idx_info);
+ HDassert(idx_info->f);
+ HDassert(idx_info->layout);
+ HDassert(H5F_addr_defined(idx_info->layout->u.chunk.addr));
+
+ /* Set up user data for B-tree deletion */
+ HDmemset(&udata, 0, sizeof udata);
+ tmp_layout = *idx_info->layout;
+ udata.mesg = &tmp_layout;
+
+ /* Set up the shared structure */
+ if(H5D_btree_shared_create(idx_info->f, &tmp_layout) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't create wrapper for shared B-tree info")
+
+ /* Delete entire B-tree */
+ if(H5B_delete(idx_info->f, idx_info->dxpl_id, H5B_BTREE, tmp_layout.u.chunk.addr, &udata) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTDELETE, FAIL, "unable to delete chunk B-tree")
+
+ /* Free the raw B-tree node buffer */
+ if(NULL == tmp_layout.u.chunk.btree_shared)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "ref-counted page nil")
+ if(H5RC_DEC(tmp_layout.u.chunk.btree_shared) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "unable to decrement ref-counted page")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_btree_idx_delete() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_btree_idx_copy_setup
+ *
+ * Purpose: Set up any necessary information for copying chunks
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, May 29, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_btree_idx_copy_setup(const H5D_chk_idx_info_t *idx_info_src,
+ const H5D_chk_idx_info_t *idx_info_dst)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_btree_idx_copy_setup)
+
+ HDassert(idx_info_src);
+ HDassert(idx_info_src->f);
+ HDassert(idx_info_src->layout);
+ HDassert(idx_info_dst);
+ HDassert(idx_info_dst->f);
+ HDassert(idx_info_dst->layout);
+ HDassert(!H5F_addr_defined(idx_info_dst->layout->u.chunk.addr));
+
+ /* Create shared B-tree info for each file */
+ if(H5D_btree_shared_create(idx_info_src->f, idx_info_src->layout) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create wrapper for source shared B-tree info")
+ if(H5D_btree_shared_create(idx_info_dst->f, idx_info_dst->layout) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create wrapper for destination shared B-tree info")
+
+ /* Create the root of the B-tree that describes chunked storage in the dest. file */
+ if(H5D_btree_idx_create(idx_info_dst) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to initialize chunked storage")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_btree_idx_copy_setup() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_btree_idx_copy_shutdown
+ *
+ * Purpose: Shutdown any information from copying chunks
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, May 29, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_btree_idx_copy_shutdown(H5O_layout_t *layout_src, H5O_layout_t *layout_dst)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_btree_idx_copy_shutdown)
+
+ HDassert(layout_src);
+ HDassert(layout_dst);
+
+ /* Decrement refcount on shared B-tree info */
+ if(H5RC_DEC(layout_src->u.chunk.btree_shared) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "unable to decrement ref-counted page")
+ if(H5RC_DEC(layout_dst->u.chunk.btree_shared) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "unable to decrement ref-counted page")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_btree_idx_copy_shutdown() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_btree_idx_size
+ *
+ * Purpose: Retrieve the amount of B-tree storage for chunked dataset
+ *
+ * Return: Success: Non-negative
+ * Failure: negative
+ *
+ * Programmer: Vailin Choi
+ * June 8, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_btree_idx_size(const H5D_chk_idx_info_t *idx_info, hsize_t *index_size)
+{
+ H5D_btree_ud0_t udata; /* User-data for loading btree nodes */
+ H5B_info_t bt_info; /* B-tree info */
+ hbool_t shared_init = FALSE; /* Whether shared B-tree info is initialized */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5D_btree_idx_size, FAIL)
+
+ /* Check args */
+ HDassert(idx_info);
+ HDassert(idx_info->f);
+ HDassert(idx_info->layout);
+ HDassert(index_size);
+
+ /* Initialize the shared info for the B-tree traversal */
+ if(H5D_btree_shared_create(idx_info->f, idx_info->layout) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create wrapper for shared B-tree info")
+ shared_init = TRUE;
+
+ /* Initialize btree node user-data */
+ HDmemset(&udata, 0, sizeof udata);
+ udata.mesg = idx_info->layout;
+
+ /* Get metadata information for B-tree */
+ if(H5B_get_info(idx_info->f, idx_info->dxpl_id, H5B_BTREE, idx_info->layout->u.chunk.addr, &bt_info, NULL, &udata) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to iterate over chunk B-tree")
+
+ /* Set the size of the B-tree */
+ *index_size = bt_info.size;
+
+done:
+ if(shared_init) {
+ if(idx_info->layout->u.chunk.btree_shared == NULL)
+ HDONE_ERROR(H5E_IO, H5E_CANTFREE, FAIL, "ref-counted page nil")
+ if(H5RC_DEC(idx_info->layout->u.chunk.btree_shared) < 0)
+ HDONE_ERROR(H5E_IO, H5E_CANTFREE, FAIL, "unable to decrement ref-counted page")
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_btree_idx_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_btree_idx_dest
+ *
+ * Purpose: Release indexing information in memory.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * Thursday, May 21, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_btree_idx_dest(const H5D_chk_idx_info_t *idx_info)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_btree_idx_dest)
+
+ HDassert(idx_info);
+ HDassert(idx_info->f);
+ HDassert(idx_info->layout);
+
+ /* Free the raw B-tree node buffer */
+ if(idx_info->layout->u.chunk.btree_shared == NULL)
+ HGOTO_ERROR(H5E_IO, H5E_CANTFREE, FAIL, "ref-counted page nil")
+ if(H5RC_DEC(idx_info->layout->u.chunk.btree_shared) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTFREE, FAIL, "unable to decrement ref-counted page")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_btree_idx_dest() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_btree_debug
+ *
+ * Purpose: Debugs a B-tree node for indexed raw data storage.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * Thursday, April 16, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_btree_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent,
+ int fwidth, unsigned ndims)
+{
+ H5D_btree_ud0_t udata; /* B-tree user data */
+ H5O_layout_t layout; /* Layout information for B-tree callback */
+ hbool_t shared_init = FALSE; /* Whether B-tree shared info is initialized */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5D_btree_debug, FAIL)
+
+ /* Set up "fake" layout info */
+ layout.u.chunk.ndims = ndims;
+
+ /* Allocate the shared structure */
+ if(H5D_btree_shared_create(f, &layout) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create wrapper for shared B-tree info")
+ shared_init = TRUE;
+
+ /* Set up B-tree user data */
+ HDmemset(&udata, 0, sizeof udata);
+ udata.mesg = &layout;
+
+ (void)H5B_debug(f, dxpl_id, addr, stream, indent, fwidth, H5B_BTREE, &udata);
+
+done:
+ if(shared_init) {
+ /* Free the raw B-tree node buffer */
+ if(layout.u.chunk.btree_shared == NULL)
+ HDONE_ERROR(H5E_IO, H5E_CANTFREE, FAIL, "ref-counted page nil")
+ if(H5RC_DEC(layout.u.chunk.btree_shared) < 0)
+ HDONE_ERROR(H5E_IO, H5E_CANTFREE, FAIL, "unable to decrement ref-counted page")
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_btree_debug() */
+
diff --git a/src/H5Dchunk.c b/src/H5Dchunk.c
new file mode 100644
index 0000000..82168a1
--- /dev/null
+++ b/src/H5Dchunk.c
@@ -0,0 +1,4504 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5D_PACKAGE /*suppress error about including H5Dpkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Dpkg.h" /* Dataset functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5FLprivate.h" /* Free Lists */
+#include "H5Iprivate.h" /* IDs */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5Vprivate.h" /* Vector and array functions */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+/* Default skip list height for storing list of chunks */
+#define H5D_CHUNK_DEFAULT_SKIPLIST_HEIGHT 8
+
+/* Macros for iterating over chunks to operate on */
+#define H5D_CHUNK_GET_FIRST_NODE(map) (map->use_single ? (H5SL_node_t *)(1) : H5SL_first(map->sel_chunks))
+#define H5D_CHUNK_GET_NODE_INFO(map, node) (map->use_single ? map->single_chunk_info : (H5D_chunk_info_t *)H5SL_item(node))
+#define H5D_CHUNK_GET_NEXT_NODE(map, node) (map->use_single ? (H5SL_node_t *)NULL : H5SL_next(node))
+
+/*
+ * Feature: If this constant is defined then every cache preemption and load
+ * causes a character to be printed on the standard error stream:
+ *
+ * `.': Entry was preempted because it has been completely read or
+ * completely written but not partially read and not partially
+ * written. This is often a good reason for preemption because such
+ * a chunk will be unlikely to be referenced in the near future.
+ *
+ * `:': Entry was preempted because it hasn't been used recently.
+ *
+ * `#': Entry was preempted because another chunk collided with it. This
+ * is usually a relatively bad thing. If there are too many of
+ * these then the number of entries in the cache can be increased.
+ *
+ * c: Entry was preempted because the file is closing.
+ *
+ * w: A chunk read operation was eliminated because the library is
+ * about to write new values to the entire chunk. This is a good
+ * thing, especially on files where the chunk size is the same as
+ * the disk block size, chunks are aligned on disk block boundaries,
+ * and the operating system can also eliminate a read operation.
+ */
+
+/*#define H5D_CHUNK_DEBUG */
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+/* Callback info for iteration to prune chunks */
+typedef struct H5D_chunk_it_ud1_t {
+ H5D_chunk_common_ud_t common; /* Common info for B-tree user data (must be first) */
+ const H5D_chk_idx_info_t *idx_info; /* Chunked index info */
+ const H5D_io_info_t *io_info; /* I/O info for dataset operation */
+ const hsize_t *dims; /* New dataset dimensions */
+ const hsize_t *down_chunks; /* "down" size of number of chunks in each dimension */
+ H5SL_t *outside; /* Skip list to hold chunks outside the new dimensions */
+ H5S_t *chunk_space; /* Dataspace for a chunk */
+ uint32_t elmts_per_chunk;/* Elements in chunk */
+ hsize_t *hyper_start; /* Starting location of hyperslab */
+ H5D_fill_buf_info_t fb_info; /* Dataset's fill buffer info */
+ hbool_t fb_info_init; /* Whether the fill value buffer has been initialized */
+} H5D_chunk_it_ud1_t;
+
+/* Skip list node for storing chunks to remove during a "prune" iteration */
+typedef struct H5D_chunk_sl_ck_t {
+ hsize_t index; /* Index of chunk to remove (must be first) */
+ H5D_chunk_rec_t rec; /* Chunk record */
+} H5D_chunk_sl_ck_t;
+
+/* Skip list callback info when destroying list & removing chunks during "prune" */
+typedef struct H5D_chunk_sl_rm_t {
+ const H5D_chk_idx_info_t *idx_info; /* I/O info for dataset operation */
+ const H5O_layout_t *mesg; /* Layout message */
+} H5D_chunk_sl_rm_t;
+
+/* Callback info for iteration to obtain chunk address and the index of the chunk for all chunks in the B-tree. */
+typedef struct H5D_chunk_id_ud2_t {
+ /* down */
+ H5D_chunk_common_ud_t common; /* Common info for B-tree user data (must be first) */
+ const hsize_t *down_chunks; /* "down chunk" element counts for chunks */
+
+ /* up */
+ haddr_t *chunk_addr; /* Array of chunk addresses to fill in */
+} H5D_chunk_it_ud2_t;
+
+/* Callback info for iteration to copy data */
+typedef struct H5D_chunk_it_ud3_t {
+ H5D_chunk_common_ud_t common; /* Common info for B-tree user data (must be first) */
+ H5F_t *file_src; /* Source file for copy */
+ H5D_chk_idx_info_t *idx_info_dst; /* Dest. chunk index info object */
+ void *buf; /* Buffer to hold chunk data for read/write */
+ void *bkg; /* Buffer for background information during type conversion */
+ size_t buf_size; /* Buffer size */
+ hbool_t do_convert; /* Whether to perform type conversions */
+
+ /* needed for converting variable-length data */
+ hid_t tid_src; /* Datatype ID for source datatype */
+ hid_t tid_dst; /* Datatype ID for destination datatype */
+ hid_t tid_mem; /* Datatype ID for memory datatype */
+ H5T_t *dt_src; /* Source datatype */
+ H5T_path_t *tpath_src_mem; /* Datatype conversion path from source file to memory */
+ H5T_path_t *tpath_mem_dst; /* Datatype conversion path from memory to dest. file */
+ void *reclaim_buf; /* Buffer for reclaiming data */
+ size_t reclaim_buf_size; /* Reclaim buffer size */
+ uint32_t nelmts; /* Number of elements in buffer */
+ H5S_t *buf_space; /* Dataspace describing buffer */
+
+ /* needed for compressed variable-length data */
+ H5O_pline_t *pline; /* Filter pipeline */
+
+ /* needed for copy object pointed by refs */
+ H5O_copy_t *cpy_info; /* Copy options */
+} H5D_chunk_it_ud3_t;
+
+/* Callback info for iteration to dump index */
+typedef struct H5D_chunk_it_ud4_t {
+ FILE *stream; /* Output stream */
+ hbool_t header_displayed; /* Node's header is displayed? */
+ unsigned ndims; /* Number of dimensions for chunk/dataset */
+} H5D_chunk_it_ud4_t;
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+/* Chunked layout operation callbacks */
+static herr_t H5D_chunk_new(H5F_t *f, hid_t dapl_id, hid_t dxpl_id, H5D_t *dset,
+ const H5P_genplist_t *dc_plist);
+static herr_t H5D_chunk_io_init(const H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info, hsize_t nelmts, const H5S_t *file_space,
+ const H5S_t *mem_space, H5D_chunk_map_t *fm);
+static herr_t H5D_chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
+ H5D_chunk_map_t *fm);
+static herr_t H5D_chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
+ H5D_chunk_map_t *fm);
+static herr_t H5D_chunk_io_term(const H5D_chunk_map_t *fm);
+
+/* "Null" layout operation callbacks */
+static ssize_t H5D_null_readvv(const H5D_io_info_t *io_info,
+ size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[],
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[]);
+
+/* Helper routines */
+static void *H5D_chunk_alloc(size_t size, const H5O_pline_t *pline);
+static void *H5D_chunk_xfree(void *chk, const H5O_pline_t *pline);
+static herr_t H5D_free_chunk_info(void *item, void *key, void *opdata);
+static herr_t H5D_create_chunk_map_single(H5D_chunk_map_t *fm,
+ const H5D_io_info_t *io_info);
+static herr_t H5D_create_chunk_file_map_hyper(H5D_chunk_map_t *fm,
+ const H5D_io_info_t *io_info);
+static herr_t H5D_create_chunk_mem_map_hyper(const H5D_chunk_map_t *fm);
+static herr_t H5D_chunk_file_cb(void *elem, hid_t type_id, unsigned ndims,
+ const hsize_t *coords, void *fm);
+static herr_t H5D_chunk_mem_cb(void *elem, hid_t type_id, unsigned ndims,
+ const hsize_t *coords, void *fm);
+
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+/* Compact storage layout I/O ops */
+const H5D_layout_ops_t H5D_LOPS_CHUNK[1] = {{
+ H5D_chunk_new,
+ H5D_chunk_io_init,
+ H5D_chunk_read,
+ H5D_chunk_write,
+#ifdef H5_HAVE_PARALLEL
+ H5D_chunk_collective_read,
+ H5D_chunk_collective_write,
+#endif /* H5_HAVE_PARALLEL */
+ NULL,
+ NULL,
+ H5D_chunk_io_term
+}};
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* "null" storage layout I/O ops */
+const H5D_layout_ops_t H5D_LOPS_NULL[1] = {{
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+#ifdef H5_HAVE_PARALLEL
+ NULL,
+ NULL,
+#endif /* H5_HAVE_PARALLEL */
+ H5D_null_readvv,
+ NULL,
+ NULL
+}};
+
+/* Declare a free list to manage the H5F_rdcc_ent_ptr_t sequence information */
+H5FL_SEQ_DEFINE_STATIC(H5D_rdcc_ent_ptr_t);
+
+/* Declare a free list to manage H5F_rdcc_ent_t objects */
+H5FL_DEFINE_STATIC(H5D_rdcc_ent_t);
+
+/* Declare a free list to manage the H5D_chunk_info_t struct */
+H5FL_DEFINE(H5D_chunk_info_t);
+
+/* Declare a free list to manage the chunk sequence information */
+H5FL_BLK_DEFINE_STATIC(chunk);
+
+/* Declare a free list to manage H5D_chunk_sl_ck_t objects */
+H5FL_DEFINE_STATIC(H5D_chunk_sl_ck_t);
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_new
+ *
+ * Purpose: Constructs new chunked layout information for dataset
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, May 22, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_chunk_new(H5F_t *f, hid_t dapl_id, hid_t dxpl_id, H5D_t *dset,
+ const H5P_genplist_t *dc_plist)
+{
+ const H5T_t *type = dset->shared->type; /* Convenience pointer to dataset's datatype */
+ hsize_t max_dim[H5O_LAYOUT_NDIMS]; /* Maximum size of data in elements */
+ uint64_t chunk_size; /* Size of chunk in bytes */
+ unsigned chunk_ndims = 0; /* Dimensionality of chunk */
+ int ndims; /* Rank of dataspace */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_new)
+
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(dset);
+ HDassert(dc_plist);
+
+ /* Retrieve rank of chunks from property list */
+ if(H5P_get(dc_plist, H5D_CRT_CHUNK_DIM_NAME, &chunk_ndims) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve chunk dimensions")
+
+ /* Set up layout information */
+ if((ndims = H5S_GET_EXTENT_NDIMS(dset->shared->space)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to get rank")
+ dset->shared->layout.u.chunk.ndims = (unsigned)ndims + 1;
+ HDassert((unsigned)(dset->shared->layout.u.chunk.ndims) <= NELMTS(dset->shared->layout.u.chunk.dim));
+
+ /* Initialize to no address */
+ dset->shared->layout.u.chunk.addr = HADDR_UNDEF;
+
+ /*
+ * Chunked storage allows any type of data space extension, so we
+ * don't even bother checking.
+ */
+ if(chunk_ndims != (unsigned)ndims)
+ HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "dimensionality of chunks doesn't match the data space")
+ if(dset->shared->dcpl_cache.efl.nused > 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "external storage not supported with chunked layout")
+
+ /*
+ * The chunk size of a dimension with a fixed size cannot exceed
+ * the maximum dimension size
+ */
+ if(H5P_get(dc_plist, H5D_CRT_CHUNK_SIZE_NAME, dset->shared->layout.u.chunk.dim) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't retrieve chunk size")
+ dset->shared->layout.u.chunk.dim[dset->shared->layout.u.chunk.ndims - 1] = H5T_GET_SIZE(type);
+
+ /* Sanity check dimensions */
+ if(H5S_get_simple_extent_dims(dset->shared->space, NULL, max_dim) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to query maximum dimensions")
+ for(u = 0; u < dset->shared->layout.u.chunk.ndims - 1; u++)
+ if(max_dim[u] != H5S_UNLIMITED && max_dim[u] < dset->shared->layout.u.chunk.dim[u])
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "chunk size must be <= maximum dimension size for fixed-sized dimensions")
+
+ /* Compute the total size of a chunk */
+ /* (Use 64-bit value to ensure that we can detect >4GB chunks) */
+ for(u = 1, chunk_size = (uint64_t)dset->shared->layout.u.chunk.dim[0]; u < dset->shared->layout.u.chunk.ndims; u++)
+ chunk_size *= (uint64_t)dset->shared->layout.u.chunk.dim[u];
+
+ /* Check for chunk larger than can be represented in 32-bits */
+ /* (Chunk size is encoded in 32-bit value in v1 B-tree records) */
+ if(chunk_size > (uint64_t)0xffffffff)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "chunk size must be < 4GB")
+
+ /* Retain computed chunk size */
+ H5_ASSIGN_OVERFLOW(dset->shared->layout.u.chunk.size, chunk_size, uint64_t, uint32_t);
+
+ /* Initialize the chunk cache for the dataset */
+ if(H5D_chunk_init(f, dapl_id, dxpl_id, dset) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize chunk cache")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_new() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_io_init
+ *
+ * Purpose: Performs initialization before any sort of I/O on the raw data
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, March 20, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_chunk_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
+ H5D_chunk_map_t *fm)
+{
+ H5D_t *dataset = io_info->dset; /* Local pointer to dataset info */
+ const H5T_t *mem_type = type_info->mem_type; /* Local pointer to memory datatype */
+ H5S_t *tmp_mspace = NULL; /* Temporary memory dataspace */
+ hssize_t old_offset[H5O_LAYOUT_NDIMS]; /* Old selection offset */
+ htri_t file_space_normalized = FALSE; /* File dataspace was normalized */
+ hid_t f_tid = (-1); /* Temporary copy of file datatype for iteration */
+ hbool_t iter_init = FALSE; /* Selection iteration info has been initialized */
+ unsigned f_ndims; /* The number of dimensions of the file's dataspace */
+ int sm_ndims; /* The number of dimensions of the memory buffer's dataspace (signed) */
+ H5SL_node_t *curr_node; /* Current node in skip list */
+ H5S_sel_type fsel_type; /* Selection type on disk */
+ char bogus; /* "bogus" buffer to pass to selection iterator */
+ unsigned u; /* Local index variable */
+ hbool_t sel_hyper_flag;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_io_init)
+
+ /* Get layout for dataset */
+ fm->layout = &(dataset->shared->layout);
+ fm->nelmts = nelmts;
+
+ /* Check if the memory space is scalar & make equivalent memory space */
+ if((sm_ndims = H5S_GET_EXTENT_NDIMS(mem_space)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimension number")
+ /* Set the number of dimensions for the memory dataspace */
+ H5_ASSIGN_OVERFLOW(fm->m_ndims, sm_ndims, int, unsigned);
+
+ /* Get dim number and dimensionality for each dataspace */
+ fm->f_ndims = f_ndims = dataset->shared->layout.u.chunk.ndims - 1;
+ if(H5S_get_simple_extent_dims(file_space, fm->f_dims, NULL) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality")
+
+ /* Normalize hyperslab selections by adjusting them by the offset */
+ /* (It might be worthwhile to normalize both the file and memory dataspaces
+ * before any (contiguous, chunked, etc) file I/O operation, in order to
+ * speed up hyperslab calculations by removing the extra checks and/or
+ * additions involving the offset and the hyperslab selection -QAK)
+ */
+ if((file_space_normalized = H5S_hyper_normalize_offset((H5S_t *)file_space, old_offset)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "unable to normalize dataspace by offset")
+
+ /* Decide the number of chunks in each dimension*/
+ for(u = 0; u < f_ndims; u++) {
+ /* Keep the size of the chunk dimensions as hsize_t for various routines */
+ fm->chunk_dim[u] = fm->layout->u.chunk.dim[u];
+
+ /* Round up to the next integer # of chunks, to accomodate partial chunks */
+ fm->chunks[u] = ((fm->f_dims[u] + dataset->shared->layout.u.chunk.dim[u]) - 1) / dataset->shared->layout.u.chunk.dim[u];
+ } /* end for */
+
+ /* Compute the "down" size of 'chunks' information */
+ if(H5V_array_down(f_ndims, fm->chunks, fm->down_chunks) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "can't compute 'down' sizes")
+
+#ifdef H5_HAVE_PARALLEL
+ /* Calculate total chunk in file map*/
+ fm->select_chunk = NULL;
+ fm->total_chunks = 1;
+ for(u = 0; u < fm->f_ndims; u++)
+ fm->total_chunks = fm->total_chunks * fm->chunks[u];
+ if(io_info->using_mpi_vfd) {
+ H5_CHECK_OVERFLOW(fm->total_chunks, hsize_t, size_t);
+ if(NULL == (fm->select_chunk = (H5D_chunk_info_t **)H5MM_calloc((size_t)fm->total_chunks * sizeof(H5D_chunk_info_t *))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate chunk info")
+ } /* end if */
+#endif /* H5_HAVE_PARALLEL */
+
+
+ /* Initialize "last chunk" information */
+ fm->last_index = (hsize_t)-1;
+ fm->last_chunk_info = NULL;
+
+ /* Point at the dataspaces */
+ fm->file_space = file_space;
+ fm->mem_space = mem_space;
+
+ /* Special case for only one element in selection */
+ /* (usually appending a record) */
+ if(nelmts == 1
+#ifdef H5_HAVE_PARALLEL
+ && !(io_info->using_mpi_vfd)
+#endif /* H5_HAVE_PARALLEL */
+ ) {
+ /* Initialize skip list for chunk selections */
+ fm->sel_chunks = NULL;
+ fm->use_single = TRUE;
+
+ /* Initialize single chunk dataspace */
+ if(NULL == dataset->shared->cache.chunk.single_space) {
+ /* Make a copy of the dataspace for the dataset */
+ if((dataset->shared->cache.chunk.single_space = H5S_copy(file_space, TRUE, FALSE)) == NULL)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy file space")
+
+ /* Resize chunk's dataspace dimensions to size of chunk */
+ if(H5S_set_extent_real(dataset->shared->cache.chunk.single_space, fm->chunk_dim) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't adjust chunk dimensions")
+
+ /* Set the single chunk dataspace to 'all' selection */
+ if(H5S_select_all(dataset->shared->cache.chunk.single_space, TRUE) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTSELECT, FAIL, "unable to set all selection")
+ } /* end if */
+ fm->single_space = dataset->shared->cache.chunk.single_space;
+ HDassert(fm->single_space);
+
+ /* Allocate the single chunk information */
+ if(NULL == dataset->shared->cache.chunk.single_chunk_info) {
+ if(NULL == (dataset->shared->cache.chunk.single_chunk_info = H5FL_MALLOC(H5D_chunk_info_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate chunk info")
+ } /* end if */
+ fm->single_chunk_info = dataset->shared->cache.chunk.single_chunk_info;
+ HDassert(fm->single_chunk_info);
+
+ /* Reset chunk template information */
+ fm->mchunk_tmpl = NULL;
+
+ /* Set up chunk mapping for single element */
+ if(H5D_create_chunk_map_single(fm, io_info) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create chunk selections for single element")
+ } /* end if */
+ else {
+ /* Initialize skip list for chunk selections */
+ if(NULL == dataset->shared->cache.chunk.sel_chunks) {
+ if(NULL == (dataset->shared->cache.chunk.sel_chunks = H5SL_create(H5SL_TYPE_HSIZE, 0.5, (size_t)H5D_CHUNK_DEFAULT_SKIPLIST_HEIGHT)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTCREATE, FAIL, "can't create skip list for chunk selections")
+ } /* end if */
+ fm->sel_chunks = dataset->shared->cache.chunk.sel_chunks;
+ HDassert(fm->sel_chunks);
+
+ /* We are not using single element mode */
+ fm->use_single = FALSE;
+
+ /* Get type of selection on disk & in memory */
+ if((fsel_type = H5S_GET_SELECT_TYPE(file_space)) < H5S_SEL_NONE)
+ HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "unable to get type of selection")
+ if((fm->msel_type = H5S_GET_SELECT_TYPE(mem_space)) < H5S_SEL_NONE)
+ HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "unable to get type of selection")
+
+ /* If the selection is NONE or POINTS, set the flag to FALSE */
+ if(fsel_type == H5S_SEL_POINTS || fsel_type == H5S_SEL_NONE)
+ sel_hyper_flag = FALSE;
+ else
+ sel_hyper_flag = TRUE;
+
+ /* Check if file selection is a not a hyperslab selection */
+ if(sel_hyper_flag) {
+ /* Build the file selection for each chunk */
+ if(H5D_create_chunk_file_map_hyper(fm, io_info) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file chunk selections")
+
+ /* Clean file chunks' hyperslab span "scratch" information */
+ curr_node = H5SL_first(fm->sel_chunks);
+ while(curr_node) {
+ H5D_chunk_info_t *chunk_info; /* Pointer chunk information */
+
+ /* Get pointer to chunk's information */
+ chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node);
+ HDassert(chunk_info);
+
+ /* Clean hyperslab span's "scratch" information */
+ if(H5S_hyper_reset_scratch(chunk_info->fspace) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "unable to reset span scratch info")
+
+ /* Get the next chunk node in the skip list */
+ curr_node = H5SL_next(curr_node);
+ } /* end while */
+ } /* end if */
+ else {
+ /* Create temporary datatypes for selection iteration */
+ if((f_tid = H5I_register(H5I_DATATYPE, H5T_copy(dataset->shared->type, H5T_COPY_ALL), FALSE)) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register file datatype")
+
+ /* Spaces might not be the same shape, iterate over the file selection directly */
+ if(H5S_select_iterate(&bogus, f_tid, file_space, H5D_chunk_file_cb, fm) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file chunk selections")
+
+ /* Reset "last chunk" info */
+ fm->last_index = (hsize_t)-1;
+ fm->last_chunk_info = NULL;
+ } /* end else */
+
+ /* Build the memory selection for each chunk */
+ if(sel_hyper_flag && H5S_select_shape_same(file_space, mem_space) == TRUE) {
+ /* Reset chunk template information */
+ fm->mchunk_tmpl = NULL;
+
+ /* If the selections are the same shape, use the file chunk information
+ * to generate the memory chunk information quickly.
+ */
+ if(H5D_create_chunk_mem_map_hyper(fm) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create memory chunk selections")
+ } /* end if */
+ else {
+ size_t elmt_size; /* Memory datatype size */
+
+ /* Make a copy of equivalent memory space */
+ if((tmp_mspace = H5S_copy(mem_space, TRUE, FALSE)) == NULL)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space")
+
+ /* De-select the mem space copy */
+ if(H5S_select_none(tmp_mspace) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to de-select memory space")
+
+ /* Save chunk template information */
+ fm->mchunk_tmpl = tmp_mspace;
+
+ /* Create temporary datatypes for selection iteration */
+ if(f_tid < 0) {
+ if((f_tid = H5I_register(H5I_DATATYPE, H5T_copy(dataset->shared->type, H5T_COPY_ALL), FALSE)) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register file datatype")
+ } /* end if */
+
+ /* Create selection iterator for memory selection */
+ if(0 == (elmt_size = H5T_get_size(mem_type)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_BADSIZE, FAIL, "datatype size invalid")
+ if(H5S_select_iter_init(&(fm->mem_iter), mem_space, elmt_size) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator")
+ iter_init = TRUE; /* Selection iteration info has been initialized */
+
+ /* Spaces aren't the same shape, iterate over the memory selection directly */
+ if(H5S_select_iterate(&bogus, f_tid, file_space, H5D_chunk_mem_cb, fm) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create memory chunk selections")
+
+ /* Clean up hyperslab stuff, if necessary */
+ if(fm->msel_type != H5S_SEL_POINTS) {
+ /* Clean memory chunks' hyperslab span "scratch" information */
+ curr_node = H5SL_first(fm->sel_chunks);
+ while(curr_node) {
+ H5D_chunk_info_t *chunk_info; /* Pointer chunk information */
+
+ /* Get pointer to chunk's information */
+ chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node);
+ HDassert(chunk_info);
+
+ /* Clean hyperslab span's "scratch" information */
+ if(H5S_hyper_reset_scratch(chunk_info->mspace) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "unable to reset span scratch info")
+
+ /* Get the next chunk node in the skip list */
+ curr_node = H5SL_next(curr_node);
+ } /* end while */
+ } /* end if */
+ } /* end else */
+ } /* end else */
+
+done:
+ /* Release the [potentially partially built] chunk mapping information if an error occurs */
+ if(ret_value < 0) {
+ if(tmp_mspace && !fm->mchunk_tmpl) {
+ if(H5S_close(tmp_mspace) < 0)
+ HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "can't release memory chunk dataspace template")
+ } /* end if */
+
+ if(H5D_chunk_io_term(fm) < 0)
+ HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release chunk mapping")
+ } /* end if */
+
+ /* Reset the global dataspace info */
+ fm->file_space = NULL;
+ fm->mem_space = NULL;
+
+ if(iter_init) {
+ if(H5S_SELECT_ITER_RELEASE(&(fm->mem_iter)) < 0)
+ HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator")
+ } /* end if */
+ if(f_tid!=(-1)) {
+ if(H5I_dec_ref(f_tid, FALSE) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
+ } /* end if */
+ if(file_space_normalized) {
+ /* (Casting away const OK -QAK) */
+ if(H5S_hyper_denormalize_offset((H5S_t *)file_space, old_offset) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "unable to normalize dataspace by offset")
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_io_init() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_alloc
+ *
+ * Purpose: Allocate space for a chunk in memory. This routine allocates
+ * memory space for non-filtered chunks from a block free list
+ * and uses malloc()/free() for filtered chunks.
+ *
+ * Return: Pointer to memory for chunk on success/NULL on failure
+ *
+ * Programmer: Quincey Koziol
+ * April 22, 2004
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5D_chunk_alloc(size_t size, const H5O_pline_t *pline)
+{
+ void *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_chunk_alloc)
+
+ HDassert(size);
+ HDassert(pline);
+
+ if(pline->nused > 0)
+ ret_value = H5MM_malloc(size);
+ else
+ ret_value = H5FL_BLK_MALLOC(chunk, size);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D_chunk_alloc() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_xfree
+ *
+ * Purpose: Free space for a chunk in memory. This routine allocates
+ * memory space for non-filtered chunks from a block free list
+ * and uses malloc()/free() for filtered chunks.
+ *
+ * Return: NULL (never fails)
+ *
+ * Programmer: Quincey Koziol
+ * April 22, 2004
+ *
+ *-------------------------------------------------------------------------
+ */
+static void *
+H5D_chunk_xfree(void *chk, const H5O_pline_t *pline)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_chunk_xfree)
+
+ HDassert(pline);
+
+ if(chk) {
+ if(pline->nused > 0)
+ H5MM_xfree(chk);
+ else
+ (void)H5FL_BLK_FREE(chunk, chk);
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(NULL)
+} /* H5D_chunk_xfree() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5D_free_chunk_info
+ PURPOSE
+ Internal routine to destroy a chunk info node
+ USAGE
+ void H5D_free_chunk_info(chunk_info)
+ void *chunk_info; IN: Pointer to chunk info to destroy
+ RETURNS
+ No return value
+ DESCRIPTION
+ Releases all the memory for a chunk info node. Called by H5SL_free
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static herr_t
+H5D_free_chunk_info(void *item, void UNUSED *key, void UNUSED *opdata)
+{
+ H5D_chunk_info_t *chunk_info = (H5D_chunk_info_t *)item;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_free_chunk_info)
+
+ HDassert(chunk_info);
+
+ /* Close the chunk's file dataspace, if it's not shared */
+ if(!chunk_info->fspace_shared)
+ (void)H5S_close(chunk_info->fspace);
+ else
+ H5S_select_all(chunk_info->fspace, TRUE);
+
+ /* Close the chunk's memory dataspace, if it's not shared */
+ if(!chunk_info->mspace_shared)
+ (void)H5S_close(chunk_info->mspace);
+
+ /* Free the actual chunk info */
+ (void)H5FL_FREE(H5D_chunk_info_t, chunk_info);
+
+ FUNC_LEAVE_NOAPI(0)
+} /* H5D_free_chunk_info() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_create_chunk_map_single
+ *
+ * Purpose: Create chunk selections when appending a single record
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, November 20, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_create_chunk_map_single(H5D_chunk_map_t *fm, const H5D_io_info_t
+#ifndef H5_HAVE_PARALLEL
+ UNUSED
+#endif /* H5_HAVE_PARALLEL */
+ *io_info)
+{
+ H5D_chunk_info_t *chunk_info; /* Chunk information to insert into skip list */
+ hsize_t sel_start[H5O_LAYOUT_NDIMS]; /* Offset of low bound of file selection */
+ hsize_t sel_end[H5O_LAYOUT_NDIMS]; /* Offset of high bound of file selection */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_create_chunk_map_single)
+
+ /* Sanity check */
+ HDassert(fm->f_ndims > 0);
+
+ /* Get coordinate for selection */
+ if(H5S_SELECT_BOUNDS(fm->file_space, sel_start, sel_end) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info")
+
+ /* Initialize the 'single chunk' file & memory chunk information */
+ chunk_info = fm->single_chunk_info;
+ chunk_info->chunk_points = 1;
+
+ /* Set chunk location & hyperslab size */
+ for(u = 0; u < fm->f_ndims; u++) {
+ HDassert(sel_start[u] == sel_end[u]);
+ chunk_info->coords[u] = (sel_start[u] / fm->layout->u.chunk.dim[u]) * fm->layout->u.chunk.dim[u];
+ } /* end for */
+ chunk_info->coords[fm->f_ndims] = 0;
+
+ /* Calculate the index of this chunk */
+ if(H5V_chunk_index(fm->f_ndims, chunk_info->coords, fm->layout->u.chunk.dim, fm->down_chunks, &chunk_info->index) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index")
+
+ /* Copy selection for file's dataspace into chunk dataspace */
+ if(H5S_select_copy(fm->single_space, fm->file_space, FALSE) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy file selection")
+
+ /* Move selection back to have correct offset in chunk */
+ if(H5S_SELECT_ADJUST_U(fm->single_space, chunk_info->coords) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't adjust chunk selection")
+
+#ifdef H5_HAVE_PARALLEL
+ /* store chunk selection information */
+ if(io_info->using_mpi_vfd)
+ fm->select_chunk[chunk_info->index] = chunk_info;
+#endif /* H5_HAVE_PARALLEL */
+
+ /* Set the file dataspace for the chunk to the shared 'single' dataspace */
+ chunk_info->fspace = fm->single_space;
+
+ /* Indicate that the chunk's file dataspace is shared */
+ chunk_info->fspace_shared = TRUE;
+
+ /* Just point at the memory dataspace & selection */
+ /* (Casting away const OK -QAK) */
+ chunk_info->mspace = (H5S_t *)fm->mem_space;
+
+ /* Indicate that the chunk's memory dataspace is shared */
+ chunk_info->mspace_shared = TRUE;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_create_chunk_map_single() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_create_chunk_file_map_hyper
+ *
+ * Purpose: Create all chunk selections in file.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, May 29, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_create_chunk_file_map_hyper(H5D_chunk_map_t *fm, const H5D_io_info_t
+#ifndef H5_HAVE_PARALLEL
+ UNUSED
+#endif /* H5_HAVE_PARALLEL */
+ *io_info)
+{
+ hsize_t sel_start[H5O_LAYOUT_NDIMS]; /* Offset of low bound of file selection */
+ hsize_t sel_end[H5O_LAYOUT_NDIMS]; /* Offset of high bound of file selection */
+ hsize_t sel_points; /* Number of elements in file selection */
+ hsize_t start_coords[H5O_LAYOUT_NDIMS]; /* Starting coordinates of selection */
+ hsize_t coords[H5O_LAYOUT_NDIMS]; /* Current coordinates of chunk */
+ hsize_t end[H5O_LAYOUT_NDIMS]; /* Current coordinates of chunk */
+ hsize_t chunk_index; /* Index of chunk */
+ int curr_dim; /* Current dimension to increment */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_create_chunk_file_map_hyper)
+
+ /* Sanity check */
+ assert(fm->f_ndims>0);
+
+ /* Get number of elements selected in file */
+ sel_points = fm->nelmts;
+
+ /* Get bounding box for selection (to reduce the number of chunks to iterate over) */
+ if(H5S_SELECT_BOUNDS(fm->file_space, sel_start, sel_end) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info")
+
+ /* Set initial chunk location & hyperslab size */
+ for(u = 0; u < fm->f_ndims; u++) {
+ start_coords[u] = (sel_start[u] / fm->layout->u.chunk.dim[u]) * fm->layout->u.chunk.dim[u];
+ coords[u] = start_coords[u];
+ end[u] = (coords[u] + fm->chunk_dim[u]) - 1;
+ } /* end for */
+
+
+ /* Calculate the index of this chunk */
+ if(H5V_chunk_index(fm->f_ndims, coords, fm->layout->u.chunk.dim, fm->down_chunks, &chunk_index) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index")
+
+ /* Iterate through each chunk in the dataset */
+ while(sel_points) {
+ /* Check for intersection of temporary chunk and file selection */
+ /* (Casting away const OK - QAK) */
+ if(TRUE == H5S_hyper_intersect_block((H5S_t *)fm->file_space, coords, end)) {
+ H5S_t *tmp_fchunk; /* Temporary file dataspace */
+ H5D_chunk_info_t *new_chunk_info; /* chunk information to insert into skip list */
+ hssize_t schunk_points; /* Number of elements in chunk selection */
+
+ /* Create "temporary" chunk for selection operations (copy file space) */
+ if(NULL == (tmp_fchunk = H5S_copy(fm->file_space, TRUE, FALSE)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space")
+
+ /* Make certain selections are stored in span tree form (not "optimized hyperslab" or "all") */
+ if(H5S_hyper_convert(tmp_fchunk) < 0) {
+ (void)H5S_close(tmp_fchunk);
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to convert selection to span trees")
+ } /* end if */
+
+ /* "AND" temporary chunk and current chunk */
+ if(H5S_select_hyperslab(tmp_fchunk,H5S_SELECT_AND,coords,NULL,fm->chunk_dim,NULL) < 0) {
+ (void)H5S_close(tmp_fchunk);
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't create chunk selection")
+ } /* end if */
+
+ /* Resize chunk's dataspace dimensions to size of chunk */
+ if(H5S_set_extent_real(tmp_fchunk,fm->chunk_dim) < 0) {
+ (void)H5S_close(tmp_fchunk);
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't adjust chunk dimensions")
+ } /* end if */
+
+ /* Move selection back to have correct offset in chunk */
+ if(H5S_SELECT_ADJUST_U(tmp_fchunk, coords) < 0) {
+ (void)H5S_close(tmp_fchunk);
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't adjust chunk selection")
+ } /* end if */
+
+ /* Add temporary chunk to the list of chunks */
+
+ /* Allocate the file & memory chunk information */
+ if (NULL==(new_chunk_info = H5FL_MALLOC (H5D_chunk_info_t))) {
+ (void)H5S_close(tmp_fchunk);
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate chunk info")
+ } /* end if */
+
+ /* Initialize the chunk information */
+
+ /* Set the chunk index */
+ new_chunk_info->index=chunk_index;
+
+#ifdef H5_HAVE_PARALLEL
+ /* store chunk selection information */
+ if(io_info->using_mpi_vfd)
+ fm->select_chunk[chunk_index] = new_chunk_info;
+#endif /* H5_HAVE_PARALLEL */
+
+ /* Set the file chunk dataspace */
+ new_chunk_info->fspace = tmp_fchunk;
+ new_chunk_info->fspace_shared = FALSE;
+
+ /* Set the memory chunk dataspace */
+ new_chunk_info->mspace=NULL;
+ new_chunk_info->mspace_shared = FALSE;
+
+ /* Copy the chunk's coordinates */
+ for(u=0; u<fm->f_ndims; u++)
+ new_chunk_info->coords[u]=coords[u];
+ new_chunk_info->coords[fm->f_ndims]=0;
+
+ /* Insert the new chunk into the skip list */
+ if(H5SL_insert(fm->sel_chunks, new_chunk_info, &new_chunk_info->index) < 0) {
+ H5D_free_chunk_info(new_chunk_info, NULL, NULL);
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert chunk into skip list")
+ } /* end if */
+
+ /* Get number of elements selected in chunk */
+ if((schunk_points = H5S_GET_SELECT_NPOINTS(tmp_fchunk)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection # of elements")
+ H5_ASSIGN_OVERFLOW(new_chunk_info->chunk_points, schunk_points, hssize_t, uint32_t);
+
+ /* Decrement # of points left in file selection */
+ sel_points -= (hsize_t)schunk_points;
+
+ /* Leave if we are done */
+ if(sel_points == 0)
+ HGOTO_DONE(SUCCEED)
+ } /* end if */
+
+ /* Increment chunk index */
+ chunk_index++;
+
+ /* Set current increment dimension */
+ curr_dim=(int)fm->f_ndims-1;
+
+ /* Increment chunk location in fastest changing dimension */
+ H5_CHECK_OVERFLOW(fm->chunk_dim[curr_dim],hsize_t,hssize_t);
+ coords[curr_dim]+=fm->chunk_dim[curr_dim];
+ end[curr_dim]+=fm->chunk_dim[curr_dim];
+
+ /* Bring chunk location back into bounds, if necessary */
+ if(coords[curr_dim]>sel_end[curr_dim]) {
+ do {
+ /* Reset current dimension's location to 0 */
+ coords[curr_dim]=start_coords[curr_dim]; /*lint !e771 The start_coords will always be initialized */
+ end[curr_dim]=(coords[curr_dim]+(hssize_t)fm->chunk_dim[curr_dim])-1;
+
+ /* Decrement current dimension */
+ curr_dim--;
+
+ /* Increment chunk location in current dimension */
+ coords[curr_dim]+=fm->chunk_dim[curr_dim];
+ end[curr_dim]=(coords[curr_dim]+fm->chunk_dim[curr_dim])-1;
+ } while(coords[curr_dim]>sel_end[curr_dim]);
+
+ /* Re-Calculate the index of this chunk */
+ if(H5V_chunk_index(fm->f_ndims, coords, fm->layout->u.chunk.dim, fm->down_chunks, &chunk_index) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index")
+ } /* end if */
+ } /* end while */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_create_chunk_file_map_hyper() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_create_chunk_mem_map_hyper
+ *
+ * Purpose: Create all chunk selections in memory by copying the file
+ * chunk selections and adjusting their offsets to be correct
+ * for the memory.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, May 29, 2003
+ *
+ * Assumptions: That the file and memory selections are the same shape.
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_create_chunk_mem_map_hyper(const H5D_chunk_map_t *fm)
+{
+ H5SL_node_t *curr_node; /* Current node in skip list */
+ hsize_t file_sel_start[H5O_LAYOUT_NDIMS]; /* Offset of low bound of file selection */
+ hsize_t file_sel_end[H5O_LAYOUT_NDIMS]; /* Offset of high bound of file selection */
+ hsize_t mem_sel_start[H5O_LAYOUT_NDIMS]; /* Offset of low bound of file selection */
+ hsize_t mem_sel_end[H5O_LAYOUT_NDIMS]; /* Offset of high bound of file selection */
+ hssize_t adjust[H5O_LAYOUT_NDIMS]; /* Adjustment to make to all file chunks */
+ hssize_t chunk_adjust[H5O_LAYOUT_NDIMS]; /* Adjustment to make to a particular chunk */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_create_chunk_mem_map_hyper)
+
+ /* Sanity check */
+ assert(fm->f_ndims>0);
+
+ /* Check for all I/O going to a single chunk */
+ if(H5SL_count(fm->sel_chunks)==1) {
+ H5D_chunk_info_t *chunk_info; /* Pointer to chunk information */
+
+ /* Get the node */
+ curr_node=H5SL_first(fm->sel_chunks);
+
+ /* Get pointer to chunk's information */
+ chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node);
+ assert(chunk_info);
+
+ /* Just point at the memory dataspace & selection */
+ /* (Casting away const OK -QAK) */
+ chunk_info->mspace = (H5S_t *)fm->mem_space;
+
+ /* Indicate that the chunk's memory space is shared */
+ chunk_info->mspace_shared = TRUE;
+ } /* end if */
+ else {
+ /* Get bounding box for file selection */
+ if(H5S_SELECT_BOUNDS(fm->file_space, file_sel_start, file_sel_end) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info")
+
+ /* Get bounding box for memory selection */
+ if(H5S_SELECT_BOUNDS(fm->mem_space, mem_sel_start, mem_sel_end) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info")
+
+ /* Calculate the adjustment for memory selection from file selection */
+ assert(fm->m_ndims==fm->f_ndims);
+ for(u=0; u<fm->f_ndims; u++) {
+ H5_CHECK_OVERFLOW(file_sel_start[u],hsize_t,hssize_t);
+ H5_CHECK_OVERFLOW(mem_sel_start[u],hsize_t,hssize_t);
+ adjust[u]=(hssize_t)file_sel_start[u]-(hssize_t)mem_sel_start[u];
+ } /* end for */
+
+ /* Iterate over each chunk in the chunk list */
+ curr_node=H5SL_first(fm->sel_chunks);
+ while(curr_node) {
+ H5D_chunk_info_t *chunk_info; /* Pointer to chunk information */
+
+ /* Get pointer to chunk's information */
+ chunk_info = (H5D_chunk_info_t *)H5SL_item(curr_node);
+ assert(chunk_info);
+
+ /* Copy the information */
+
+ /* Copy the memory dataspace */
+ if((chunk_info->mspace = H5S_copy(fm->mem_space, TRUE, FALSE)) == NULL)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space")
+
+ /* Release the current selection */
+ if(H5S_SELECT_RELEASE(chunk_info->mspace) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection")
+
+ /* Copy the file chunk's selection */
+ if(H5S_select_copy(chunk_info->mspace,chunk_info->fspace,FALSE) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy selection")
+
+ /* Compensate for the chunk offset */
+ for(u=0; u<fm->f_ndims; u++) {
+ H5_CHECK_OVERFLOW(chunk_info->coords[u],hsize_t,hssize_t);
+ chunk_adjust[u]=adjust[u]-(hssize_t)chunk_info->coords[u]; /*lint !e771 The adjust array will always be initialized */
+ } /* end for */
+
+ /* Adjust the selection */
+ if(H5S_hyper_adjust_s(chunk_info->mspace,chunk_adjust) < 0) /*lint !e772 The chunk_adjust array will always be initialized */
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't adjust chunk selection")
+
+ /* Get the next chunk node in the skip list */
+ curr_node=H5SL_next(curr_node);
+ } /* end while */
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_create_chunk_mem_map_hyper() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_file_cb
+ *
+ * Purpose: Callback routine for file selection iterator. Used when
+ * creating selections in file for each point selected.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Wednesday, July 23, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_chunk_file_cb(void UNUSED *elem, hid_t UNUSED type_id, unsigned ndims, const hsize_t *coords, void *_fm)
+{
+ H5D_chunk_map_t *fm = (H5D_chunk_map_t *)_fm; /* File<->memory chunk mapping info */
+ H5D_chunk_info_t *chunk_info; /* Chunk information for current chunk */
+ hsize_t coords_in_chunk[H5O_LAYOUT_NDIMS]; /* Coordinates of element in chunk */
+ hsize_t chunk_index; /* Chunk index */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_file_cb)
+
+ /* Calculate the index of this chunk */
+ if(H5V_chunk_index(ndims, coords, fm->layout->u.chunk.dim, fm->down_chunks, &chunk_index) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index")
+
+ /* Find correct chunk in file & memory skip list */
+ if(chunk_index==fm->last_index) {
+ /* If the chunk index is the same as the last chunk index we used,
+ * get the cached info to operate on.
+ */
+ chunk_info=fm->last_chunk_info;
+ } /* end if */
+ else {
+ /* If the chunk index is not the same as the last chunk index we used,
+ * find the chunk in the skip list.
+ */
+ /* Get the chunk node from the skip list */
+ if(NULL == (chunk_info = (H5D_chunk_info_t *)H5SL_search(fm->sel_chunks, &chunk_index))) {
+ H5S_t *fspace; /* Memory chunk's dataspace */
+
+ /* Allocate the file & memory chunk information */
+ if (NULL==(chunk_info = H5FL_MALLOC (H5D_chunk_info_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate chunk info")
+
+ /* Initialize the chunk information */
+
+ /* Set the chunk index */
+ chunk_info->index=chunk_index;
+
+ /* Create a dataspace for the chunk */
+ if((fspace = H5S_create_simple(fm->f_ndims,fm->chunk_dim,NULL))==NULL) {
+ (void)H5FL_FREE(H5D_chunk_info_t,chunk_info);
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "unable to create dataspace for chunk")
+ } /* end if */
+
+ /* De-select the chunk space */
+ if(H5S_select_none(fspace) < 0) {
+ (void)H5S_close(fspace);
+ (void)H5FL_FREE(H5D_chunk_info_t,chunk_info);
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to de-select dataspace")
+ } /* end if */
+
+ /* Set the file chunk dataspace */
+ chunk_info->fspace = fspace;
+ chunk_info->fspace_shared = FALSE;
+
+ /* Set the memory chunk dataspace */
+ chunk_info->mspace = NULL;
+ chunk_info->mspace_shared = FALSE;
+
+ /* Set the number of selected elements in chunk to zero */
+ chunk_info->chunk_points = 0;
+
+ /* Compute the chunk's coordinates */
+ for(u = 0; u < fm->f_ndims; u++) {
+ H5_CHECK_OVERFLOW(fm->layout->u.chunk.dim[u], hsize_t, hssize_t);
+ chunk_info->coords[u] = (coords[u] / (hssize_t)fm->layout->u.chunk.dim[u]) * (hssize_t)fm->layout->u.chunk.dim[u];
+ } /* end for */
+ chunk_info->coords[fm->f_ndims] = 0;
+
+ /* Insert the new chunk into the skip list */
+ if(H5SL_insert(fm->sel_chunks,chunk_info,&chunk_info->index) < 0) {
+ H5D_free_chunk_info(chunk_info,NULL,NULL);
+ HGOTO_ERROR(H5E_DATASPACE,H5E_CANTINSERT,FAIL,"can't insert chunk into skip list")
+ } /* end if */
+ } /* end if */
+
+ /* Update the "last chunk seen" information */
+ fm->last_index=chunk_index;
+ fm->last_chunk_info=chunk_info;
+ } /* end else */
+
+ /* Get the coordinates of the element in the chunk */
+ for(u = 0; u < fm->f_ndims; u++)
+ coords_in_chunk[u] = coords[u] % fm->layout->u.chunk.dim[u];
+
+ /* Add point to file selection for chunk */
+ if(H5S_select_elements(chunk_info->fspace, H5S_SELECT_APPEND, (size_t)1, coords_in_chunk) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "unable to select element")
+
+ /* Increment the number of elemented selected in chunk */
+ chunk_info->chunk_points++;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_file_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_mem_cb
+ *
+ * Purpose: Callback routine for file selection iterator. Used when
+ * creating selections in memory for each chunk.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Raymond Lu
+ * Thursday, April 10, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static herr_t
+H5D_chunk_mem_cb(void UNUSED *elem, hid_t UNUSED type_id, unsigned ndims, const hsize_t *coords, void *_fm)
+{
+ H5D_chunk_map_t *fm = (H5D_chunk_map_t *)_fm; /* File<->memory chunk mapping info */
+ H5D_chunk_info_t *chunk_info; /* Chunk information for current chunk */
+ hsize_t coords_in_mem[H5O_LAYOUT_NDIMS]; /* Coordinates of element in memory */
+ hsize_t chunk_index; /* Chunk index */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_mem_cb)
+
+ /* Calculate the index of this chunk */
+ if(H5V_chunk_index(ndims, coords, fm->layout->u.chunk.dim, fm->down_chunks, &chunk_index) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index")
+
+ /* Find correct chunk in file & memory skip list */
+ if(chunk_index == fm->last_index) {
+ /* If the chunk index is the same as the last chunk index we used,
+ * get the cached spaces to operate on.
+ */
+ chunk_info = fm->last_chunk_info;
+ } /* end if */
+ else {
+ /* If the chunk index is not the same as the last chunk index we used,
+ * find the chunk in the skip list.
+ */
+ /* Get the chunk node from the skip list */
+ if(NULL == (chunk_info = (H5D_chunk_info_t *)H5SL_search(fm->sel_chunks, &chunk_index)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_NOTFOUND, FAIL, "can't locate chunk in skip list")
+
+ /* Check if the chunk already has a memory space */
+ if(NULL == chunk_info->mspace) {
+ /* Copy the template memory chunk dataspace */
+ if(NULL == (chunk_info->mspace = H5S_copy(fm->mchunk_tmpl, FALSE, FALSE)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy file space")
+ } /* end else */
+
+ /* Update the "last chunk seen" information */
+ fm->last_index = chunk_index;
+ fm->last_chunk_info = chunk_info;
+ } /* end else */
+
+ /* Get coordinates of selection iterator for memory */
+ if(H5S_SELECT_ITER_COORDS(&fm->mem_iter, coords_in_mem) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get iterator coordinates")
+
+ /* Add point to memory selection for chunk */
+ if(fm->msel_type == H5S_SEL_POINTS) {
+ if(H5S_select_elements(chunk_info->mspace, H5S_SELECT_APPEND, (size_t)1, coords_in_mem) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "unable to select element")
+ } /* end if */
+ else {
+ if(H5S_hyper_add_span_element(chunk_info->mspace, fm->m_ndims, coords_in_mem) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "unable to select element")
+ } /* end else */
+
+ /* Move memory selection iterator to next element in selection */
+ if(H5S_SELECT_ITER_NEXT(&fm->mem_iter, (size_t)1) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to move to next iterator location")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_mem_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_cacheable
+ *
+ * Purpose: A small internal function to if it's possible to load the
+ * chunk into cache.
+ *
+ * Return: TRUE or FALSE
+ *
+ * Programmer: Raymond Lu
+ * 17 July 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+hbool_t
+H5D_chunk_cacheable(const H5D_io_info_t *io_info, haddr_t caddr)
+{
+ const H5D_t *dataset = io_info->dset;
+ hbool_t ret_value;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_chunk_cacheable)
+
+ HDassert(io_info);
+ HDassert(dataset);
+
+ /* Must bring the whole chunk in if there are any filters */
+ if(dataset->shared->dcpl_cache.pline.nused > 0)
+ ret_value = TRUE;
+ else {
+#ifdef H5_HAVE_PARALLEL
+ /* If MPI based VFD is used and the file is opened for write access, must
+ * bypass the chunk-cache scheme because other MPI processes could
+ * be writing to other elements in the same chunk. Do a direct
+ * write-through of only the elements requested.
+ */
+ if(io_info->using_mpi_vfd && (H5F_ACC_RDWR & H5F_INTENT(dataset->oloc.file)))
+ ret_value = FALSE;
+ else {
+#endif /* H5_HAVE_PARALLEL */
+ /* If the chunk is too large to keep in the cache and if the address
+ * for the chunk has been defined, then don't load the chunk into the
+ * cache, just write the data to it directly.
+ */
+ H5_CHECK_OVERFLOW(dataset->shared->layout.u.chunk.size, uint32_t, size_t);
+ if((size_t)dataset->shared->layout.u.chunk.size > dataset->shared->cache.chunk.nbytes
+ && H5F_addr_defined(caddr))
+ ret_value = FALSE;
+ else
+ ret_value = TRUE;
+#ifdef H5_HAVE_PARALLEL
+ } /* end else */
+#endif /* H5_HAVE_PARALLEL */
+ } /* end else */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_cacheable() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_in_cache
+ *
+ * Purpose: Check if a chunk is in the cache.
+ *
+ * Return: TRUE or FALSE
+ *
+ * Programmer: Quincey Koziol
+ * 1 April 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static hbool_t
+H5D_chunk_in_cache(const H5D_t *dset, const hsize_t *chunk_offset,
+ hsize_t chunk_idx)
+{
+ H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk);/*raw data chunk cache*/
+ hbool_t found = FALSE; /*already in cache? */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_chunk_in_cache)
+
+ /* Sanity checks */
+ HDassert(dset);
+ HDassert(chunk_offset);
+
+ /* Check if the chunk is in the cache (but hasn't been written to disk yet) */
+ if(rdcc->nslots > 0) {
+ unsigned idx = H5D_CHUNK_HASH(dset->shared, chunk_idx); /* Cache entry index */
+ H5D_rdcc_ent_t *ent = rdcc->slot[idx]; /* Cache entry */
+
+ /* Potential match... */
+ if(ent) {
+ size_t u; /* Local index variable */
+
+ for(u = 0, found = TRUE; u < dset->shared->layout.u.chunk.ndims; u++) {
+ if(chunk_offset[u] != ent->offset[u]) {
+ found = FALSE;
+ break;
+ } /* end if */
+ } /* end for */
+ } /* end if */
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(found)
+} /* end H5D_chunk_in_cache() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_read
+ *
+ * Purpose: Read from a chunked dataset.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Raymond Lu
+ * Thursday, April 10, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t UNUSED nelmts, const H5S_t UNUSED *file_space, const H5S_t UNUSED *mem_space,
+ H5D_chunk_map_t *fm)
+{
+ H5SL_node_t *chunk_node; /* Current node in chunk skip list */
+ H5D_io_info_t nul_io_info; /* "null" I/O info object */
+ H5D_io_info_t ctg_io_info; /* Contiguous I/O info object */
+ H5D_storage_t ctg_store; /* Chunk storage information as contiguous dataset */
+ H5D_io_info_t cpt_io_info; /* Compact I/O info object */
+ H5D_storage_t cpt_store; /* Chunk storage information as compact dataset */
+ hbool_t cpt_dirty; /* Temporary placeholder for compact storage "dirty" flag */
+ uint32_t src_accessed_bytes = 0; /* Total accessed size in a chunk */
+ hbool_t skip_missing_chunks = FALSE; /* Whether to skip missing chunks */
+ unsigned idx_hint = 0; /* Cache index hint */
+ herr_t ret_value = SUCCEED; /*return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_read)
+
+ /* Sanity check */
+ HDassert(io_info);
+ HDassert(io_info->u.rbuf);
+ HDassert(type_info);
+ HDassert(fm);
+
+ /* Set up "null" I/O info object */
+ HDmemcpy(&nul_io_info, io_info, sizeof(nul_io_info));
+ nul_io_info.layout_ops = *H5D_LOPS_NULL;
+
+ /* Set up contiguous I/O info object */
+ HDmemcpy(&ctg_io_info, io_info, sizeof(ctg_io_info));
+ ctg_io_info.store = &ctg_store;
+ ctg_io_info.layout_ops = *H5D_LOPS_CONTIG;
+
+ /* Initialize temporary contiguous storage info */
+ H5_ASSIGN_OVERFLOW(ctg_store.contig.dset_size, io_info->dset->shared->layout.u.chunk.size, uint32_t, hsize_t);
+
+ /* Set up compact I/O info object */
+ HDmemcpy(&cpt_io_info, io_info, sizeof(cpt_io_info));
+ cpt_io_info.store = &cpt_store;
+ cpt_io_info.layout_ops = *H5D_LOPS_COMPACT;
+
+ /* Initialize temporary compact storage info */
+ cpt_store.compact.dirty = &cpt_dirty;
+
+ {
+ const H5O_fill_t *fill = &(io_info->dset->shared->dcpl_cache.fill); /* Fill value info */
+ H5D_fill_value_t fill_status; /* Fill value status */
+
+ /* Check the fill value status */
+ if(H5P_is_fill_value_defined(fill, &fill_status) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't tell if fill value defined")
+
+ /* If we are never to return fill values, or if we would return them
+ * but they aren't set, set the flag to skip missing chunks.
+ */
+ if(fill->fill_time == H5D_FILL_TIME_NEVER ||
+ (fill->fill_time == H5D_FILL_TIME_IFSET && fill_status != H5D_FILL_VALUE_USER_DEFINED))
+ skip_missing_chunks = TRUE;
+ }
+
+ /* Iterate through nodes in chunk skip list */
+ chunk_node = H5D_CHUNK_GET_FIRST_NODE(fm);
+ while(chunk_node) {
+ H5D_chunk_info_t *chunk_info; /* Chunk information */
+ H5D_io_info_t *chk_io_info; /* Pointer to I/O info object for this chunk */
+ void *chunk; /* Pointer to locked chunk buffer */
+ H5D_chunk_ud_t udata; /* B-tree pass-through */
+
+ /* Get the actual chunk information from the skip list node */
+ chunk_info = H5D_CHUNK_GET_NODE_INFO(fm, chunk_node);
+
+ /* Get the info for the chunk in the file */
+ if(H5D_chunk_get_info(io_info->dset, io_info->dxpl_id, chunk_info->coords, &udata) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address")
+
+ /* Check for non-existant chunk & skip it if appropriate */
+ if(!H5F_addr_defined(udata.addr) && !H5D_chunk_in_cache(io_info->dset, chunk_info->coords, chunk_info->index)
+ && skip_missing_chunks) {
+ /* No chunk cached */
+ chunk = NULL;
+
+ /* Point I/O info at "null" I/O info for this chunk */
+ chk_io_info = &nul_io_info;
+ } /* end if */
+ else {
+ /* Load the chunk into cache and lock it. */
+ if(H5D_chunk_cacheable(io_info, udata.addr)) {
+ /* Pass in chunk's coordinates in a union. */
+ io_info->store->chunk.offset = chunk_info->coords;
+ io_info->store->chunk.index = chunk_info->index;
+
+ /* Compute # of bytes accessed in chunk */
+ src_accessed_bytes = chunk_info->chunk_points * type_info->src_type_size;
+
+ /* Lock the chunk into the cache */
+ if(NULL == (chunk = H5D_chunk_lock(io_info, &udata, FALSE, &idx_hint)))
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk")
+
+ /* Set up the storage buffer information for this chunk */
+ cpt_store.compact.buf = chunk;
+
+ /* Point I/O info at contiguous I/O info for this chunk */
+ chk_io_info = &cpt_io_info;
+ } /* end if */
+ else {
+ /* Sanity check */
+ HDassert(H5F_addr_defined(udata.addr));
+
+ /* Set up the storage address information for this chunk */
+ ctg_store.contig.dset_addr = udata.addr;
+
+ /* No chunk cached */
+ chunk = NULL;
+
+ /* Point I/O info at temporary I/O info for this chunk */
+ chk_io_info = &ctg_io_info;
+ } /* end else */
+ } /* end else */
+
+ /* Perform the actual read operation */
+ if((io_info->io_ops.single_read)(chk_io_info, type_info,
+ (hsize_t)chunk_info->chunk_points, chunk_info->fspace, chunk_info->mspace) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "chunked read failed")
+
+ /* Release the cache lock on the chunk. */
+ if(chunk && H5D_chunk_unlock(io_info, FALSE, idx_hint, chunk, src_accessed_bytes) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk")
+
+ /* Advance to next chunk in list */
+ chunk_node = H5D_CHUNK_GET_NEXT_NODE(fm, chunk_node);
+ } /* end while */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D_chunk_read() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_write
+ *
+ * Purpose: Writes to a chunked dataset.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Raymond Lu
+ * Thursday, April 10, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t UNUSED nelmts, const H5S_t UNUSED *file_space, const H5S_t UNUSED *mem_space,
+ H5D_chunk_map_t *fm)
+{
+ H5SL_node_t *chunk_node; /* Current node in chunk skip list */
+ H5D_io_info_t ctg_io_info; /* Contiguous I/O info object */
+ H5D_storage_t ctg_store; /* Chunk storage information as contiguous dataset */
+ H5D_io_info_t cpt_io_info; /* Compact I/O info object */
+ H5D_storage_t cpt_store; /* Chunk storage information as compact dataset */
+ hbool_t cpt_dirty; /* Temporary placeholder for compact storage "dirty" flag */
+ uint32_t dst_accessed_bytes = 0; /* Total accessed size in a chunk */
+ unsigned idx_hint = 0; /* Cache index hint */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_write)
+
+ /* Sanity check */
+ HDassert(io_info);
+ HDassert(io_info->u.wbuf);
+ HDassert(type_info);
+ HDassert(fm);
+
+ /* Set up contiguous I/O info object */
+ HDmemcpy(&ctg_io_info, io_info, sizeof(ctg_io_info));
+ ctg_io_info.store = &ctg_store;
+ ctg_io_info.layout_ops = *H5D_LOPS_CONTIG;
+
+ /* Initialize temporary contiguous storage info */
+ H5_ASSIGN_OVERFLOW(ctg_store.contig.dset_size, io_info->dset->shared->layout.u.chunk.size, uint32_t, hsize_t);
+
+ /* Set up compact I/O info object */
+ HDmemcpy(&cpt_io_info, io_info, sizeof(cpt_io_info));
+ cpt_io_info.store = &cpt_store;
+ cpt_io_info.layout_ops = *H5D_LOPS_COMPACT;
+
+ /* Initialize temporary compact storage info */
+ cpt_store.compact.dirty = &cpt_dirty;
+
+ /* Iterate through nodes in chunk skip list */
+ chunk_node = H5D_CHUNK_GET_FIRST_NODE(fm);
+ while(chunk_node) {
+ H5D_chunk_info_t *chunk_info; /* Chunk information */
+ H5D_io_info_t *chk_io_info; /* Pointer to I/O info object for this chunk */
+ void *chunk; /* Pointer to locked chunk buffer */
+ H5D_chunk_ud_t udata; /* B-tree pass-through */
+
+ /* Get the actual chunk information from the skip list node */
+ chunk_info = H5D_CHUNK_GET_NODE_INFO(fm, chunk_node);
+
+ /* Load the chunk into cache. But if the whole chunk is written,
+ * simply allocate space instead of load the chunk. */
+ if(H5D_chunk_get_info(io_info->dset, io_info->dxpl_id, chunk_info->coords, &udata) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address")
+ if(H5D_chunk_cacheable(io_info, udata.addr)) {
+ hbool_t entire_chunk = TRUE; /* Whether whole chunk is selected */
+
+ /* Pass in chunk's coordinates in a union. */
+ io_info->store->chunk.offset = chunk_info->coords;
+ io_info->store->chunk.index = chunk_info->index;
+
+ /* Compute # of bytes accessed in chunk */
+ dst_accessed_bytes = chunk_info->chunk_points * type_info->dst_type_size;
+
+ /* Determine if we will access all the data in the chunk */
+ if(dst_accessed_bytes != ctg_store.contig.dset_size ||
+ (chunk_info->chunk_points * type_info->src_type_size) != ctg_store.contig.dset_size)
+ entire_chunk = FALSE;
+
+ /* Lock the chunk into the cache */
+ if(NULL == (chunk = H5D_chunk_lock(io_info, &udata, entire_chunk, &idx_hint)))
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk")
+
+ /* Set up the storage buffer information for this chunk */
+ cpt_store.compact.buf = chunk;
+
+ /* Point I/O info at main I/O info for this chunk */
+ chk_io_info = &cpt_io_info;
+ } /* end if */
+ else {
+ /* Sanity check */
+ HDassert(H5F_addr_defined(udata.addr));
+
+ /* Set up the storage address information for this chunk */
+ ctg_store.contig.dset_addr = udata.addr;
+
+ /* No chunk cached */
+ chunk = NULL;
+
+ /* Point I/O info at temporary I/O info for this chunk */
+ chk_io_info = &ctg_io_info;
+ } /* end else */
+
+ /* Perform the actual write operation */
+ if((io_info->io_ops.single_write)(chk_io_info, type_info,
+ (hsize_t)chunk_info->chunk_points, chunk_info->fspace, chunk_info->mspace) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "chunked write failed")
+
+ /* Release the cache lock on the chunk. */
+ if(chunk && H5D_chunk_unlock(io_info, TRUE, idx_hint, chunk, dst_accessed_bytes) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk")
+
+ /* Advance to next chunk in list */
+ chunk_node = H5D_CHUNK_GET_NEXT_NODE(fm, chunk_node);
+ } /* end while */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D_chunk_write() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_io_term
+ *
+ * Purpose: Destroy I/O operation information.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Saturday, May 17, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_chunk_io_term(const H5D_chunk_map_t *fm)
+{
+ herr_t ret_value = SUCCEED; /*return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_io_term)
+
+ /* Single element I/O vs. multiple element I/O cleanup */
+ if(fm->use_single) {
+ /* Sanity checks */
+ HDassert(fm->sel_chunks == NULL);
+ HDassert(fm->single_chunk_info);
+ HDassert(fm->single_chunk_info->fspace_shared);
+ HDassert(fm->single_chunk_info->mspace_shared);
+
+ /* Reset the selection for the single element I/O */
+ H5S_select_all(fm->single_space, TRUE);
+ } /* end if */
+ else {
+ /* Release the nodes on the list of selected chunks */
+ if(fm->sel_chunks)
+ if(H5SL_free(fm->sel_chunks, H5D_free_chunk_info, NULL) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTNEXT, FAIL, "can't iterate over chunks")
+ } /* end else */
+
+ /* Free the memory chunk dataspace template */
+ if(fm->mchunk_tmpl)
+ if(H5S_close(fm->mchunk_tmpl) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "can't release memory chunk dataspace template")
+#ifdef H5_HAVE_PARALLEL
+ if(fm->select_chunk)
+ H5MM_xfree(fm->select_chunk);
+#endif /* H5_HAVE_PARALLEL */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_io_term() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_init
+ *
+ * Purpose: Initialize the raw data chunk cache for a dataset. This is
+ * called when the dataset is initialized.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * Monday, May 18, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_chunk_init(H5F_t *f, hid_t dapl_id, hid_t dxpl_id, const H5D_t *dset)
+{
+ H5D_chk_idx_info_t idx_info; /* Chunked index info */
+ H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk); /* Convenience pointer to dataset's chunk cache */
+ H5P_genplist_t *dapl; /* Data access property list object pointer */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5D_chunk_init, FAIL)
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(dset);
+
+ if(NULL == (dapl = (H5P_genplist_t *)H5I_object(dapl_id)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for fapl ID");
+
+ /* Use the properties in dapl_id if they have been set, otherwise use the properties from the file */
+ if(H5P_get(dapl, H5D_ACS_DATA_CACHE_NUM_SLOTS_NAME, &rdcc->nslots) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET,FAIL, "can't get data cache number of slots");
+ if(rdcc->nslots == H5D_CHUNK_CACHE_NSLOTS_DEFAULT)
+ rdcc->nslots = H5F_RDCC_NSLOTS(f);
+
+ if(H5P_get(dapl, H5D_ACS_DATA_CACHE_BYTE_SIZE_NAME, &rdcc->nbytes) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET,FAIL, "can't get data cache byte size");
+ if(rdcc->nbytes == H5D_CHUNK_CACHE_NBYTES_DEFAULT)
+ rdcc->nbytes = H5F_RDCC_NBYTES(f);
+
+ if(H5P_get(dapl, H5D_ACS_PREEMPT_READ_CHUNKS_NAME, &rdcc->w0) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET,FAIL, "can't get preempt read chunks");
+ if(rdcc->w0 < 0)
+ rdcc->w0 = H5F_RDCC_W0(f);
+
+ /* If nbytes or nslots is 0, set them both to 0 and avoid allocating space */
+ if(!rdcc->nbytes || !rdcc->nslots)
+ rdcc->nbytes = rdcc->nslots = 0;
+ else {
+ rdcc->slot = H5FL_SEQ_CALLOC(H5D_rdcc_ent_ptr_t, rdcc->nslots);
+ if(NULL == rdcc->slot)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Reset any cached chunk info for this dataset */
+ H5D_chunk_cinfo_cache_reset(&(rdcc->last));
+ } /* end else */
+
+ /* Compose chunked index info struct */
+ idx_info.f = f;
+ idx_info.dxpl_id = dxpl_id;
+ idx_info.layout = &dset->shared->layout;
+
+ /* Allocate any indexing structures */
+ if((dset->shared->layout.u.chunk.ops->init)(&idx_info) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize indexing information")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_init() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_cinfo_cache_reset
+ *
+ * Purpose: Reset the cached chunk info
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * November 27, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_chunk_cinfo_cache_reset(H5D_chunk_cached_t *last)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_chunk_cinfo_cache_reset)
+
+ /* Sanity check */
+ HDassert(last);
+
+ /* Indicate that the cached info is not valid */
+ last->valid = FALSE;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5D_chunk_cinfo_cache_reset() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_cinfo_cache_update
+ *
+ * Purpose: Update the cached chunk info
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * November 27, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_chunk_cinfo_cache_update(H5D_chunk_cached_t *last, const H5D_chunk_ud_t *udata)
+{
+ unsigned u; /* Local index variable */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_chunk_cinfo_cache_update)
+
+ /* Sanity check */
+ HDassert(last);
+ HDassert(udata);
+ HDassert(udata->common.mesg);
+ HDassert(udata->common.offset);
+
+ /* Stored the information to cache */
+ for(u = 0; u < udata->common.mesg->u.chunk.ndims; u++)
+ last->offset[u] = udata->common.offset[u];
+ last->nbytes = udata->nbytes;
+ last->filter_mask = udata->filter_mask;
+ last->addr = udata->addr;
+
+ /* Indicate that the cached info is valid */
+ last->valid = TRUE;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5D_chunk_cinfo_cache_update() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_cinfo_cache_found
+ *
+ * Purpose: Look for chunk info in cache
+ *
+ * Return: TRUE/FALSE/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * November 27, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static hbool_t
+H5D_chunk_cinfo_cache_found(const H5D_chunk_cached_t *last, H5D_chunk_ud_t *udata)
+{
+ hbool_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_chunk_cinfo_cache_found)
+
+ /* Sanity check */
+ HDassert(last);
+ HDassert(udata);
+ HDassert(udata->common.mesg);
+ HDassert(udata->common.offset);
+
+ /* Check if the cached information is what is desired */
+ if(last->valid) {
+ unsigned u; /* Local index variable */
+
+ /* Check that the offset is the same */
+ for(u = 0; u < udata->common.mesg->u.chunk.ndims; u++)
+ if(last->offset[u] != udata->common.offset[u])
+ HGOTO_DONE(FALSE)
+
+ /* Retrieve the information from the cache */
+ udata->nbytes = last->nbytes;
+ udata->filter_mask = last->filter_mask;
+ udata->addr = last->addr;
+
+ /* Indicate that the data was found */
+ HGOTO_DONE(TRUE)
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D_chunk_cinfo_cache_found() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_create
+ *
+ * Purpose: Creates a new chunked storage index and initializes the
+ * layout information with information about the storage. The
+ * layout info should be immediately written to the object header.
+ *
+ * Return: Non-negative on success (with the layout information initialized
+ * and ready to write to an object header). Negative on failure.
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, May 22, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_chunk_create(H5D_t *dset /*in,out*/, hid_t dxpl_id)
+{
+ H5D_chk_idx_info_t idx_info; /* Chunked index info */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5D_chunk_create, FAIL)
+
+ /* Check args */
+ HDassert(dset);
+ HDassert(H5D_CHUNKED == dset->shared->layout.type);
+ HDassert(dset->shared->layout.u.chunk.ndims > 0 && dset->shared->layout.u.chunk.ndims <= H5O_LAYOUT_NDIMS);
+#ifndef NDEBUG
+{
+ unsigned u; /* Local index variable */
+
+ for(u = 0; u < dset->shared->layout.u.chunk.ndims; u++)
+ HDassert(dset->shared->layout.u.chunk.dim[u] > 0);
+}
+#endif
+
+ /* Compose chunked index info struct */
+ idx_info.f = dset->oloc.file;
+ idx_info.dxpl_id = dxpl_id;
+ idx_info.layout = &dset->shared->layout;
+
+ /* Create the index for the chunks */
+ if((dset->shared->layout.u.chunk.ops->create)(&idx_info) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't create chunk index")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_get_info
+ *
+ * Purpose: Get the info about a chunk if file space has been
+ * assigned. Save the retrieved information in the udata
+ * supplied.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Albert Cheng
+ * June 27, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_chunk_get_info(const H5D_t *dset, hid_t dxpl_id, const hsize_t *chunk_offset,
+ H5D_chunk_ud_t *udata)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_get_info)
+
+ HDassert(dset);
+ HDassert(dset->shared->layout.u.chunk.ndims > 0);
+ HDassert(chunk_offset);
+ HDassert(udata);
+
+ /* Initialize the query information about the chunk we are looking for */
+ udata->common.mesg = &(dset->shared->layout);
+ udata->common.offset = chunk_offset;
+
+ /* Reset information about the chunk we are looking for */
+ udata->nbytes = 0;
+ udata->filter_mask = 0;
+ udata->addr = HADDR_UNDEF;
+
+ /* Check for cached information */
+ if(!H5D_chunk_cinfo_cache_found(&dset->shared->cache.chunk.last, udata)) {
+ H5D_chk_idx_info_t idx_info; /* Chunked index info */
+
+ /* Compose chunked index info struct */
+ idx_info.f = dset->oloc.file;
+ idx_info.dxpl_id = dxpl_id;
+ idx_info.layout = &dset->shared->layout;
+
+ /* Go get the chunk information */
+ if((dset->shared->layout.u.chunk.ops->get_addr)(&idx_info, udata) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't query chunk address")
+
+ /* Cache the information retrieved */
+ H5D_chunk_cinfo_cache_update(&dset->shared->cache.chunk.last, udata);
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D_chunk_get_info() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_flush_entry
+ *
+ * Purpose: Writes a chunk to disk. If RESET is non-zero then the
+ * entry is cleared -- it's slightly faster to flush a chunk if
+ * the RESET flag is turned on because it results in one fewer
+ * memory copy.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * Thursday, May 21, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_chunk_flush_entry(const H5D_t *dset, hid_t dxpl_id, const H5D_dxpl_cache_t *dxpl_cache,
+ H5D_rdcc_ent_t *ent, hbool_t reset)
+{
+ void *buf = NULL; /* Temporary buffer */
+ hbool_t point_of_no_return = FALSE;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_flush_entry)
+
+ HDassert(dset);
+ HDassert(dxpl_cache);
+ HDassert(ent);
+ HDassert(!ent->locked);
+
+ buf = ent->chunk;
+ if(ent->dirty) {
+ H5D_chunk_ud_t udata; /* pass through B-tree */
+ hbool_t must_insert = FALSE; /* Whether the chunk must go through the "insert" method */
+
+ /* Set up user data for index callbacks */
+ udata.common.mesg = &dset->shared->layout;
+ udata.common.offset = ent->offset;
+ udata.filter_mask = 0;
+ udata.nbytes = ent->chunk_size;
+ udata.addr = ent->chunk_addr;
+
+ /* Should the chunk be filtered before writing it to disk? */
+ if(dset->shared->dcpl_cache.pline.nused) {
+ size_t alloc = ent->alloc_size; /* Bytes allocated for BUF */
+ size_t nbytes; /* Chunk size (in bytes) */
+
+ if(!reset) {
+ /*
+ * Copy the chunk to a new buffer before running it through
+ * the pipeline because we'll want to save the original buffer
+ * for later.
+ */
+ H5_ASSIGN_OVERFLOW(alloc, ent->chunk_size, uint32_t, size_t);
+ if(NULL == (buf = H5MM_malloc(alloc)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for pipeline")
+ HDmemcpy(buf, ent->chunk, ent->chunk_size);
+ } /* end if */
+ else {
+ /*
+ * If we are reseting and something goes wrong after this
+ * point then it's too late to recover because we may have
+ * destroyed the original data by calling H5Z_pipeline().
+ * The only safe option is to continue with the reset
+ * even if we can't write the data to disk.
+ */
+ point_of_no_return = TRUE;
+ ent->chunk = NULL;
+ } /* end else */
+ H5_ASSIGN_OVERFLOW(nbytes, udata.nbytes, uint32_t, size_t);
+ if(H5Z_pipeline(&(dset->shared->dcpl_cache.pline), 0, &(udata.filter_mask), dxpl_cache->err_detect,
+ dxpl_cache->filter_cb, &nbytes, &alloc, &buf) < 0)
+ HGOTO_ERROR(H5E_PLINE, H5E_CANTFILTER, FAIL, "output pipeline failed")
+ H5_ASSIGN_OVERFLOW(udata.nbytes, nbytes, size_t, uint32_t);
+
+ /* Indicate that the chunk must go through 'insert' method */
+ must_insert = TRUE;
+ } /* end if */
+ else if(!H5F_addr_defined(udata.addr))
+ /* Indicate that the chunk must go through 'insert' method */
+ must_insert = TRUE;
+
+ /* Check if the chunk needs to be 'inserted' (could exist already and
+ * the 'insert' operation could resize it)
+ */
+ if(must_insert) {
+ H5D_chk_idx_info_t idx_info; /* Chunked index info */
+
+ /* Compose chunked index info struct */
+ idx_info.f = dset->oloc.file;
+ idx_info.dxpl_id = dxpl_id;
+ idx_info.layout = &dset->shared->layout;
+
+ /* Create the chunk it if it doesn't exist, or reallocate the chunk
+ * if its size changed.
+ */
+ if((dset->shared->layout.u.chunk.ops->insert)(&idx_info, &udata) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert/resize chunk")
+
+ /* Update the chunk entry's address, in case it was allocated or relocated */
+ ent->chunk_addr = udata.addr;
+ } /* end if */
+
+ /* Write the data to the file */
+ HDassert(H5F_addr_defined(udata.addr));
+ if(H5F_block_write(dset->oloc.file, H5FD_MEM_DRAW, udata.addr, udata.nbytes, dxpl_id, buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write raw data to file")
+
+ /* Cache the chunk's info, in case it's accessed again shortly */
+ H5D_chunk_cinfo_cache_update(&dset->shared->cache.chunk.last, &udata);
+
+ /* Mark cache entry as clean */
+ ent->dirty = FALSE;
+
+ /* Increment # of flushed entries */
+ dset->shared->cache.chunk.stats.nflushes++;
+ } /* end if */
+
+ /* Reset, but do not free or removed from list */
+ if(reset) {
+ point_of_no_return = FALSE;
+ if(buf == ent->chunk)
+ buf = NULL;
+ if(ent->chunk != NULL)
+ ent->chunk = (uint8_t *)H5D_chunk_xfree(ent->chunk, &(dset->shared->dcpl_cache.pline));
+ } /* end if */
+
+done:
+ /* Free the temp buffer only if it's different than the entry chunk */
+ if(buf != ent->chunk)
+ H5MM_xfree(buf);
+
+ /*
+ * If we reached the point of no return then we have no choice but to
+ * reset the entry. This can only happen if RESET is true but the
+ * output pipeline failed. Do not free the entry or remove it from the
+ * list.
+ */
+ if(ret_value < 0 && point_of_no_return) {
+ if(ent->chunk)
+ ent->chunk = (uint8_t *)H5D_chunk_xfree(ent->chunk, &(dset->shared->dcpl_cache.pline));
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_flush_entry() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_cache_evict
+ *
+ * Purpose: Preempts the specified entry from the cache, flushing it to
+ * disk if necessary.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * Thursday, May 21, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_chunk_cache_evict(const H5D_t *dset, hid_t dxpl_id, const H5D_dxpl_cache_t *dxpl_cache,
+ H5D_rdcc_ent_t *ent, hbool_t flush)
+{
+ H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk);
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_cache_evict)
+
+ HDassert(dset);
+ HDassert(dxpl_cache);
+ HDassert(ent);
+ HDassert(!ent->locked);
+ HDassert(ent->idx < rdcc->nslots);
+
+ if(flush) {
+ /* Flush */
+ if(H5D_chunk_flush_entry(dset, dxpl_id, dxpl_cache, ent, TRUE) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "cannot flush indexed storage buffer")
+ } /* end if */
+ else {
+ /* Don't flush, just free chunk */
+ if(ent->chunk != NULL)
+ ent->chunk = (uint8_t *)H5D_chunk_xfree(ent->chunk, &(dset->shared->dcpl_cache.pline));
+ } /* end else */
+
+ /* Unlink from list */
+ if(ent->prev)
+ ent->prev->next = ent->next;
+ else
+ rdcc->head = ent->next;
+ if(ent->next)
+ ent->next->prev = ent->prev;
+ else
+ rdcc->tail = ent->prev;
+ ent->prev = ent->next = NULL;
+
+ /* Remove from cache */
+ rdcc->slot[ent->idx] = NULL;
+ ent->idx = UINT_MAX;
+ rdcc->nbytes -= ent->chunk_size;
+ --rdcc->nused;
+
+ /* Free */
+ (void)H5FL_FREE(H5D_rdcc_ent_t, ent);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_cache_evict() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_cache_prune
+ *
+ * Purpose: Prune the cache by preempting some things until the cache has
+ * room for something which is SIZE bytes. Only unlocked
+ * entries are considered for preemption.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * Thursday, May 21, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_chunk_cache_prune(const H5D_t *dset, hid_t dxpl_id,
+ const H5D_dxpl_cache_t *dxpl_cache, size_t size)
+{
+ const H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk);
+ size_t total = rdcc->nbytes;
+ const int nmeth = 2; /*number of methods */
+ int w[1]; /*weighting as an interval */
+ H5D_rdcc_ent_t *p[2], *cur; /*list pointers */
+ H5D_rdcc_ent_t *n[2]; /*list next pointers */
+ int nerrors = 0; /* Accumulated error count during preemptions */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_cache_prune)
+
+ /*
+ * Preemption is accomplished by having multiple pointers (currently two)
+ * slide down the list beginning at the head. Pointer p(N+1) will start
+ * traversing the list when pointer pN reaches wN percent of the original
+ * list. In other words, preemption method N gets to consider entries in
+ * approximate least recently used order w0 percent before method N+1
+ * where 100% means tha method N will run to completion before method N+1
+ * begins. The pointers participating in the list traversal are each
+ * given a chance at preemption before any of the pointers are advanced.
+ */
+ w[0] = (int)(rdcc->nused * rdcc->w0);
+ p[0] = rdcc->head;
+ p[1] = NULL;
+
+ while((p[0] || p[1]) && (rdcc->nbytes + size) > total) {
+ int i; /* Local index variable */
+
+ /* Introduce new pointers */
+ for(i = 0; i < nmeth - 1; i++)
+ if(0 == w[i])
+ p[i + 1] = rdcc->head;
+
+ /* Compute next value for each pointer */
+ for(i = 0; i < nmeth; i++)
+ n[i] = p[i] ? p[i]->next : NULL;
+
+ /* Give each method a chance */
+ for(i = 0; i < nmeth && (rdcc->nbytes + size) > total; i++) {
+ if(0 == i && p[0] && !p[0]->locked &&
+ ((0 == p[0]->rd_count && 0 == p[0]->wr_count) ||
+ (0 == p[0]->rd_count && p[0]->chunk_size == p[0]->wr_count) ||
+ (p[0]->chunk_size == p[0]->rd_count && 0 == p[0]->wr_count))) {
+ /*
+ * Method 0: Preempt entries that have been completely written
+ * and/or completely read but not entries that are partially
+ * written or partially read.
+ */
+ cur = p[0];
+ } else if(1 == i && p[1] && !p[1]->locked) {
+ /*
+ * Method 1: Preempt the entry without regard to
+ * considerations other than being locked. This is the last
+ * resort preemption.
+ */
+ cur = p[1];
+ } else {
+ /* Nothing to preempt at this point */
+ cur = NULL;
+ }
+
+ if(cur) {
+ int j; /* Local index variable */
+
+ for(j = 0; j < nmeth; j++) {
+ if(p[j] == cur)
+ p[j] = NULL;
+ if(n[j] == cur)
+ n[j] = cur->next;
+ } /* end for */
+ if(H5D_chunk_cache_evict(dset, dxpl_id, dxpl_cache, cur, TRUE) < 0)
+ nerrors++;
+ } /* end if */
+ } /* end for */
+
+ /* Advance pointers */
+ for(i = 0; i < nmeth; i++)
+ p[i] = n[i];
+ for(i = 0; i < nmeth - 1; i++)
+ w[i] -= 1;
+ } /* end while */
+
+ if(nerrors)
+ HGOTO_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "unable to preempt one or more raw data cache entry")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_cache_prune() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_lock
+ *
+ * Purpose: Return a pointer to a dataset chunk. The pointer points
+ * directly into the chunk cache and should not be freed
+ * by the caller but will be valid until it is unlocked. The
+ * input value IDX_HINT is used to speed up cache lookups and
+ * it's output value should be given to H5F_chunk_unlock().
+ * IDX_HINT is ignored if it is out of range, and if it points
+ * to the wrong entry then we fall back to the normal search
+ * method.
+ *
+ * If RELAX is non-zero and the chunk isn't in the cache then
+ * don't try to read it from the file, but just allocate an
+ * uninitialized buffer to hold the result. This is intended
+ * for output functions that are about to overwrite the entire
+ * chunk.
+ *
+ * Return: Success: Ptr to a file chunk.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Thursday, May 21, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5D_chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata,
+ hbool_t relax, unsigned *idx_hint/*in,out*/)
+{
+ H5D_t *dset = io_info->dset; /* Local pointer to the dataset info */
+ const H5O_pline_t *pline = &(dset->shared->dcpl_cache.pline); /* I/O pipeline info */
+ const H5O_layout_t *layout = &(dset->shared->layout); /* Dataset layout */
+ const H5O_fill_t *fill = &(dset->shared->dcpl_cache.fill); /* Fill value info */
+ H5D_fill_buf_info_t fb_info; /* Dataset's fill buffer info */
+ hbool_t fb_info_init = FALSE; /* Whether the fill value buffer has been initialized */
+ H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk); /*raw data chunk cache*/
+ H5D_rdcc_ent_t *ent = NULL; /*cache entry */
+ unsigned idx = 0; /*hash index number */
+ hbool_t found = FALSE; /*already in cache? */
+ haddr_t chunk_addr = HADDR_UNDEF; /* Address of chunk on disk */
+ size_t chunk_size; /*size of a chunk */
+ void *chunk = NULL; /*the file chunk */
+ unsigned u; /*counters */
+ void *ret_value; /*return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_lock)
+
+ HDassert(io_info);
+ HDassert(io_info->dxpl_cache);
+ HDassert(io_info->store);
+ HDassert(udata);
+ HDassert(dset);
+ HDassert(TRUE == H5P_isa_class(io_info->dxpl_id, H5P_DATASET_XFER));
+
+ /* Get the chunk's size */
+ HDassert(layout->u.chunk.size > 0);
+ H5_ASSIGN_OVERFLOW(chunk_size, layout->u.chunk.size, uint32_t, size_t);
+
+ /* Search for the chunk in the cache */
+ if(rdcc->nslots > 0) {
+ idx = H5D_CHUNK_HASH(dset->shared, io_info->store->chunk.index);
+ ent = rdcc->slot[idx];
+
+ if(ent)
+ for(u = 0, found = TRUE; u < layout->u.chunk.ndims; u++)
+ if(io_info->store->chunk.offset[u] != ent->offset[u]) {
+ found = FALSE;
+ break;
+ } /* end if */
+ } /* end if */
+
+ if(found) {
+ /*
+ * Already in the cache. Count a hit.
+ */
+ rdcc->stats.nhits++;
+ } /* end if */
+ else if(relax) {
+ /*
+ * Not in the cache, but we're about to overwrite the whole thing
+ * anyway, so just allocate a buffer for it but don't initialize that
+ * buffer with the file contents. Count this as a hit instead of a
+ * miss because we saved ourselves lots of work.
+ */
+ rdcc->stats.nhits++;
+
+ if(NULL == (chunk = H5D_chunk_alloc(chunk_size, pline)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for raw data chunk")
+
+ /* In the case that some dataset functions look through this data,
+ * clear it to all 0s. */
+ HDmemset(chunk, 0, chunk_size);
+ } /* end if */
+ else {
+ /*
+ * Not in the cache. Count this as a miss if it's in the file
+ * or an init if it isn't.
+ */
+
+ /* Save the chunk address */
+ chunk_addr = udata->addr;
+
+ /* Check if the chunk exists on disk */
+ if(H5F_addr_defined(chunk_addr)) {
+ size_t chunk_alloc = 0; /*allocated chunk size */
+
+ /* Chunk size on disk isn't [likely] the same size as the final chunk
+ * size in memory, so allocate memory big enough. */
+ H5_ASSIGN_OVERFLOW(chunk_alloc, udata->nbytes, uint32_t, size_t);
+ if(NULL == (chunk = H5D_chunk_alloc(chunk_alloc, pline)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for raw data chunk")
+ if(H5F_block_read(dset->oloc.file, H5FD_MEM_DRAW, chunk_addr, chunk_alloc, io_info->dxpl_id, chunk) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, NULL, "unable to read raw data chunk")
+
+ if(pline->nused) {
+ if(H5Z_pipeline(pline, H5Z_FLAG_REVERSE, &(udata->filter_mask), io_info->dxpl_cache->err_detect,
+ io_info->dxpl_cache->filter_cb, &chunk_alloc, &chunk_alloc, &chunk) < 0)
+ HGOTO_ERROR(H5E_PLINE, H5E_CANTFILTER, NULL, "data pipeline read failed")
+ H5_ASSIGN_OVERFLOW(udata->nbytes, chunk_alloc, size_t, uint32_t);
+ } /* end if */
+
+ /* Increment # of cache misses */
+ rdcc->stats.nmisses++;
+ } /* end if */
+ else {
+ H5D_fill_value_t fill_status;
+
+#ifdef OLD_WAY
+ /* Clear the error stack from not finding the chunk on disk */
+ H5E_clear_stack(NULL);
+#endif /* OLD_WAY */
+
+ /* Chunk size on disk isn't [likely] the same size as the final chunk
+ * size in memory, so allocate memory big enough. */
+ if(NULL == (chunk = H5D_chunk_alloc(chunk_size, pline)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for raw data chunk")
+
+ if(H5P_is_fill_value_defined(fill, &fill_status) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't tell if fill value defined")
+
+ if(fill->fill_time == H5D_FILL_TIME_ALLOC ||
+ (fill->fill_time == H5D_FILL_TIME_IFSET && fill_status == H5D_FILL_VALUE_USER_DEFINED)) {
+ /*
+ * The chunk doesn't exist in the file. Replicate the fill
+ * value throughout the chunk, if the fill value is defined.
+ */
+
+ /* Initialize the fill value buffer */
+ /* (use the compact dataset storage buffer as the fill value buffer) */
+ if(H5D_fill_init(&fb_info, chunk, FALSE,
+ NULL, NULL, NULL, NULL,
+ &dset->shared->dcpl_cache.fill, dset->shared->type,
+ dset->shared->type_id, (size_t)0, chunk_size, io_info->dxpl_id) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "can't initialize fill buffer info")
+ fb_info_init = TRUE;
+
+ /* Check for VL datatype & non-default fill value */
+ if(fb_info.has_vlen_fill_type)
+ /* Fill the buffer with VL datatype fill values */
+ if(H5D_fill_refill_vl(&fb_info, fb_info.elmts_per_buf, io_info->dxpl_id) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, NULL, "can't refill fill value buffer")
+ } /* end if */
+ else
+ HDmemset(chunk, 0, chunk_size);
+
+ /* Increment # of creations */
+ rdcc->stats.ninits++;
+ } /* end else */
+ } /* end else */
+ HDassert(found || chunk_size > 0);
+
+ if(!found && rdcc->nslots > 0 && chunk_size <= rdcc->nbytes &&
+ (!ent || !ent->locked)) {
+ /*
+ * Add the chunk to the cache only if the slot is not already locked.
+ * Preempt enough things from the cache to make room.
+ */
+ if(ent) {
+ if(H5D_chunk_cache_evict(io_info->dset, io_info->dxpl_id, io_info->dxpl_cache, ent, TRUE) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTINIT, NULL, "unable to preempt chunk from cache")
+ } /* end if */
+ if(H5D_chunk_cache_prune(io_info->dset, io_info->dxpl_id, io_info->dxpl_cache, chunk_size) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTINIT, NULL, "unable to preempt chunk(s) from cache")
+
+ /* Create a new entry */
+ ent = H5FL_MALLOC(H5D_rdcc_ent_t);
+ ent->locked = 0;
+ ent->dirty = FALSE;
+ ent->chunk_addr = chunk_addr;
+ H5_ASSIGN_OVERFLOW(ent->chunk_size, chunk_size, size_t, uint32_t);
+ ent->alloc_size = chunk_size;
+ for(u = 0; u < layout->u.chunk.ndims; u++)
+ ent->offset[u] = io_info->store->chunk.offset[u];
+ H5_ASSIGN_OVERFLOW(ent->rd_count, chunk_size, size_t, uint32_t);
+ H5_ASSIGN_OVERFLOW(ent->wr_count, chunk_size, size_t, uint32_t);
+ ent->chunk = (uint8_t *)chunk;
+
+ /* Add it to the cache */
+ HDassert(NULL == rdcc->slot[idx]);
+ rdcc->slot[idx] = ent;
+ ent->idx = idx;
+ rdcc->nbytes += chunk_size;
+ rdcc->nused++;
+
+ /* Add it to the linked list */
+ ent->next = NULL;
+ if(rdcc->tail) {
+ rdcc->tail->next = ent;
+ ent->prev = rdcc->tail;
+ rdcc->tail = ent;
+ } /* end if */
+ else {
+ rdcc->head = rdcc->tail = ent;
+ ent->prev = NULL;
+ } /* end else */
+ found = TRUE;
+ } else if(!found) {
+ /*
+ * The chunk is larger than the entire cache so we don't cache it.
+ * This is the reason all those arguments have to be repeated for the
+ * unlock function.
+ */
+ ent = NULL;
+ idx = UINT_MAX;
+ } else {
+ /*
+ * The chunk is not at the beginning of the cache; move it backward
+ * by one slot. This is how we implement the LRU preemption
+ * algorithm.
+ */
+ HDassert(ent);
+ if(ent->next) {
+ if(ent->next->next)
+ ent->next->next->prev = ent;
+ else
+ rdcc->tail = ent;
+ ent->next->prev = ent->prev;
+ if(ent->prev)
+ ent->prev->next = ent->next;
+ else
+ rdcc->head = ent->next;
+ ent->prev = ent->next;
+ ent->next = ent->next->next;
+ ent->prev->next = ent;
+ } /* end if */
+ } /* end else */
+
+ /* Lock the chunk into the cache */
+ if(ent) {
+ HDassert(!ent->locked);
+ ent->locked = TRUE;
+ chunk = ent->chunk;
+ } /* end if */
+
+ if(idx_hint)
+ *idx_hint = idx;
+
+ /* Set return value */
+ ret_value = chunk;
+
+done:
+ /* Release the fill buffer info, if it's been initialized */
+ if(fb_info_init && H5D_fill_term(&fb_info) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, NULL, "Can't release fill buffer info")
+
+ /* Release the chunk allocated, on error */
+ if(!ret_value)
+ if(chunk)
+ chunk = H5D_chunk_xfree(chunk, pline);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_lock() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_unlock
+ *
+ * Purpose: Unlocks a previously locked chunk. The LAYOUT, COMP, and
+ * OFFSET arguments should be the same as for H5D_chunk_lock().
+ * The DIRTY argument should be set to non-zero if the chunk has
+ * been modified since it was locked. The IDX_HINT argument is
+ * the returned index hint from the lock operation and BUF is
+ * the return value from the lock.
+ *
+ * The NACCESSED argument should be the number of bytes accessed
+ * for reading or writing (depending on the value of DIRTY).
+ * It's only purpose is to provide additional information to the
+ * preemption policy.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * Thursday, May 21, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_chunk_unlock(const H5D_io_info_t *io_info, hbool_t dirty, unsigned idx_hint,
+ void *chunk, uint32_t naccessed)
+{
+ const H5O_layout_t *layout = &(io_info->dset->shared->layout); /* Dataset layout */
+ const H5D_rdcc_t *rdcc = &(io_info->dset->shared->cache.chunk);
+ H5D_rdcc_ent_t *ent = NULL;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_unlock)
+
+ HDassert(io_info);
+
+ if(UINT_MAX == idx_hint) {
+ /*
+ * It's not in the cache, probably because it's too big. If it's
+ * dirty then flush it to disk. In any case, free the chunk.
+ * Note: we have to copy the layout and filter messages so we
+ * don't discard the `const' qualifier.
+ */
+ if(dirty) {
+ H5D_rdcc_ent_t x;
+
+ HDmemset(&x, 0, sizeof(x));
+ x.dirty = TRUE;
+ HDmemcpy(x.offset, io_info->store->chunk.offset, layout->u.chunk.ndims * sizeof(x.offset[0]));
+ HDassert(layout->u.chunk.size > 0);
+ x.chunk_addr = HADDR_UNDEF;
+ x.chunk_size = layout->u.chunk.size;
+ H5_ASSIGN_OVERFLOW(x.alloc_size, x.chunk_size, uint32_t, size_t);
+ x.chunk = (uint8_t *)chunk;
+
+ if(H5D_chunk_flush_entry(io_info->dset, io_info->dxpl_id, io_info->dxpl_cache, &x, TRUE) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "cannot flush indexed storage buffer")
+ } /* end if */
+ else {
+ if(chunk)
+ chunk = H5D_chunk_xfree(chunk, &(io_info->dset->shared->dcpl_cache.pline));
+ } /* end else */
+ } /* end if */
+ else {
+ /* Sanity check */
+ HDassert(idx_hint < rdcc->nslots);
+ HDassert(rdcc->slot[idx_hint]);
+ HDassert(rdcc->slot[idx_hint]->chunk == chunk);
+
+ /*
+ * It's in the cache so unlock it.
+ */
+ ent = rdcc->slot[idx_hint];
+ HDassert(ent->locked);
+ if(dirty) {
+ ent->dirty = TRUE;
+ ent->wr_count -= MIN(ent->wr_count, naccessed);
+ } /* end if */
+ else
+ ent->rd_count -= MIN(ent->rd_count, naccessed);
+ ent->locked = FALSE;
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_unlock() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_flush
+ *
+ * Purpose: Writes all dirty chunks to disk and optionally preempts them
+ * from the cache.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * Thursday, May 21, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_chunk_flush(H5D_t *dset, hid_t dxpl_id, unsigned flags)
+{
+ H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */
+ H5D_dxpl_cache_t *dxpl_cache = &_dxpl_cache; /* Data transfer property cache */
+ H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk);
+ unsigned nerrors = 0;
+ H5D_rdcc_ent_t *ent, *next;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5D_chunk_flush, FAIL)
+
+ /* Fill the DXPL cache values for later use */
+ if(H5D_get_dxpl_cache(dxpl_id, &dxpl_cache) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache")
+
+ /* Loop over all entries in the chunk cache */
+ for(ent = rdcc->head; ent; ent = next) {
+ next = ent->next;
+ if((flags & H5F_FLUSH_INVALIDATE)) {
+ if(H5D_chunk_cache_evict(dset, dxpl_id, dxpl_cache, ent, TRUE) < 0)
+ nerrors++;
+ } else {
+ if(H5D_chunk_flush_entry(dset, dxpl_id, dxpl_cache, ent, FALSE) < 0)
+ nerrors++;
+ }
+ } /* end for */
+ if(nerrors)
+ HGOTO_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "unable to flush one or more raw data chunks")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_flush() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_allocated_cb
+ *
+ * Purpose: Simply counts the number of chunks for a dataset.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, April 21, 1999
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+H5D_chunk_allocated_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata)
+{
+ hsize_t *nbytes = (hsize_t *)_udata;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_chunk_allocated_cb)
+
+ *(hsize_t *)nbytes += chunk_rec->nbytes;
+
+ FUNC_LEAVE_NOAPI(H5_ITER_CONT)
+} /* H5D_chunk_allocated_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_allocated
+ *
+ * Purpose: Return the number of bytes allocated in the file for storage
+ * of raw data in the chunked dataset
+ *
+ * Return: Success: Number of bytes stored in all chunks.
+ * Failure: 0
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, May 20, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_chunk_allocated(H5D_t *dset, hid_t dxpl_id, hsize_t *nbytes)
+{
+ H5D_chk_idx_info_t idx_info; /* Chunked index info */
+ const H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk); /* Raw data chunk cache */
+ H5D_rdcc_ent_t *ent; /* Cache entry */
+ H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */
+ H5D_dxpl_cache_t *dxpl_cache = &_dxpl_cache; /* Data transfer property cache */
+ hsize_t chunk_bytes = 0; /* Number of bytes allocated for chunks */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5D_chunk_allocated, FAIL)
+
+ HDassert(dset);
+
+ /* Fill the DXPL cache values for later use */
+ if(H5D_get_dxpl_cache(dxpl_id, &dxpl_cache) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache")
+
+ /* Search for cached chunks that haven't been written out */
+ for(ent = rdcc->head; ent; ent = ent->next) {
+ /* Flush the chunk out to disk, to make certain the size is correct later */
+ if(H5D_chunk_flush_entry(dset, dxpl_id, dxpl_cache, ent, FALSE) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "cannot flush indexed storage buffer")
+ } /* end for */
+
+ /* Compose chunked index info struct */
+ idx_info.f = dset->oloc.file;
+ idx_info.dxpl_id = dxpl_id;
+ idx_info.layout = &dset->shared->layout;
+
+ /* Call the index-specific "get all the allocated chunks sizes" routine */
+ if((dset->shared->layout.u.chunk.ops->iterate)(&idx_info, H5D_chunk_allocated_cb, &chunk_bytes) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to retrieve allocated chunk information from index")
+
+ /* Set number of bytes for caller */
+ *nbytes = chunk_bytes;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_allocated() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_allocate
+ *
+ * Purpose: Allocate file space for all chunks that are not allocated yet.
+ * Return SUCCEED if all needed allocation succeed, otherwise
+ * FAIL.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Albert Cheng
+ * June 26, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_chunk_allocate(H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite)
+{
+ H5D_chk_idx_info_t idx_info; /* Chunked index info */
+ const H5D_chunk_ops_t *ops = dset->shared->layout.u.chunk.ops; /* Chunk operations */
+ hsize_t chunk_offset[H5O_LAYOUT_NDIMS]; /* Offset of current chunk */
+ size_t orig_chunk_size; /* Original size of chunk in bytes */
+ unsigned filter_mask = 0; /* Filter mask for chunks that have them */
+ const H5O_layout_t *layout = &(dset->shared->layout); /* Dataset layout */
+ const H5O_pline_t *pline = &(dset->shared->dcpl_cache.pline); /* I/O pipeline info */
+ const H5O_fill_t *fill = &(dset->shared->dcpl_cache.fill); /* Fill value info */
+ H5D_fill_value_t fill_status; /* The fill value status */
+ hbool_t should_fill = FALSE; /* Whether fill values should be written */
+ H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */
+ H5D_dxpl_cache_t *dxpl_cache = &_dxpl_cache; /* Data transfer property cache */
+#ifdef H5_HAVE_PARALLEL
+ MPI_Comm mpi_comm = MPI_COMM_NULL; /* MPI communicator for file */
+ int mpi_rank = (-1); /* This process's rank */
+ int mpi_code; /* MPI return code */
+ hbool_t blocks_written = FALSE; /* Flag to indicate that chunk was actually written */
+ hbool_t using_mpi = FALSE; /* Flag to indicate that the file is being accessed with an MPI-capable file driver */
+#endif /* H5_HAVE_PARALLEL */
+ hbool_t carry; /* Flag to indicate that chunk increment carrys to higher dimension (sorta) */
+ int space_ndims; /* Dataset's space rank */
+ hsize_t space_dim[H5O_LAYOUT_NDIMS]; /* Dataset's dataspace dimensions */
+ H5D_fill_buf_info_t fb_info; /* Dataset's fill buffer info */
+ hbool_t fb_info_init = FALSE; /* Whether the fill value buffer has been initialized */
+ hid_t data_dxpl_id; /* DXPL ID to use for raw data I/O operations */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5D_chunk_allocate, FAIL)
+
+ /* Check args */
+ HDassert(dset && H5D_CHUNKED == layout->type);
+ HDassert(layout->u.chunk.ndims > 0 && layout->u.chunk.ndims <= H5O_LAYOUT_NDIMS);
+ HDassert(H5F_addr_defined(layout->u.chunk.addr));
+ HDassert(TRUE == H5P_isa_class(dxpl_id, H5P_DATASET_XFER));
+
+ /* Retrieve the dataset dimensions */
+ if((space_ndims = H5S_get_simple_extent_dims(dset->shared->space, space_dim, NULL)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to get simple dataspace info")
+ space_dim[space_ndims] = layout->u.chunk.dim[space_ndims];
+
+#ifdef H5_HAVE_PARALLEL
+ /* Retrieve MPI parameters */
+ if(IS_H5FD_MPI(dset->oloc.file)) {
+ /* Get the MPI communicator */
+ if(MPI_COMM_NULL == (mpi_comm = H5F_mpi_get_comm(dset->oloc.file)))
+ HGOTO_ERROR(H5E_INTERNAL, H5E_MPI, FAIL, "Can't retrieve MPI communicator")
+
+ /* Get the MPI rank */
+ if((mpi_rank = H5F_mpi_get_rank(dset->oloc.file)) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_MPI, FAIL, "Can't retrieve MPI rank")
+
+ /* Set the MPI-capable file driver flag */
+ using_mpi = TRUE;
+
+ /* Use the internal "independent" DXPL */
+ data_dxpl_id = H5AC_ind_dxpl_id;
+ } /* end if */
+ else {
+#endif /* H5_HAVE_PARALLEL */
+ /* Use the DXPL we were given */
+ data_dxpl_id = dxpl_id;
+#ifdef H5_HAVE_PARALLEL
+ } /* end else */
+#endif /* H5_HAVE_PARALLEL */
+
+ /* Fill the DXPL cache values for later use */
+ if(H5D_get_dxpl_cache(data_dxpl_id, &dxpl_cache) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache")
+
+ /* Get original chunk size */
+ H5_ASSIGN_OVERFLOW(orig_chunk_size, layout->u.chunk.size, uint32_t, size_t);
+
+ /* Check the dataset's fill-value status */
+ if(H5P_is_fill_value_defined(fill, &fill_status) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't tell if fill value defined")
+
+ /* If we are filling the dataset on allocation or "if set" and
+ * the fill value _is_ set, _and_ we are not overwriting the new blocks,
+ * or if there are any pipeline filters defined,
+ * set the "should fill" flag
+ */
+ if((!full_overwrite && (fill->fill_time == H5D_FILL_TIME_ALLOC ||
+ (fill->fill_time == H5D_FILL_TIME_IFSET && fill_status == H5D_FILL_VALUE_USER_DEFINED)))
+ || pline->nused > 0)
+ should_fill = TRUE;
+
+ /* Check if fill values should be written to chunks */
+ if(should_fill) {
+ /* Initialize the fill value buffer */
+ /* (delay allocating fill buffer for VL datatypes until refilling) */
+ /* (casting away const OK - QAK) */
+ if(H5D_fill_init(&fb_info, NULL, (hbool_t)(pline->nused > 0),
+ (H5MM_allocate_t)H5D_chunk_alloc, (void *)pline,
+ (H5MM_free_t)H5D_chunk_xfree, (void *)pline,
+ &dset->shared->dcpl_cache.fill, dset->shared->type,
+ dset->shared->type_id, (size_t)0, orig_chunk_size, data_dxpl_id) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize fill buffer info")
+ fb_info_init = TRUE;
+
+ /* Check if there are filters which need to be applied to the chunk */
+ /* (only do this in advance when the chunk info can be re-used (i.e.
+ * it doesn't contain any non-default VL datatype fill values)
+ */
+ if(!fb_info.has_vlen_fill_type && pline->nused > 0) {
+ size_t buf_size = orig_chunk_size;
+
+ /* Push the chunk through the filters */
+ if(H5Z_pipeline(pline, 0, &filter_mask, dxpl_cache->err_detect, dxpl_cache->filter_cb, &orig_chunk_size, &buf_size, &fb_info.fill_buf) < 0)
+ HGOTO_ERROR(H5E_PLINE, H5E_WRITEERROR, FAIL, "output pipeline failed")
+ } /* end if */
+ } /* end if */
+
+ /* Compose chunked index info struct */
+ idx_info.f = dset->oloc.file;
+ idx_info.dxpl_id = dxpl_id;
+ idx_info.layout = &dset->shared->layout;
+
+ /* Reset the chunk offset indices */
+ HDmemset(chunk_offset, 0, (layout->u.chunk.ndims * sizeof(chunk_offset[0])));
+
+ /* Loop over all chunks */
+ carry = FALSE;
+ while(!carry) {
+ H5D_chunk_ud_t udata; /* User data for querying chunk info */
+ int i; /* Local index variable */
+
+ /* Get the chunk's info */
+ if(H5D_chunk_get_info(dset, dxpl_id, chunk_offset, &udata) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address")
+
+ /* Check if the chunk exists yet on disk */
+ if(!H5F_addr_defined(udata.addr)) {
+ const H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk); /* Raw data chunk cache */
+ H5D_rdcc_ent_t *ent; /* Cache entry */
+ hbool_t chunk_exists; /* Flag to indicate whether a chunk exists already */
+ unsigned u; /* Local index variable */
+
+ /* Didn't find the chunk on disk */
+ chunk_exists = FALSE;
+
+ /* Look for chunk in cache */
+ for(ent = rdcc->head; ent && !chunk_exists; ent = ent->next) {
+ /* Assume a match */
+ chunk_exists = TRUE;
+ for(u = 0; u < layout->u.chunk.ndims; u++)
+ if(ent->offset[u] != chunk_offset[u]) {
+ chunk_exists = FALSE; /* Reset if no match */
+ break;
+ } /* end if */
+ } /* end for */
+
+ /* Chunk wasn't in cache either, create it now */
+ if(!chunk_exists) {
+ H5D_chunk_ud_t udata; /* B-tree pass-through for creating chunk */
+ size_t chunk_size; /* Size of chunk in bytes, possibly filtered */
+
+ /* Check for VL datatype & non-default fill value */
+ if(fb_info_init && fb_info.has_vlen_fill_type) {
+ /* Sanity check */
+ HDassert(should_fill);
+
+ /* Fill the buffer with VL datatype fill values */
+ if(H5D_fill_refill_vl(&fb_info, fb_info.elmts_per_buf, data_dxpl_id) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "can't refill fill value buffer")
+
+ /* Check if there are filters which need to be applied to the chunk */
+ if(pline->nused > 0) {
+ size_t buf_size = orig_chunk_size;
+ size_t nbytes = fb_info.fill_buf_size;
+
+ /* Push the chunk through the filters */
+ if(H5Z_pipeline(pline, 0, &filter_mask, dxpl_cache->err_detect, dxpl_cache->filter_cb, &nbytes, &buf_size, &fb_info.fill_buf) < 0)
+ HGOTO_ERROR(H5E_PLINE, H5E_WRITEERROR, FAIL, "output pipeline failed")
+
+ /* Keep the number of bytes the chunk turned in to */
+ chunk_size = nbytes;
+ } /* end if */
+ else
+ H5_ASSIGN_OVERFLOW(chunk_size, layout->u.chunk.size, uint32_t, size_t);
+ } /* end if */
+ else
+ chunk_size = orig_chunk_size;
+
+ /* Initialize the chunk information */
+ udata.common.mesg = layout;
+ udata.common.offset = chunk_offset;
+ H5_ASSIGN_OVERFLOW(udata.nbytes, chunk_size, size_t, uint32_t);
+ udata.filter_mask = filter_mask;
+ udata.addr = HADDR_UNDEF;
+
+ /* Allocate the chunk with all processes */
+ if((ops->insert)(&idx_info, &udata) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert record into chunk index")
+ HDassert(H5F_addr_defined(udata.addr));
+
+ /* Check if fill values should be written to chunks */
+ if(should_fill) {
+ /* Sanity check */
+ HDassert(fb_info_init);
+ HDassert(udata.nbytes == chunk_size);
+
+#ifdef H5_HAVE_PARALLEL
+ /* Check if this file is accessed with an MPI-capable file driver */
+ if(using_mpi) {
+ /* Write the chunks out from only one process */
+ /* !! Use the internal "independent" DXPL!! -QAK */
+ if(H5_PAR_META_WRITE == mpi_rank)
+ if(H5F_block_write(dset->oloc.file, H5FD_MEM_DRAW, udata.addr, chunk_size, data_dxpl_id, fb_info.fill_buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write raw data to file")
+
+ /* Indicate that blocks are being written */
+ blocks_written = TRUE;
+ } /* end if */
+ else {
+#endif /* H5_HAVE_PARALLEL */
+ if(H5F_block_write(dset->oloc.file, H5FD_MEM_DRAW, udata.addr, chunk_size, data_dxpl_id, fb_info.fill_buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write raw data to file")
+#ifdef H5_HAVE_PARALLEL
+ } /* end else */
+#endif /* H5_HAVE_PARALLEL */
+ } /* end if */
+
+ /* Release the fill buffer if we need to re-allocate it each time */
+ if(fb_info_init && fb_info.has_vlen_fill_type && pline->nused > 0)
+ H5D_fill_release(&fb_info);
+ } /* end if */
+ } /* end if */
+
+ /* Increment indices */
+ carry = TRUE;
+ for(i = (int)(space_ndims - 1); i >= 0; --i) {
+ chunk_offset[i] += layout->u.chunk.dim[i];
+ if(chunk_offset[i] >= space_dim[i])
+ chunk_offset[i] = 0;
+ else {
+ carry = FALSE;
+ break;
+ } /* end else */
+ } /* end for */
+ } /* end while */
+
+#ifdef H5_HAVE_PARALLEL
+ /* Only need to block at the barrier if we actually initialized a chunk */
+ /* using an MPI-capable file driver */
+ if(using_mpi && blocks_written) {
+ /* Wait at barrier to avoid race conditions where some processes are
+ * still writing out chunks and other processes race ahead to read
+ * them in, getting bogus data.
+ */
+ if(MPI_SUCCESS != (mpi_code = MPI_Barrier(mpi_comm)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Barrier failed", mpi_code)
+ } /* end if */
+#endif /* H5_HAVE_PARALLEL */
+
+ /* Reset any cached chunk info for this dataset */
+ H5D_chunk_cinfo_cache_reset(&dset->shared->cache.chunk.last);
+
+done:
+ /* Release the fill buffer info, if it's been initialized */
+ if(fb_info_init && H5D_fill_term(&fb_info) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release fill buffer info")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_allocate() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_prune_cb
+ *
+ * Purpose: Search for chunks that are no longer inside the pruned
+ * dataset's extent
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
+ * March 26, 2002
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+H5D_chunk_prune_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata)
+{
+ H5D_chunk_it_ud1_t *udata = (H5D_chunk_it_ud1_t *)_udata; /* User data */
+ H5D_chunk_sl_ck_t *sl_node = NULL; /* Skip list node for chunk to remove */
+ unsigned rank; /* Current # of dimensions */
+ hbool_t should_delete = FALSE; /* Whether the chunk should be deleted */
+ hbool_t needs_fill = FALSE; /* Whether the chunk overlaps the new extent and needs fill valiues */
+ unsigned u; /* Local index variable */
+ int ret_value = H5_ITER_CONT; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_prune_cb)
+
+ /* Figure out what chunks are no longer in use for the specified extent and release them */
+ rank = udata->common.mesg->u.chunk.ndims - 1;
+ for(u = 0; u < rank; u++)
+ /* The chunk record points to a chunk of storage that contains the
+ * beginning of the logical address space represented by UDATA.
+ */
+ if(chunk_rec->offset[u] >= udata->dims[u]) {
+ /* Indicate that the chunk will be deleted */
+ should_delete = TRUE;
+
+ /* Break out of loop, we know the chunk is outside the current dimensions */
+ break;
+ } /* end if */
+ /* Check for chunk that overlaps new extent and will need fill values */
+ else if((chunk_rec->offset[u] + udata->common.mesg->u.chunk.dim[u]) > udata->dims[u])
+ /* Indicate that the chunk needs filling */
+ /* (but continue in loop, since it could be outside the extent in
+ * another dimension -QAK)
+ */
+ needs_fill = TRUE;
+
+ /* Check for chunk to delete */
+ if(should_delete) {
+ /* Allocate space for the shared structure */
+ if(NULL == (sl_node = H5FL_MALLOC(H5D_chunk_sl_ck_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5_ITER_ERROR, "memory allocation failed for shared B-tree info")
+
+ /* Calculate the index of this chunk */
+ if(H5V_chunk_index(rank, chunk_rec->offset, udata->common.mesg->u.chunk.dim, udata->down_chunks, &sl_node->index) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_BADRANGE, H5_ITER_ERROR, "can't get chunk index")
+
+ /* Store the key for the chunk */
+ sl_node->rec = *chunk_rec;
+
+ /* Insert the chunk description in the skip list */
+ if(H5SL_insert(udata->outside, sl_node, &sl_node->index) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTINSERT, H5_ITER_ERROR, "can't insert chunk into skip list")
+ } /* end if */
+ /* Check for chunk that overlaps the new dataset dimensions and needs filling */
+ else if(needs_fill) {
+ const H5D_io_info_t *io_info = udata->io_info; /* Local pointer to I/O info */
+ H5D_t *dset = io_info->dset; /* Local pointer to the dataset info */
+ const H5O_layout_t *layout = &(dset->shared->layout); /* Dataset's layout */
+ H5S_sel_iter_t chunk_iter; /* Memory selection iteration info */
+ hssize_t sel_nelmts; /* Number of elements in selection */
+ hsize_t count[H5O_LAYOUT_NDIMS]; /* Element count of hyperslab */
+ void *chunk; /* The file chunk */
+ unsigned idx_hint; /* Which chunk we're dealing with */
+ H5D_chunk_ud_t chk_udata; /* User data for locking chunk */
+ uint32_t bytes_accessed; /* Bytes accessed in chunk */
+
+ /* Initialize the fill value buffer, if necessary */
+ if(!udata->fb_info_init) {
+ H5_CHECK_OVERFLOW(udata->elmts_per_chunk, uint32_t, size_t);
+ if(H5D_fill_init(&udata->fb_info, NULL, FALSE, NULL, NULL, NULL, NULL,
+ &dset->shared->dcpl_cache.fill,
+ dset->shared->type, dset->shared->type_id, (size_t)udata->elmts_per_chunk,
+ io_info->dxpl_cache->max_temp_buf, io_info->dxpl_id) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, H5_ITER_ERROR, "can't initialize fill buffer info")
+ udata->fb_info_init = TRUE;
+ } /* end if */
+
+ /* Compute the # of elements to leave with existing value, in each dimension */
+ for(u = 0; u < rank; u++) {
+ count[u] = MIN(layout->u.chunk.dim[u], (udata->dims[u] - chunk_rec->offset[u]));
+ HDassert(count[u] > 0);
+ } /* end for */
+
+ /* Select all elements in chunk, to begin with */
+ if(H5S_select_all(udata->chunk_space, TRUE) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTSELECT, H5_ITER_ERROR, "unable to select space")
+
+ /* "Subtract out" the elements to keep */
+ if(H5S_select_hyperslab(udata->chunk_space, H5S_SELECT_NOTB, udata->hyper_start, NULL, count, NULL) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTSELECT, H5_ITER_ERROR, "unable to select hyperslab")
+
+ /* Calculate the index of this chunk */
+ if(H5V_chunk_index(rank, chunk_rec->offset, layout->u.chunk.dim, udata->down_chunks, &io_info->store->chunk.index) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, H5_ITER_ERROR, "can't get chunk index")
+
+ /* Lock the chunk into the cache, to get a pointer to the chunk buffer */
+ /* (Casting away const OK -QAK) */
+ io_info->store->chunk.offset = (hsize_t *)chunk_rec->offset;
+ chk_udata.common.mesg = layout;
+ chk_udata.common.offset = chunk_rec->offset;
+ chk_udata.nbytes = chunk_rec->nbytes;
+ chk_udata.filter_mask = chunk_rec->filter_mask;
+ chk_udata.addr = chunk_rec->chunk_addr;
+ if(NULL == (chunk = (void *)H5D_chunk_lock(udata->io_info, &chk_udata, FALSE, &idx_hint)))
+ HGOTO_ERROR(H5E_DATASET, H5E_READERROR, H5_ITER_ERROR, "unable to lock raw data chunk")
+
+
+ /* Fill the selection in the memory buffer */
+ /* Use the size of the elements in the chunk directly instead of */
+ /* relying on the fill.size, which might be set to 0 if there is */
+ /* no fill-value defined for the dataset -QAK */
+
+ /* Get the number of elements in the selection */
+ sel_nelmts = H5S_GET_SELECT_NPOINTS(udata->chunk_space);
+ HDassert(sel_nelmts >= 0);
+ H5_CHECK_OVERFLOW(sel_nelmts, hssize_t, size_t);
+
+ /* Check for VL datatype & non-default fill value */
+ if(udata->fb_info.has_vlen_fill_type)
+ /* Re-fill the buffer to use for this I/O operation */
+ if(H5D_fill_refill_vl(&udata->fb_info, (size_t)sel_nelmts, io_info->dxpl_id) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, H5_ITER_ERROR, "can't refill fill value buffer")
+
+ /* Create a selection iterator for scattering the elements to memory buffer */
+ if(H5S_select_iter_init(&chunk_iter, udata->chunk_space, layout->u.chunk.dim[rank]) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, H5_ITER_ERROR, "unable to initialize chunk selection information")
+
+ /* Scatter the data into memory */
+ if(H5D_scatter_mem(udata->fb_info.fill_buf, udata->chunk_space, &chunk_iter, (size_t)sel_nelmts, io_info->dxpl_cache, chunk/*out*/) < 0) {
+ H5S_SELECT_ITER_RELEASE(&chunk_iter);
+ HGOTO_ERROR(H5E_DATASET, H5E_READERROR, H5_ITER_ERROR, "scatter failed")
+ } /* end if */
+
+ /* Release the selection iterator */
+ if(H5S_SELECT_ITER_RELEASE(&chunk_iter) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, H5_ITER_ERROR, "Can't release selection iterator")
+
+
+ /* The number of bytes accessed in the chunk */
+ /* (i.e. the bytes replaced with fill values) */
+ H5_CHECK_OVERFLOW(sel_nelmts, hssize_t, uint32_t);
+ bytes_accessed = (uint32_t)sel_nelmts * layout->u.chunk.dim[rank];
+
+ /* Release lock on chunk */
+ if(H5D_chunk_unlock(io_info, TRUE, idx_hint, chunk, bytes_accessed) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, H5_ITER_ERROR, "unable to unlock raw data chunk")
+ } /* end else-if */
+
+done:
+ if(ret_value != H5_ITER_CONT && sl_node)
+ (void)H5FL_FREE(H5D_chunk_sl_ck_t, sl_node);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_prune_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_prune_sl_rm_cb
+ *
+ * Purpose: Destroy a skip list node for "pruning" chunks, also removes
+ * the chunk from the index.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol, koziol@hdfgroup.org
+ * May 3, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_chunk_prune_sl_rm_cb(void *item, void UNUSED *key, void *op_data)
+{
+ H5D_chunk_sl_ck_t *sl_node = (H5D_chunk_sl_ck_t *)item; /* Temporary pointer to chunk to remove */
+ H5D_chunk_sl_rm_t *rm_info = (H5D_chunk_sl_rm_t *)op_data; /* Information needed for removing chunk from B-tree */
+ H5D_chunk_common_ud_t idx_udata; /* User data for index removal routine */
+ herr_t ret_value = H5_ITER_CONT; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_prune_sl_rm_cb)
+
+ /* Sanity checks */
+ HDassert(sl_node);
+ HDassert(rm_info);
+
+ /* Initialize the user data for the index callback */
+ idx_udata.mesg = rm_info->mesg;
+ idx_udata.offset = sl_node->rec.offset;
+
+ /* Remove */
+ if((rm_info->idx_info->layout->u.chunk.ops->remove)(rm_info->idx_info, &idx_udata) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTDELETE, H5_ITER_ERROR, "unable to remove chunk entry from index")
+
+done:
+ (void)H5FL_FREE(H5D_chunk_sl_ck_t, sl_node);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D_chunk_prune_sl_rm_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_prune_by_extent
+ *
+ * Purpose: This function searches for chunks that are no longer necessary
+ * both in the raw data cache and in the chunk index.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
+ * Algorithm: Robb Matzke
+ * March 27, 2002
+ *
+ * The algorithm is:
+ *
+ * For chunks that are no longer necessary:
+ *
+ * 1. Search in the raw data cache for each chunk
+ * 2. If found then preempt it from the cache
+ * 3. Search in the B-tree for each chunk
+ * 4. If found then remove it from the B-tree and deallocate file storage for the chunk
+ *
+ * This example shows a 2d dataset of 90x90 with a chunk size of 20x20.
+ *
+ *
+ * 0 20 40 60 80 90 100
+ * 0 +---------+---------+---------+---------+-----+...+
+ * |:::::X:::::::::::::: : : | :
+ * |:::::::X:::::::::::: : : | : Key
+ * |::::::::::X::::::::: : : | : --------
+ * |::::::::::::X::::::: : : | : +-+ Dataset
+ * 20+::::::::::::::::::::.........:.........:.....+...: | | Extent
+ * | :::::X::::: : : | : +-+
+ * | ::::::::::: : : | :
+ * | ::::::::::: : : | : ... Chunk
+ * | :::::::X::: : : | : : : Boundary
+ * 40+.........:::::::::::.........:.........:.....+...: :.:
+ * | : : : : | :
+ * | : : : : | : ... Allocated
+ * | : : : : | : ::: & Filled
+ * | : : : : | : ::: Chunk
+ * 60+.........:.........:.........:.........:.....+...:
+ * | : :::::::X::: : | : X Element
+ * | : ::::::::::: : | : Written
+ * | : ::::::::::: : | :
+ * | : ::::::::::: : | :
+ * 80+.........:.........:::::::::::.........:.....+...: O Fill Val
+ * | : : ::::::::::: | : Explicitly
+ * | : : ::::::X:::: | : Written
+ * 90+---------+---------+---------+---------+-----+ :
+ * : : : ::::::::::: :
+ * 100:.........:.........:.........:::::::::::.........:
+ *
+ *
+ * We have 25 total chunks for this dataset, 5 of which have space
+ * allocated in the file because they were written to one or more
+ * elements. These five chunks (and only these five) also have entries in
+ * the storage B-tree for this dataset.
+ *
+ * Now lets say we want to shrink the dataset down to 70x70:
+ *
+ *
+ * 0 20 40 60 70 80 90 100
+ * 0 +---------+---------+---------+----+----+-----+...+
+ * |:::::X:::::::::::::: : | : | :
+ * |:::::::X:::::::::::: : | : | : Key
+ * |::::::::::X::::::::: : | : | : --------
+ * |::::::::::::X::::::: : | : | : +-+ Dataset
+ * 20+::::::::::::::::::::.........:....+....:.....|...: | | Extent
+ * | :::::X::::: : | : | : +-+
+ * | ::::::::::: : | : | :
+ * | ::::::::::: : | : | : ... Chunk
+ * | :::::::X::: : | : | : : : Boundary
+ * 40+.........:::::::::::.........:....+....:.....|...: :.:
+ * | : : : | : | :
+ * | : : : | : | : ... Allocated
+ * | : : : | : | : ::: & Filled
+ * | : : : | : | : ::: Chunk
+ * 60+.........:.........:.........:....+....:.....|...:
+ * | : :::::::X::: | : | : X Element
+ * | : ::::::::::: | : | : Written
+ * +---------+---------+---------+----+ : | :
+ * | : ::::::::::: : | :
+ * 80+.........:.........:::::::::X:.........:.....|...: O Fill Val
+ * | : : ::::::::::: | : Explicitly
+ * | : : ::::::X:::: | : Written
+ * 90+---------+---------+---------+---------+-----+ :
+ * : : : ::::::::::: :
+ * 100:.........:.........:.........:::::::::::.........:
+ *
+ *
+ * That means that the nine chunks along the bottom and right side should
+ * no longer exist. Of those nine chunks, (0,80), (20,80), (40,80),
+ * (60,80), (80,80), (80,60), (80,40), (80,20), and (80,0), one is actually allocated
+ * that needs to be released.
+ * To release the chunks, we traverse the B-tree to obtain a list of unused
+ * allocated chunks, and then call H5B_remove() for each chunk.
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_chunk_prune_by_extent(H5D_t *dset, hid_t dxpl_id, const hsize_t *old_dims)
+{
+ H5D_chk_idx_info_t idx_info; /* Chunked index info */
+ H5D_io_info_t chk_io_info; /* Chunked I/O info object */
+ H5D_storage_t chk_store; /* Chunk storage information */
+ H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */
+ H5D_dxpl_cache_t *dxpl_cache = &_dxpl_cache; /* Data transfer property cache */
+ const H5O_layout_t *layout = &(dset->shared->layout); /* Dataset's layout */
+ const H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk); /*raw data chunk cache */
+ H5D_rdcc_ent_t *ent = NULL, *next = NULL; /* Cache entries */
+ hsize_t curr_dims[H5O_LAYOUT_NDIMS]; /* Current dataspace dimensions */
+ H5D_chunk_it_ud1_t udata; /* Chunk index iterator user data */
+ hbool_t udata_init = FALSE; /* Whether the chunk index iterator user data has been initialized */
+ H5D_chunk_sl_rm_t rm_info; /* User data for skip list destroy callback */
+ H5S_t *chunk_space = NULL; /* Dataspace for a chunk */
+ hsize_t chunk_dims[H5O_LAYOUT_NDIMS]; /* Chunk dimensions */
+ hsize_t chunks[H5O_LAYOUT_NDIMS]; /* Current number of chunks in each dimension */
+ hsize_t down_chunks[H5O_LAYOUT_NDIMS]; /* "down" size of number of elements in each dimension */
+ hsize_t hyper_start[H5O_LAYOUT_NDIMS]; /* Starting location of hyperslab */
+ uint32_t elmts_per_chunk; /* Elements in chunk */
+ unsigned rank; /* Current # of dimensions */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5D_chunk_prune_by_extent, FAIL)
+
+ /* Check args */
+ HDassert(dset && H5D_CHUNKED == layout->type);
+ HDassert(layout->u.chunk.ndims > 0 && layout->u.chunk.ndims <= H5O_LAYOUT_NDIMS);
+ HDassert(H5F_addr_defined(layout->u.chunk.addr));
+ HDassert(dxpl_cache);
+
+ /* Fill the DXPL cache values for later use */
+ if(H5D_get_dxpl_cache(dxpl_id, &dxpl_cache) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache")
+
+ /* Go get the rank & dimensions (including the element size) */
+ rank = layout->u.chunk.ndims - 1;
+ if(H5S_get_simple_extent_dims(dset->shared->space, curr_dims, NULL) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get dataset dimensions")
+ curr_dims[rank] = layout->u.chunk.dim[rank];
+
+ /*-------------------------------------------------------------------------
+ * Figure out what chunks are no longer in use for the specified extent
+ * and release them from the linked list raw data cache
+ *-------------------------------------------------------------------------
+ */
+ for(ent = rdcc->head; ent; ent = next) {
+ /* Get pointer to next extry in cache, in case this one is evicted */
+ next = ent->next;
+
+ /* Check for chunk offset outside of new dimensions */
+ for(u = 0; u < rank; u++)
+ if((hsize_t)ent->offset[u] >= curr_dims[u]) {
+ /* Evict the entry from the cache, but do not flush it to disk */
+ if(H5D_chunk_cache_evict(dset, dxpl_id, dxpl_cache, ent, FALSE) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTREMOVE, FAIL, "unable to evict chunk")
+
+ /* Break out of loop, chunk is evicted */
+ break;
+ } /* end if */
+ } /* end for */
+
+ /* Round up to the next integer # of chunks, to accomodate partial chunks */
+ /* (also compute the number of elements per chunk) */
+ /* (also copy the chunk dimensions into 'hsize_t' array for creating dataspace) */
+ elmts_per_chunk = 1;
+ for(u = 0; u < rank; u++) {
+ chunks[u] = ((old_dims[u] + layout->u.chunk.dim[u]) - 1) / layout->u.chunk.dim[u];
+ elmts_per_chunk *= layout->u.chunk.dim[u];
+ chunk_dims[u] = layout->u.chunk.dim[u];
+ } /* end for */
+
+ /* Get the "down" sizes for each dimension */
+ if(H5V_array_down(rank, chunks, down_chunks) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_BADVALUE, FAIL, "can't compute 'down' sizes")
+
+ /* Create a data space for a chunk & set the extent */
+ if(NULL == (chunk_space = H5S_create_simple(rank, chunk_dims, NULL)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create simple dataspace")
+
+ /* Reset hyperslab start array */
+ /* (hyperslabs will always start from origin) */
+ HDmemset(hyper_start, 0, sizeof(hyper_start));
+
+ /* Set up chunked I/O info object, for operations on chunks (in callback) */
+ /* (Casting away const OK -QAK) */
+ H5D_BUILD_IO_INFO_RD(&chk_io_info, dset, dxpl_cache, dxpl_id, &chk_store, NULL);
+
+ /* Compose chunked index info struct */
+ idx_info.f = dset->oloc.file;
+ idx_info.dxpl_id = dxpl_id;
+ idx_info.layout = &dset->shared->layout;
+
+ /* Initialize the user data for the iteration */
+ HDmemset(&udata, 0, sizeof udata);
+ udata.common.mesg = layout;
+ udata.io_info = &chk_io_info;
+ udata.idx_info = &idx_info;
+ udata.dims = curr_dims;
+ udata.down_chunks = down_chunks;
+ udata.elmts_per_chunk = elmts_per_chunk;
+ udata.chunk_space = chunk_space;
+ udata.hyper_start = hyper_start;
+ udata_init = TRUE;
+
+ /* Initialize the skip list that will hold the chunks outside the dimensions */
+ if(NULL == (udata.outside = H5SL_create(H5SL_TYPE_HSIZE, 0.5, (size_t)H5D_CHUNK_DEFAULT_SKIPLIST_HEIGHT)))
+ HGOTO_ERROR(H5E_IO, H5E_CANTCREATE, FAIL, "can't create skip list for chunks outside new dimensions")
+
+ /* Iterate over the chunks */
+ if((dset->shared->layout.u.chunk.ops->iterate)(&idx_info, H5D_chunk_prune_cb, &udata) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to retrieve prune chunks from index")
+
+ /* Set up user data for skip list callback */
+ rm_info.idx_info = &idx_info;
+ rm_info.mesg = layout;
+
+ /* Destroy the skip list, deleting the chunks in the callback */
+ H5SL_destroy(udata.outside, H5D_chunk_prune_sl_rm_cb, &rm_info);
+
+ /* Reset any cached chunk info for this dataset */
+ H5D_chunk_cinfo_cache_reset(&dset->shared->cache.chunk.last);
+
+done:
+ /* Release resources */
+ if(chunk_space && H5S_close(chunk_space) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataspace")
+ if(udata_init) {
+ if(udata.fb_info_init && H5D_fill_term(&udata.fb_info) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release fill buffer info")
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_prune_by_extent() */
+
+#ifdef H5_HAVE_PARALLEL
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_addrmap_cb
+ *
+ * Purpose: Callback when obtaining the chunk addresses for all existing chunks
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Kent Yang
+ * Tuesday, November 15, 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+H5D_chunk_addrmap_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata)
+{
+ H5D_chunk_it_ud2_t *udata = (H5D_chunk_it_ud2_t *)_udata; /* User data for callback */
+ unsigned rank = udata->common.mesg->u.chunk.ndims - 1; /* # of dimensions of dataset */
+ hsize_t chunk_index;
+ int ret_value = H5_ITER_CONT; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_addrmap_cb)
+
+ /* Compute the index for this chunk */
+ if(H5V_chunk_index(rank, chunk_rec->offset, udata->common.mesg->u.chunk.dim, udata->down_chunks, &chunk_index) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, H5_ITER_ERROR, "can't get chunk index")
+
+ /* Set it in the userdata to return */
+ udata->chunk_addr[chunk_index] = chunk_rec->chunk_addr;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D_chunk_addrmap_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_addrmap
+ *
+ * Purpose: Obtain the chunk addresses for all existing chunks
+ *
+ * Return: Success: Non-negative on succeed.
+ * Failure: negative value
+ *
+ * Programmer: Kent Yang
+ * November 15, 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_chunk_addrmap(const H5D_io_info_t *io_info, haddr_t chunk_addr[],
+ const hsize_t down_chunks[])
+{
+ H5D_chk_idx_info_t idx_info; /* Chunked index info */
+ H5D_t *dset = io_info->dset; /* Local pointer to dataset info */
+ H5D_chunk_it_ud2_t udata; /* User data for iteration callback */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5D_chunk_addrmap, FAIL)
+
+ HDassert(dset);
+ HDassert(chunk_addr);
+ HDassert(down_chunks);
+
+ /* Set up user data for B-tree callback */
+ HDmemset(&udata, 0, sizeof(udata));
+ udata.common.mesg = &dset->shared->layout;
+ udata.down_chunks = down_chunks;
+ udata.chunk_addr = chunk_addr;
+
+ /* Compose chunked index info struct */
+ idx_info.f = dset->oloc.file;
+ idx_info.dxpl_id = io_info->dxpl_id;
+ idx_info.layout = &dset->shared->layout;
+
+ /* Iterate over chunks to build mapping of chunk addresses */
+ if((dset->shared->layout.u.chunk.ops->iterate)(&idx_info, H5D_chunk_addrmap_cb, &udata) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to iterate over chunk index to build address map")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_addrmap() */
+#endif /* H5_HAVE_PARALLEL */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_delete
+ *
+ * Purpose: Delete raw data storage for entire dataset (i.e. all chunks)
+ *
+ * Return: Success: Non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, March 20, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_chunk_delete(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout)
+{
+ H5D_chk_idx_info_t idx_info; /* Chunked index info */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5D_chunk_delete, FAIL)
+
+ /* Compose chunked index info struct */
+ idx_info.f = f;
+ idx_info.dxpl_id = dxpl_id;
+ idx_info.layout = layout;
+
+ /* Check if the index has been created in the file */
+ if(H5F_addr_defined(layout->u.chunk.addr)) {
+ /* Delete the chunked storage information in the file */
+ if((layout->u.chunk.ops->delete)(&idx_info) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTDELETE, FAIL, "unable to delete chunk index")
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_delete() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_update_cache
+ *
+ * Purpose: Update any cached chunks index values after the dataspace
+ * size has changed
+ *
+ * Return: Success: Non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Saturday, May 29, 2004
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_chunk_update_cache(H5D_t *dset, hid_t dxpl_id)
+{
+ H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk); /*raw data chunk cache */
+ H5D_rdcc_ent_t *ent, *next; /*cache entry */
+ H5D_rdcc_ent_t *old_ent; /* Old cache entry */
+ H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */
+ H5D_dxpl_cache_t *dxpl_cache = &_dxpl_cache; /* Data transfer property cache */
+ unsigned rank; /*current # of dimensions */
+ hsize_t curr_dims[H5O_LAYOUT_NDIMS]; /*current dataspace dimensions */
+ hsize_t chunks[H5O_LAYOUT_NDIMS]; /*current number of chunks in each dimension */
+ hsize_t down_chunks[H5O_LAYOUT_NDIMS]; /* "down" size of number of elements in each dimension */
+ unsigned u; /*counters */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5D_chunk_update_cache, FAIL)
+
+ /* Check args */
+ HDassert(dset && H5D_CHUNKED == dset->shared->layout.type);
+ HDassert(dset->shared->layout.u.chunk.ndims > 0 && dset->shared->layout.u.chunk.ndims <= H5O_LAYOUT_NDIMS);
+
+ /* Get the rank */
+ rank = dset->shared->layout.u.chunk.ndims-1;
+ HDassert(rank > 0);
+
+ /* 1-D dataset's chunks can't have their index change */
+ if(rank == 1)
+ HGOTO_DONE(SUCCEED)
+
+ /* Go get the dimensions */
+ if(H5S_get_simple_extent_dims(dset->shared->space, curr_dims, NULL) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get dataset dimensions")
+
+ /* Round up to the next integer # of chunks, to accomodate partial chunks */
+ for(u = 0; u < rank; u++)
+ chunks[u] = ((curr_dims[u] + dset->shared->layout.u.chunk.dim[u]) - 1) / dset->shared->layout.u.chunk.dim[u];
+
+ /* Get the "down" sizes for each dimension */
+ if(H5V_array_down(rank, chunks, down_chunks) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "can't compute 'down' sizes")
+
+ /* Fill the DXPL cache values for later use */
+ if(H5D_get_dxpl_cache(dxpl_id, &dxpl_cache) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache")
+
+ /* Recompute the index for each cached chunk that is in a dataset */
+ for(ent = rdcc->head; ent; ent = next) {
+ hsize_t idx; /* Chunk index */
+ unsigned old_idx; /* Previous index number */
+
+ /* Get the pointer to the next cache entry */
+ next = ent->next;
+
+ /* Calculate the index of this chunk */
+ if(H5V_chunk_index(rank, ent->offset, dset->shared->layout.u.chunk.dim, down_chunks, &idx) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index")
+
+ /* Compute the index for the chunk entry */
+ old_idx = ent->idx; /* Save for later */
+ ent->idx = H5D_CHUNK_HASH(dset->shared, idx);
+
+ if(old_idx != ent->idx) {
+ /* Check if there is already a chunk at this chunk's new location */
+ old_ent = rdcc->slot[ent->idx];
+ if(old_ent != NULL) {
+ HDassert(old_ent->locked == 0);
+
+ /* Check if we are removing the entry we would walk to next */
+ if(old_ent == next)
+ next = old_ent->next;
+
+ /* Remove the old entry from the cache */
+ if(H5D_chunk_cache_evict(dset, dxpl_id, dxpl_cache, old_ent, TRUE) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "unable to flush one or more raw data chunks")
+ } /* end if */
+
+ /* Insert this chunk into correct location in hash table */
+ rdcc->slot[ent->idx] = ent;
+
+ /* Null out previous location */
+ rdcc->slot[old_idx] = NULL;
+ } /* end if */
+ } /* end for */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_update_cache() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_copy_cb
+ *
+ * Purpose: Copy chunked raw data from source file and insert to the
+ * index in the destination file
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Peter Cao
+ * August 20, 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+H5D_chunk_copy_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata)
+{
+ H5D_chunk_it_ud3_t *udata = (H5D_chunk_it_ud3_t *)_udata; /* User data for callback */
+ H5D_chunk_ud_t udata_dst; /* User data about new destination chunk */
+ hbool_t is_vlen = FALSE; /* Whether datatype is variable-length */
+ hbool_t fix_ref = FALSE; /* Whether to fix up references in the dest. file */
+
+ /* General information about chunk copy */
+ void *bkg = udata->bkg; /* Background buffer for datatype conversion */
+ void *buf = udata->buf; /* Chunk buffer for I/O & datatype conversions */
+ size_t buf_size = udata->buf_size; /* Size of chunk buffer */
+ H5O_pline_t *pline = udata->pline; /* I/O pipeline for applying filters */
+
+ /* needed for commpressed variable length data */
+ hbool_t has_filters = FALSE; /* Whether chunk has filters */
+ size_t nbytes; /* Size of chunk in file (in bytes) */
+ H5Z_cb_t cb_struct; /* Filter failure callback struct */
+
+ int ret_value = H5_ITER_CONT; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_copy_cb)
+
+ /* Get 'size_t' local value for number of bytes in chunk */
+ H5_ASSIGN_OVERFLOW(nbytes, chunk_rec->nbytes, uint32_t, size_t);
+
+ /* Check parameter for type conversion */
+ if(udata->do_convert) {
+ if(H5T_detect_class(udata->dt_src, H5T_VLEN) > 0)
+ is_vlen = TRUE;
+ else if((H5T_get_class(udata->dt_src, FALSE) == H5T_REFERENCE) && (udata->file_src != udata->idx_info_dst->f))
+ fix_ref = TRUE;
+ else
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "unable to copy dataset elements")
+ } /* end if */
+
+ /* Check for filtered chunks */
+ if(pline && pline->nused) {
+ has_filters = TRUE;
+ cb_struct.func = NULL; /* no callback function when failed */
+ } /* end if */
+
+ /* Resize the buf if it is too small to hold the data */
+ if(nbytes > buf_size) {
+ void *new_buf; /* New buffer for data */
+
+ /* Re-allocate memory for copying the chunk */
+ if(NULL == (new_buf = H5MM_realloc(udata->buf, nbytes)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5_ITER_ERROR, "memory allocation failed for raw data chunk")
+ udata->buf = new_buf;
+ if(udata->bkg) {
+ if(NULL == (new_buf = H5MM_realloc(udata->bkg, nbytes)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5_ITER_ERROR, "memory allocation failed for raw data chunk")
+ udata->bkg = new_buf;
+ if(!udata->cpy_info->expand_ref)
+ HDmemset((uint8_t *)udata->bkg + buf_size, 0, (size_t)(nbytes - buf_size));
+
+ bkg = udata->bkg;
+ } /* end if */
+
+ buf = udata->buf;
+ udata->buf_size = buf_size = nbytes;
+ } /* end if */
+
+ /* read chunk data from the source file */
+ if(H5F_block_read(udata->file_src, H5FD_MEM_DRAW, chunk_rec->chunk_addr, nbytes, udata->idx_info_dst->dxpl_id, buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, H5_ITER_ERROR, "unable to read raw data chunk")
+
+ /* Need to uncompress variable-length & reference data elements */
+ if(has_filters && (is_vlen || fix_ref)) {
+ unsigned filter_mask = chunk_rec->filter_mask;
+
+ if(H5Z_pipeline(pline, H5Z_FLAG_REVERSE, &filter_mask, H5Z_NO_EDC, cb_struct, &nbytes, &buf_size, &buf) < 0)
+ HGOTO_ERROR(H5E_PLINE, H5E_CANTFILTER, H5_ITER_ERROR, "data pipeline read failed")
+ } /* end if */
+
+ /* Perform datatype conversion, if necessary */
+ if(is_vlen) {
+ H5T_path_t *tpath_src_mem = udata->tpath_src_mem;
+ H5T_path_t *tpath_mem_dst = udata->tpath_mem_dst;
+ H5S_t *buf_space = udata->buf_space;
+ hid_t tid_src = udata->tid_src;
+ hid_t tid_dst = udata->tid_dst;
+ hid_t tid_mem = udata->tid_mem;
+ void *reclaim_buf = udata->reclaim_buf;
+ size_t reclaim_buf_size = udata->reclaim_buf_size;
+
+ /* Convert from source file to memory */
+ H5_CHECK_OVERFLOW(udata->nelmts, uint32_t, size_t);
+ if(H5T_convert(tpath_src_mem, tid_src, tid_mem, (size_t)udata->nelmts, (size_t)0, (size_t)0, buf, NULL, udata->idx_info_dst->dxpl_id) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5_ITER_ERROR, "datatype conversion failed")
+
+ /* Copy into another buffer, to reclaim memory later */
+ HDmemcpy(reclaim_buf, buf, reclaim_buf_size);
+
+ /* Set background buffer to all zeros */
+ HDmemset(bkg, 0, buf_size);
+
+ /* Convert from memory to destination file */
+ if(H5T_convert(tpath_mem_dst, tid_mem, tid_dst, udata->nelmts, (size_t)0, (size_t)0, buf, bkg, udata->idx_info_dst->dxpl_id) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5_ITER_ERROR, "datatype conversion failed")
+
+ /* Reclaim space from variable length data */
+ if(H5D_vlen_reclaim(tid_mem, buf_space, H5P_DATASET_XFER_DEFAULT, reclaim_buf) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_BADITER, H5_ITER_ERROR, "unable to reclaim variable-length data")
+ } /* end if */
+ else if(fix_ref) {
+ /* Check for expanding references */
+ /* (background buffer has already been zeroed out, if not expanding) */
+ if(udata->cpy_info->expand_ref) {
+ size_t ref_count;
+
+ /* Determine # of reference elements to copy */
+ ref_count = nbytes / H5T_get_size(udata->dt_src);
+
+ /* Copy the reference elements */
+ if(H5O_copy_expand_ref(udata->file_src, buf, udata->idx_info_dst->dxpl_id, udata->idx_info_dst->f, bkg, ref_count, H5T_get_ref_type(udata->dt_src), udata->cpy_info) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "unable to copy reference attribute")
+ } /* end if */
+
+ /* After fix ref, copy the new reference elements to the buffer to write out */
+ HDmemcpy(buf, bkg, buf_size);
+ } /* end if */
+
+ /* Set up destination chunk callback information for insertion */
+ udata_dst.common.mesg = udata->idx_info_dst->layout;
+ udata_dst.common.offset = chunk_rec->offset;
+ udata_dst.nbytes = chunk_rec->nbytes;
+ udata_dst.filter_mask = chunk_rec->filter_mask;
+ udata_dst.addr = HADDR_UNDEF;
+
+ /* Need to compress variable-length & reference data elements before writing to file */
+ if(has_filters && (is_vlen || fix_ref) ) {
+ if(H5Z_pipeline(pline, 0, &(udata_dst.filter_mask), H5Z_NO_EDC, cb_struct, &nbytes, &buf_size, &buf) < 0)
+ HGOTO_ERROR(H5E_PLINE, H5E_CANTFILTER, H5_ITER_ERROR, "output pipeline failed")
+ H5_ASSIGN_OVERFLOW(udata_dst.nbytes, nbytes, size_t, uint32_t);
+ udata->buf = buf;
+ udata->buf_size = buf_size;
+ } /* end if */
+
+ /* Insert chunk into the destination index */
+ if((udata->idx_info_dst->layout->u.chunk.ops->insert)(udata->idx_info_dst, &udata_dst) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert chunk into index")
+
+ /* Write chunk data to destination file */
+ HDassert(H5F_addr_defined(udata_dst.addr));
+ if(H5F_block_write(udata->idx_info_dst->f, H5FD_MEM_DRAW, udata_dst.addr, nbytes, udata->idx_info_dst->dxpl_id, buf) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, H5_ITER_ERROR, "unable to write raw data to file")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_copy_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_copy
+ *
+ * Purpose: Copy chunked storage from SRC file to DST file.
+ *
+ * Return: Success: Non-negative
+ * Failure: negative
+ *
+ * Programmer: Peter Cao
+ * August 20, 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_chunk_copy(H5F_t *f_src, H5O_layout_t *layout_src, H5F_t *f_dst,
+ H5O_layout_t *layout_dst, H5T_t *dt_src, H5O_copy_t *cpy_info,
+ H5O_pline_t *pline, hid_t dxpl_id)
+{
+ H5D_chunk_it_ud3_t udata; /* User data for iteration callback */
+ H5D_chk_idx_info_t idx_info_dst; /* Dest. chunked index info */
+ H5D_chk_idx_info_t idx_info_src; /* Source chunked index info */
+ H5T_path_t *tpath_src_mem = NULL, *tpath_mem_dst = NULL; /* Datatype conversion paths */
+ hid_t tid_src = -1; /* Datatype ID for source datatype */
+ hid_t tid_dst = -1; /* Datatype ID for destination datatype */
+ hid_t tid_mem = -1; /* Datatype ID for memory datatype */
+ size_t buf_size; /* Size of copy buffer */
+ size_t reclaim_buf_size; /* Size of reclaim buffer */
+ void *buf = NULL; /* Buffer for copying data */
+ void *bkg = NULL; /* Buffer for background during type conversion */
+ void *reclaim_buf = NULL; /* Buffer for reclaiming data */
+ H5S_t *buf_space = NULL; /* Dataspace describing buffer */
+ hid_t sid_buf = -1; /* ID for buffer dataspace */
+ uint32_t nelmts = 0; /* Number of elements in buffer */
+ hbool_t do_convert = FALSE; /* Indicate that type conversions should be performed */
+ hbool_t copy_setup_done = FALSE; /* Indicate that 'copy setup' is done */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5D_chunk_copy, FAIL)
+
+ /* Check args */
+ HDassert(f_src);
+ HDassert(f_dst);
+ HDassert(layout_src && H5D_CHUNKED == layout_src->type);
+ HDassert(layout_dst && H5D_CHUNKED == layout_dst->type);
+ HDassert(dt_src);
+
+ /* Compose source & dest chunked index info structs */
+ idx_info_src.f = f_src;
+ idx_info_src.dxpl_id = dxpl_id;
+ idx_info_src.layout = layout_src;
+
+ idx_info_dst.f = f_dst;
+ idx_info_dst.dxpl_id = dxpl_id;
+ idx_info_dst.layout = layout_dst;
+
+ /* Call the index-specific "copy setup" routine */
+ if((layout_src->u.chunk.ops->copy_setup)(&idx_info_src, &idx_info_dst) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set up index-specific chunk copying information")
+ HDassert(H5F_addr_defined(layout_dst->u.chunk.addr));
+ copy_setup_done = TRUE;
+
+ /* Create datatype ID for src datatype */
+ if((tid_src = H5I_register(H5I_DATATYPE, dt_src, FALSE)) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register source file datatype")
+
+ /* If there's a VLEN source datatype, set up type conversion information */
+ if(H5T_detect_class(dt_src, H5T_VLEN) > 0) {
+ H5T_t *dt_dst; /* Destination datatype */
+ H5T_t *dt_mem; /* Memory datatype */
+ size_t mem_dt_size; /* Memory datatype size */
+ size_t tmp_dt_size; /* Temp. datatype size */
+ size_t max_dt_size; /* Max atatype size */
+ hsize_t buf_dim; /* Dimension for buffer */
+ unsigned u;
+
+ /* create a memory copy of the variable-length datatype */
+ if(NULL == (dt_mem = H5T_copy(dt_src, H5T_COPY_TRANSIENT)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy")
+ if((tid_mem = H5I_register(H5I_DATATYPE, dt_mem, FALSE)) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register memory datatype")
+
+ /* create variable-length datatype at the destinaton file */
+ if(NULL == (dt_dst = H5T_copy(dt_src, H5T_COPY_TRANSIENT)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy")
+ if(H5T_set_loc(dt_dst, f_dst, H5T_LOC_DISK) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "cannot mark datatype on disk")
+ if((tid_dst = H5I_register(H5I_DATATYPE, dt_dst, FALSE)) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register destination file datatype")
+
+ /* Set up the conversion functions */
+ if(NULL == (tpath_src_mem = H5T_path_find(dt_src, dt_mem, NULL, NULL, dxpl_id, FALSE)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert between src and mem datatypes")
+ if(NULL == (tpath_mem_dst = H5T_path_find(dt_mem, dt_dst, NULL, NULL, dxpl_id, FALSE)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert between mem and dst datatypes")
+
+ /* Determine largest datatype size */
+ if(0 == (max_dt_size = H5T_get_size(dt_src)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to determine datatype size")
+ if(0 == (mem_dt_size = H5T_get_size(dt_mem)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to determine datatype size")
+ max_dt_size = MAX(max_dt_size, mem_dt_size);
+ if(0 == (tmp_dt_size = H5T_get_size(dt_dst)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to determine datatype size")
+ max_dt_size = MAX(max_dt_size, tmp_dt_size);
+
+ /* Compute the number of elements per chunk */
+ nelmts = 1;
+ for(u = 0; u < (layout_src->u.chunk.ndims - 1); u++)
+ nelmts *= layout_src->u.chunk.dim[u];
+
+ /* Create the space and set the initial extent */
+ buf_dim = nelmts;
+ if(NULL == (buf_space = H5S_create_simple((unsigned)1, &buf_dim, NULL)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create simple dataspace")
+
+ /* Atomize */
+ if((sid_buf = H5I_register(H5I_DATASPACE, buf_space, FALSE)) < 0) {
+ H5S_close(buf_space);
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace ID")
+ } /* end if */
+
+ /* Set initial buffer sizes */
+ buf_size = nelmts * max_dt_size;
+ reclaim_buf_size = nelmts * mem_dt_size;
+
+ /* Allocate memory for reclaim buf */
+ if(NULL == (reclaim_buf = H5MM_malloc(reclaim_buf_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for raw data chunk")
+
+ /* Indicate that type conversion should be performed */
+ do_convert = TRUE;
+ } /* end if */
+ else {
+ if(H5T_get_class(dt_src, FALSE) == H5T_REFERENCE) {
+ /* Indicate that type conversion should be performed */
+ do_convert = TRUE;
+ } /* end if */
+
+ H5_ASSIGN_OVERFLOW(buf_size, layout_src->u.chunk.size, uint32_t, size_t);
+ reclaim_buf_size = 0;
+ } /* end else */
+
+ /* Set up conversion buffer, if appropriate */
+ if(do_convert) {
+ /* Allocate background memory for converting the chunk */
+ if(NULL == (bkg = H5MM_malloc(buf_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for raw data chunk")
+
+ /* Check for reference datatype and no expanding references & clear background buffer */
+ if(!cpy_info->expand_ref &&
+ ((H5T_get_class(dt_src, FALSE) == H5T_REFERENCE) && (f_src != f_dst)))
+ /* Reset value to zero */
+ HDmemset(bkg, 0, buf_size);
+ } /* end if */
+
+ /* Allocate memory for copying the chunk */
+ if(NULL == (buf = H5MM_malloc(buf_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for raw data chunk")
+
+ /* Initialize the callback structure for the source */
+ HDmemset(&udata, 0, sizeof udata);
+ udata.common.mesg = layout_src;
+ udata.file_src = f_src;
+ udata.idx_info_dst = &idx_info_dst;
+ udata.buf = buf;
+ udata.bkg = bkg;
+ udata.buf_size = buf_size;
+ udata.tid_src = tid_src;
+ udata.tid_mem = tid_mem;
+ udata.tid_dst = tid_dst;
+ udata.dt_src = dt_src;
+ udata.do_convert = do_convert;
+ udata.tpath_src_mem = tpath_src_mem;
+ udata.tpath_mem_dst = tpath_mem_dst;
+ udata.reclaim_buf = reclaim_buf;
+ udata.reclaim_buf_size = reclaim_buf_size;
+ udata.buf_space = buf_space;
+ udata.nelmts = nelmts;
+ udata.pline = pline;
+ udata.cpy_info = cpy_info;
+
+ /* Iterate over chunks to copy data */
+ if((layout_src->u.chunk.ops->iterate)(&idx_info_src, H5D_chunk_copy_cb, &udata) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_BADITER, FAIL, "unable to iterate over chunk index to copy data")
+
+ /* I/O buffers may have been re-allocated */
+ buf = udata.buf;
+ bkg = udata.bkg;
+
+done:
+ if(sid_buf > 0 && H5I_dec_ref(sid_buf, FALSE) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "can't decrement temporary dataspace ID")
+ if(tid_src > 0)
+ if(H5I_dec_ref(tid_src, FALSE) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
+ if(tid_dst > 0)
+ if(H5I_dec_ref(tid_dst, FALSE) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
+ if(tid_mem > 0)
+ if(H5I_dec_ref(tid_mem, FALSE) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
+ if(buf)
+ H5MM_xfree(buf);
+ if(bkg)
+ H5MM_xfree(bkg);
+ if(reclaim_buf)
+ H5MM_xfree(reclaim_buf);
+
+ /* Clean up any index information */
+ if(copy_setup_done)
+ if((layout_src->u.chunk.ops->copy_shutdown)(layout_src, layout_dst) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "unable to shut down index copying info")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_copy() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_bh_size
+ *
+ * Purpose: Retrieve the amount of index storage for chunked dataset
+ *
+ * Return: Success: Non-negative
+ * Failure: negative
+ *
+ * Programmer: Vailin Choi
+ * June 8, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_chunk_bh_info(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout,
+ hsize_t *index_size)
+{
+ H5D_chk_idx_info_t idx_info; /* Chunked index info */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5D_chunk_bh_info, FAIL)
+
+ /* Check args */
+ HDassert(f);
+ HDassert(layout);
+ HDassert(index_size);
+
+ /* Compose chunked index info struct */
+ idx_info.f = f;
+ idx_info.dxpl_id = dxpl_id;
+ idx_info.layout = layout;
+
+ /* Get size of index structure */
+ if((layout->u.chunk.ops->size)(&idx_info, index_size) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to retrieve chunk index info")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_bh_info() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_iter_dump
+ *
+ * Purpose: If the UDATA.STREAM member is non-null then debugging
+ * information is written to that stream.
+ *
+ * Return: Success: Non-negative
+ *
+ * Failure: Negative
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, April 21, 1999
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+H5D_chunk_dump_index_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata)
+{
+ H5D_chunk_it_ud4_t *udata = (H5D_chunk_it_ud4_t *)_udata; /* User data from caller */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_chunk_dump_index_cb)
+
+ if(udata->stream) {
+ unsigned u; /* Local index variable */
+
+ /* Print header if not already displayed */
+ if(!udata->header_displayed) {
+ HDfprintf(udata->stream, " Flags Bytes Address Logical Offset\n");
+ HDfprintf(udata->stream, " ========== ======== ========== ==============================\n");
+
+ /* Set flag that the headers has been printed */
+ udata->header_displayed = TRUE;
+ } /* end if */
+
+ /* Print information about this chunk */
+ HDfprintf(udata->stream, " 0x%08x %8Zu %10a [", chunk_rec->filter_mask, chunk_rec->nbytes, chunk_rec->chunk_addr);
+ for(u = 0; u < udata->ndims; u++)
+ HDfprintf(udata->stream, "%s%Hd", (u ? ", " : ""), chunk_rec->offset[u]);
+ HDfputs("]\n", udata->stream);
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(H5_ITER_CONT)
+} /* H5D_chunk_dump_index_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_dump_index
+ *
+ * Purpose: Prints information about the storage index to the specified
+ * stream.
+ *
+ * Return: Success: Non-negative
+ * Failure: negative
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, April 28, 1999
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_chunk_dump_index(H5D_t *dset, hid_t dxpl_id, FILE *stream)
+{
+ H5D_chunk_it_ud4_t udata; /* User data for callback */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5D_chunk_dump_index, FAIL)
+
+ /* Sanity check */
+ HDassert(dset);
+
+ /* Only display info if stream is defined */
+ if(stream) {
+ H5D_chk_idx_info_t idx_info; /* Chunked index info */
+
+ /* Display address of index */
+ HDfprintf(stream, " Address: %a\n", dset->shared->layout.u.chunk.addr);
+
+ /* Set up user data for callback */
+ udata.stream = stream;
+ udata.header_displayed = FALSE;
+ udata.ndims = dset->shared->layout.u.chunk.ndims;
+
+ /* Compose chunked index info struct */
+ idx_info.f = dset->oloc.file;
+ idx_info.dxpl_id = dxpl_id;
+ idx_info.layout = &dset->shared->layout;
+
+ /* Iterate over index and dump chunk info */
+ if((dset->shared->layout.u.chunk.ops->iterate)(&idx_info, H5D_chunk_dump_index_cb, &udata) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_BADITER, FAIL, "unable to iterate over chunk index to dump chunk info")
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_dump_index() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_dest
+ *
+ * Purpose: Destroy the entire chunk cache by flushing dirty entries,
+ * preempting all entries, and freeing the cache itself.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * Thursday, May 21, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_chunk_dest(H5F_t *f, hid_t dxpl_id, H5D_t *dset)
+{
+ H5D_chk_idx_info_t idx_info; /* Chunked index info */
+ H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */
+ H5D_dxpl_cache_t *dxpl_cache = &_dxpl_cache; /* Data transfer property cache */
+ H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk); /* Dataset's chunk cache */
+ H5D_rdcc_ent_t *ent = NULL, *next = NULL; /* Pointer to current & next cache entries */
+ int nerrors = 0; /* Accumulated count of errors */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5D_chunk_dest, FAIL)
+
+ HDassert(f);
+ HDassert(dset);
+
+ /* Fill the DXPL cache values for later use */
+ if(H5D_get_dxpl_cache(dxpl_id, &dxpl_cache) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache")
+
+ /* Flush all the cached chunks */
+ for(ent = rdcc->head; ent; ent = next) {
+ next = ent->next;
+ if(H5D_chunk_cache_evict(dset, dxpl_id, dxpl_cache, ent, TRUE) < 0)
+ nerrors++;
+ } /* end for */
+ if(nerrors)
+ HGOTO_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "unable to flush one or more raw data chunks")
+
+ /* Release cache structures */
+ if(rdcc->slot)
+ H5FL_SEQ_FREE(H5D_rdcc_ent_ptr_t, rdcc->slot);
+ HDmemset(rdcc, 0, sizeof(H5D_rdcc_t));
+
+ /* Compose chunked index info struct */
+ idx_info.f = f;
+ idx_info.dxpl_id = dxpl_id;
+ idx_info.layout = &dset->shared->layout;
+
+ /* Free any index structures */
+ if((dset->shared->layout.u.chunk.ops->dest)(&idx_info) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "unable to release chunk index info")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_dest() */
+
+#ifdef H5D_CHUNK_DEBUG
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_stats
+ *
+ * Purpose: Print raw data cache statistics to the debug stream. If
+ * HEADERS is non-zero then print table column headers,
+ * otherwise assume that the H5AC layer has already printed them.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * Thursday, May 21, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_chunk_stats(const H5D_t *dset, hbool_t headers)
+{
+ H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk);
+ double miss_rate;
+ char ascii[32];
+ herr_t ret_value=SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5D_chunk_stats, FAIL)
+
+ if (!H5DEBUG(AC))
+ HGOTO_DONE(SUCCEED)
+
+ if (headers) {
+ fprintf(H5DEBUG(AC), "H5D: raw data cache statistics\n");
+ fprintf(H5DEBUG(AC), " %-18s %8s %8s %8s %8s+%-8s\n",
+ "Layer", "Hits", "Misses", "MissRate", "Inits", "Flushes");
+ fprintf(H5DEBUG(AC), " %-18s %8s %8s %8s %8s-%-8s\n",
+ "-----", "----", "------", "--------", "-----", "-------");
+ }
+
+#ifdef H5AC_DEBUG
+ if (H5DEBUG(AC)) headers = TRUE;
+#endif
+
+ if (headers) {
+ if (rdcc->nhits>0 || rdcc->nmisses>0) {
+ miss_rate = 100.0 * rdcc->nmisses /
+ (rdcc->nhits + rdcc->nmisses);
+ } else {
+ miss_rate = 0.0;
+ }
+ if (miss_rate > 100) {
+ sprintf(ascii, "%7d%%", (int) (miss_rate + 0.5));
+ } else {
+ sprintf(ascii, "%7.2f%%", miss_rate);
+ }
+
+ fprintf(H5DEBUG(AC), " %-18s %8u %8u %7s %8d+%-9ld\n",
+ "raw data chunks", rdcc->nhits, rdcc->nmisses, ascii,
+ rdcc->ninits, (long)(rdcc->nflushes)-(long)(rdcc->ninits));
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_stats() */
+#endif /* H5D_CHUNK_DEBUG */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_null_readvv
+ *
+ * Purpose: Performs "no-op" I/O operation, advancing through two I/O
+ * vectors, until one runs out.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, April 1, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static ssize_t
+H5D_null_readvv(const H5D_io_info_t UNUSED *io_info,
+ size_t chunk_max_nseq, size_t *chunk_curr_seq, size_t chunk_len_arr[], hsize_t chunk_offset_arr[],
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[])
+{
+ size_t u, v; /* Local index variables */
+ size_t size; /* Size of sequence in bytes */
+ ssize_t bytes_processed = 0; /* Eventual return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_null_readvv)
+
+ /* Check args */
+ HDassert(chunk_len_arr);
+ HDassert(chunk_offset_arr);
+ HDassert(mem_len_arr);
+ HDassert(mem_offset_arr);
+
+ /* Work through all the sequences */
+ for(u = *mem_curr_seq, v = *chunk_curr_seq; u < mem_max_nseq && v < chunk_max_nseq; ) {
+ /* Choose smallest buffer to write */
+ if(chunk_len_arr[v] < mem_len_arr[u])
+ size = chunk_len_arr[v];
+ else
+ size = mem_len_arr[u];
+
+ /* Update source information */
+ chunk_len_arr[v] -= size;
+ chunk_offset_arr[v] += size;
+ if(chunk_len_arr[v] == 0)
+ v++;
+
+ /* Update destination information */
+ mem_len_arr[u] -= size;
+ mem_offset_arr[u] += size;
+ if(mem_len_arr[u] == 0)
+ u++;
+
+ /* Increment number of bytes copied */
+ bytes_processed += (ssize_t)size;
+ } /* end for */
+
+ /* Update current sequence vectors */
+ *mem_curr_seq = u;
+ *chunk_curr_seq = v;
+
+ FUNC_LEAVE_NOAPI(bytes_processed)
+} /* H5D_null_readvv() */
+
diff --git a/src/H5Dcompact.c b/src/H5Dcompact.c
index 2e4d3f7..00471d6 100644
--- a/src/H5Dcompact.c
+++ b/src/H5Dcompact.c
@@ -18,7 +18,7 @@
* August 5, 2002
*
* Purpose: Compact dataset I/O functions. These routines are similar
- * H5D_contig_* and H5D_istore_*.
+ * H5D_contig_* and H5D_chunk_*.
*/
/****************/
@@ -41,22 +41,55 @@
#include "H5Oprivate.h" /* Object headers */
#include "H5Vprivate.h" /* Vector and array functions */
+
/****************/
/* Local Macros */
/****************/
+
/******************/
/* Local Typedefs */
/******************/
+
/********************/
/* Local Prototypes */
/********************/
+/* Layout operation callbacks */
+static herr_t H5D_compact_new(H5F_t *f, hid_t dapl_id, hid_t dxpl_id, H5D_t *dset,
+ const H5P_genplist_t *dc_plist);
+static herr_t H5D_compact_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
+ H5D_chunk_map_t *cm);
+static ssize_t H5D_compact_readvv(const H5D_io_info_t *io_info,
+ size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_size_arr[], hsize_t dset_offset_arr[],
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_size_arr[], hsize_t mem_offset_arr[]);
+static ssize_t H5D_compact_writevv(const H5D_io_info_t *io_info,
+ size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_size_arr[], hsize_t dset_offset_arr[],
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_size_arr[], hsize_t mem_offset_arr[]);
+
+
/*********************/
/* Package Variables */
/*********************/
+/* Compact storage layout I/O ops */
+const H5D_layout_ops_t H5D_LOPS_COMPACT[1] = {{
+ H5D_compact_new,
+ H5D_compact_io_init,
+ H5D_contig_read,
+ H5D_contig_write,
+#ifdef H5_HAVE_PARALLEL
+ NULL,
+ NULL,
+#endif /* H5_HAVE_PARALLEL */
+ H5D_compact_readvv,
+ H5D_compact_writevv,
+ NULL
+}};
+
+
/*******************/
/* Local Variables */
/*******************/
@@ -64,6 +97,7 @@
/* Declare extern the free list to manage blocks of type conversion data */
H5FL_BLK_EXTERN(type_conv);
+
/*-------------------------------------------------------------------------
* Function: H5D_compact_fill
@@ -118,6 +152,79 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5D_compact_new
+ *
+ * Purpose: Constructs new compact layout information for dataset
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, May 22, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static herr_t
+H5D_compact_new(H5F_t *f, hid_t UNUSED dapl_id, hid_t UNUSED dxpl_id, H5D_t *dset,
+ const H5P_genplist_t UNUSED *dc_plist)
+{
+ hssize_t tmp_size; /* Temporary holder for raw data size */
+ hsize_t comp_data_size; /* Size of compact data */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_compact_new)
+
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(dset);
+ HDassert(dc_plist);
+
+ /*
+ * Compact dataset is stored in dataset object header message of
+ * layout.
+ */
+ tmp_size = H5S_GET_EXTENT_NPOINTS(dset->shared->space) * H5T_get_size(dset->shared->type);
+ H5_ASSIGN_OVERFLOW(dset->shared->layout.u.compact.size, tmp_size, hssize_t, size_t);
+
+ /* Verify data size is smaller than maximum header message size
+ * (64KB) minus other layout message fields.
+ */
+ comp_data_size = H5O_MESG_MAX_SIZE - H5O_layout_meta_size(f, &(dset->shared->layout));
+ if(dset->shared->layout.u.compact.size > comp_data_size)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "compact dataset size is bigger than header message maximum size")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_compact_new() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_compact_io_init
+ *
+ * Purpose: Performs initialization before any sort of I/O on the raw data
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, March 20, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_compact_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t UNUSED *type_info,
+ hsize_t UNUSED nelmts, const H5S_t UNUSED *file_space, const H5S_t UNUSED *mem_space,
+ H5D_chunk_map_t UNUSED *cm)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_compact_io_init)
+
+ io_info->store->compact.buf = io_info->dset->shared->layout.u.compact.buf;
+ io_info->store->compact.dirty = &io_info->dset->shared->layout.u.compact.dirty;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5D_compact_io_init() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5D_compact_readvv
*
* Purpose: Reads some data vectors from a dataset into a buffer.
@@ -135,20 +242,19 @@ done:
*
*-------------------------------------------------------------------------
*/
-ssize_t
+static ssize_t
H5D_compact_readvv(const H5D_io_info_t *io_info,
size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_size_arr[], hsize_t dset_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_size_arr[], hsize_t mem_offset_arr[],
- haddr_t UNUSED addr, void UNUSED *pointer/*in*/, void *buf)
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_size_arr[], hsize_t mem_offset_arr[])
{
- ssize_t ret_value; /* Return value */
+ ssize_t ret_value; /* Return value */
- FUNC_ENTER_NOAPI(H5D_compact_readvv, FAIL)
+ FUNC_ENTER_NOAPI_NOINIT(H5D_compact_readvv)
- assert(io_info->dset);
+ HDassert(io_info);
/* Use the vectorized memory copy routine to do actual work */
- if((ret_value=H5V_memcpyvv(buf,mem_max_nseq,mem_curr_seq,mem_size_arr,mem_offset_arr,io_info->dset->shared->layout.u.compact.buf,dset_max_nseq,dset_curr_seq,dset_size_arr,dset_offset_arr))<0)
+ if((ret_value = H5V_memcpyvv(io_info->u.rbuf, mem_max_nseq, mem_curr_seq, mem_size_arr, mem_offset_arr, io_info->store->compact.buf, dset_max_nseq, dset_curr_seq, dset_size_arr, dset_offset_arr)) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed")
done:
@@ -177,24 +283,23 @@ done:
*
*-------------------------------------------------------------------------
*/
-ssize_t
+static ssize_t
H5D_compact_writevv(const H5D_io_info_t *io_info,
size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_size_arr[], hsize_t dset_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_size_arr[], hsize_t mem_offset_arr[],
- haddr_t UNUSED addr, void UNUSED *pointer/*in*/, const void *buf)
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_size_arr[], hsize_t mem_offset_arr[])
{
- ssize_t ret_value; /* Return value */
+ ssize_t ret_value; /* Return value */
- FUNC_ENTER_NOAPI(H5D_compact_writevv, FAIL)
+ FUNC_ENTER_NOAPI_NOINIT(H5D_compact_writevv)
- assert(io_info->dset);
+ HDassert(io_info);
/* Use the vectorized memory copy routine to do actual work */
- if((ret_value=H5V_memcpyvv(io_info->dset->shared->layout.u.compact.buf,dset_max_nseq,dset_curr_seq,dset_size_arr,dset_offset_arr,buf,mem_max_nseq,mem_curr_seq,mem_size_arr,mem_offset_arr))<0)
+ if((ret_value = H5V_memcpyvv(io_info->store->compact.buf, dset_max_nseq, dset_curr_seq, dset_size_arr, dset_offset_arr, io_info->u.wbuf, mem_max_nseq, mem_curr_seq, mem_size_arr, mem_offset_arr)) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed")
/* Mark the compact dataset's buffer as dirty */
- io_info->dset->shared->layout.u.compact.dirty = TRUE;
+ *io_info->store->compact.dirty = TRUE;
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -214,7 +319,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5D_compact_copy(H5F_t *f_src, H5O_layout_t *layout_src, H5F_t *f_dst,
+H5D_compact_copy(H5F_t *f_src, H5O_layout_t *layout_src, H5F_t *f_dst,
H5O_layout_t *layout_dst, H5T_t *dt_src, H5O_copy_t *cpy_info, hid_t dxpl_id)
{
hid_t tid_src = -1; /* Datatype ID for source datatype */
@@ -236,7 +341,7 @@ H5D_compact_copy(H5F_t *f_src, H5O_layout_t *layout_src, H5F_t *f_dst,
HDassert(dt_src);
/* Create datatype ID for src datatype, so it gets freed */
- if((tid_src = H5I_register(H5I_DATATYPE, dt_src)) < 0)
+ if((tid_src = H5I_register(H5I_DATATYPE, dt_src, FALSE)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register source file datatype")
/* If there's a VLEN source datatype, do type conversion information */
@@ -255,7 +360,7 @@ H5D_compact_copy(H5F_t *f_src, H5O_layout_t *layout_src, H5F_t *f_dst,
/* create a memory copy of the variable-length datatype */
if(NULL == (dt_mem = H5T_copy(dt_src, H5T_COPY_TRANSIENT)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy")
- if((tid_mem = H5I_register(H5I_DATATYPE, dt_mem)) < 0)
+ if((tid_mem = H5I_register(H5I_DATATYPE, dt_mem, FALSE)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register memory datatype")
/* create variable-length datatype at the destinaton file */
@@ -263,14 +368,14 @@ H5D_compact_copy(H5F_t *f_src, H5O_layout_t *layout_src, H5F_t *f_dst,
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy")
if(H5T_set_loc(dt_dst, f_dst, H5T_LOC_DISK) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "cannot mark datatype on disk")
- if((tid_dst = H5I_register(H5I_DATATYPE, dt_dst)) < 0)
+ if((tid_dst = H5I_register(H5I_DATATYPE, dt_dst, FALSE)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register destination file datatype")
/* Set up the conversion functions */
if(NULL == (tpath_src_mem = H5T_path_find(dt_src, dt_mem, NULL, NULL, dxpl_id, FALSE)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert between src and mem datatypes")
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to convert between src and mem datatypes")
if(NULL == (tpath_mem_dst = H5T_path_find(dt_mem, dt_dst, NULL, NULL, dxpl_id, FALSE)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert between mem and dst datatypes")
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to convert between mem and dst datatypes")
/* Determine largest datatype size */
if(0 == (src_dt_size = H5T_get_size(dt_src)))
@@ -297,7 +402,7 @@ H5D_compact_copy(H5F_t *f_src, H5O_layout_t *layout_src, H5F_t *f_dst,
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create simple dataspace")
/* Atomize */
- if((buf_sid = H5I_register(H5I_DATASPACE, buf_space)) < 0) {
+ if((buf_sid = H5I_register(H5I_DATASPACE, buf_space, FALSE)) < 0) {
H5S_close(buf_space);
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace ID")
} /* end if */
@@ -353,29 +458,28 @@ H5D_compact_copy(H5F_t *f_src, H5O_layout_t *layout_src, H5F_t *f_dst,
/* Type conversion not necessary */
HDmemcpy(layout_dst->u.compact.buf, layout_src->u.compact.buf, layout_src->u.compact.size);
} /* end if */
- else
+ else
/* Type conversion not necessary */
HDmemcpy(layout_dst->u.compact.buf, layout_src->u.compact.buf, layout_src->u.compact.size);
done:
- if(buf_sid > 0)
- if(H5I_dec_ref(buf_sid) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary dataspace ID")
+ if(buf_sid > 0 && H5I_dec_ref(buf_sid, FALSE) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "can't decrement temporary dataspace ID")
if(tid_src > 0)
- if(H5I_dec_ref(tid_src) < 0)
+ if(H5I_dec_ref(tid_src, FALSE) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
if(tid_dst > 0)
- if(H5I_dec_ref(tid_dst) < 0)
+ if(H5I_dec_ref(tid_dst, FALSE) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
if(tid_mem > 0)
- if(H5I_dec_ref(tid_mem) < 0)
+ if(H5I_dec_ref(tid_mem, FALSE) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
if(buf)
- H5FL_BLK_FREE(type_conv, buf);
+ (void)H5FL_BLK_FREE(type_conv, buf);
if(reclaim_buf)
- H5FL_BLK_FREE(type_conv, reclaim_buf);
+ (void)H5FL_BLK_FREE(type_conv, reclaim_buf);
if(bkg)
- H5FL_BLK_FREE(type_conv, bkg);
+ (void)H5FL_BLK_FREE(type_conv, bkg);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_compact_copy() */
diff --git a/src/H5Dcontig.c b/src/H5Dcontig.c
index e1a02cb..6aafbcf 100644
--- a/src/H5Dcontig.c
+++ b/src/H5Dcontig.c
@@ -19,7 +19,7 @@
*
* Purpose:
* Contiguous dataset I/O functions. These routines are similar to
- * the H5D_istore_* routines and really only an abstract way of dealing
+ * the H5D_chunk_* routines and really only an abstract way of dealing
* with the data sieve buffer from H5F_seq_read/write.
*/
@@ -45,24 +45,53 @@
#include "H5Pprivate.h" /* Property lists */
#include "H5Vprivate.h" /* Vector and array functions */
+
/****************/
/* Local Macros */
/****************/
+
/******************/
/* Local Typedefs */
/******************/
+
/********************/
/* Local Prototypes */
/********************/
-static herr_t H5D_contig_write(H5D_t *dset, const H5D_dxpl_cache_t *dxpl_cache,
- hid_t dxpl_id, const H5D_storage_t *store, hsize_t offset, size_t size, const void *buf);
+
+/* Layout operation callbacks */
+static herr_t H5D_contig_new(H5F_t *f, hid_t dapl_id, hid_t dxpl_id, H5D_t *dset,
+ const H5P_genplist_t *dc_plist);
+static herr_t H5D_contig_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
+ H5D_chunk_map_t *cm);
+
+/* Helper routines */
+static herr_t H5D_contig_write_one(H5D_io_info_t *io_info, hsize_t offset,
+ size_t size);
+
/*********************/
/* Package Variables */
/*********************/
+/* Contiguous storage layout I/O ops */
+const H5D_layout_ops_t H5D_LOPS_CONTIG[1] = {{
+ H5D_contig_new,
+ H5D_contig_io_init,
+ H5D_contig_read,
+ H5D_contig_write,
+#ifdef H5_HAVE_PARALLEL
+ H5D_contig_collective_read,
+ H5D_contig_collective_write,
+#endif /* H5_HAVE_PARALLEL */
+ H5D_contig_readvv,
+ H5D_contig_writevv,
+ NULL
+}};
+
+
/*******************/
/* Local Variables */
/*******************/
@@ -73,9 +102,10 @@ H5FL_BLK_DEFINE(sieve_buf);
/* Declare extern the free list to manage blocks of type conversion data */
H5FL_BLK_EXTERN(type_conv);
+
/*-------------------------------------------------------------------------
- * Function: H5D_contig_create
+ * Function: H5D_contig_alloc
*
* Purpose: Allocate file space for a contiguously stored dataset
*
@@ -87,11 +117,11 @@ H5FL_BLK_EXTERN(type_conv);
*-------------------------------------------------------------------------
*/
herr_t
-H5D_contig_create(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout /*out */ )
+H5D_contig_alloc(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout /*out */ )
{
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5D_contig_create, FAIL)
+ FUNC_ENTER_NOAPI(H5D_contig_alloc, FAIL)
/* check args */
HDassert(f);
@@ -103,7 +133,7 @@ H5D_contig_create(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout /*out */ )
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_contig_create */
+} /* end H5D_contig_alloc */
/*-------------------------------------------------------------------------
@@ -121,7 +151,8 @@ done:
herr_t
H5D_contig_fill(H5D_t *dset, hid_t dxpl_id)
{
- H5D_storage_t store; /* Union of storage info for dataset */
+ H5D_io_info_t ioinfo; /* Dataset I/O info */
+ H5D_storage_t store; /* Union of storage info for dataset */
H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */
H5D_dxpl_cache_t *dxpl_cache = &_dxpl_cache; /* Data transfer property cache */
hssize_t snpoints; /* Number of points in space (for error checking) */
@@ -198,6 +229,9 @@ H5D_contig_fill(H5D_t *dset, hid_t dxpl_id)
/* Start at the beginning of the dataset */
offset = 0;
+ /* Simple setup for dataset I/O info struct */
+ H5D_BUILD_IO_INFO_WRT(&ioinfo, dset, dxpl_cache, my_dxpl_id, &store, fb_info.fill_buf);
+
/*
* Fill the entire current extent with the fill value. We can do
* this quite efficiently by making sure we copy the fill value
@@ -208,7 +242,7 @@ H5D_contig_fill(H5D_t *dset, hid_t dxpl_id)
while(npoints > 0) {
size_t curr_points; /* Number of elements to write on this iteration of the loop */
size_t size; /* Size of buffer to write */
-
+
/* Compute # of elements and buffer size to write for this iteration */
curr_points = MIN(fb_info.elmts_per_buf, npoints);
size = curr_points * fb_info.file_elmt_size;
@@ -225,7 +259,7 @@ H5D_contig_fill(H5D_t *dset, hid_t dxpl_id)
/* Write the chunks out from only one process */
/* !! Use the internal "independent" DXPL!! -QAK */
if(H5_PAR_META_WRITE == mpi_rank)
- if(H5D_contig_write(dset, dxpl_cache, my_dxpl_id, &store, offset, size, fb_info.fill_buf) < 0)
+ if(H5D_contig_write_one(&ioinfo, offset, size) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to write fill value to dataset")
/* Indicate that blocks are being written */
@@ -234,7 +268,7 @@ H5D_contig_fill(H5D_t *dset, hid_t dxpl_id)
else {
#endif /* H5_HAVE_PARALLEL */
H5_CHECK_OVERFLOW(size, size_t, hsize_t);
- if(H5D_contig_write(dset, dxpl_cache, my_dxpl_id, &store, offset, size, fb_info.fill_buf) < 0)
+ if(H5D_contig_write_one(&ioinfo, offset, size) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to write fill value to dataset")
#ifdef H5_HAVE_PARALLEL
} /* end else */
@@ -316,16 +350,172 @@ H5D_contig_get_addr(const H5D_t *dset)
FUNC_ENTER_NOAPI_NOFUNC(H5D_contig_get_addr)
/* check args */
- assert(dset);
- assert(dset->shared->layout.type==H5D_CONTIGUOUS);
+ HDassert(dset);
+ HDassert(dset->shared->layout.type == H5D_CONTIGUOUS);
FUNC_LEAVE_NOAPI(dset->shared->layout.u.contig.addr)
-} /* end H5D_contig_get_addr */
+} /* end H5D_contig_get_addr() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_contig_new
+ *
+ * Purpose: Constructs new contiguous layout information for dataset
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, May 22, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static herr_t
+H5D_contig_new(H5F_t *f, hid_t UNUSED dapl_id, hid_t UNUSED dxpl_id, H5D_t *dset,
+ const H5P_genplist_t UNUSED *dc_plist)
+{
+ hssize_t tmp_size; /* Temporary holder for raw data size */
+ hsize_t dim[H5O_LAYOUT_NDIMS]; /* Current size of data in elements */
+ hsize_t max_dim[H5O_LAYOUT_NDIMS]; /* Maximum size of data in elements */
+ int ndims; /* Rank of dataspace */
+ int i; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_contig_new)
+
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(dset);
+
+ /*
+ * The maximum size of the dataset cannot exceed the storage size.
+ * Also, only the slowest varying dimension of a simple data space
+ * can be extendible (currently only for external data storage).
+ */
+ dset->shared->layout.u.contig.addr = HADDR_UNDEF; /* Initialize to no address */
+
+ /* Check for invalid dataset dimensions */
+ if((ndims = H5S_get_simple_extent_dims(dset->shared->space, dim, max_dim)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize contiguous storage")
+ for(i = 0; i < ndims; i++)
+ if(max_dim[i] > dim[i])
+ HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "extendible contiguous non-external dataset")
+
+ /* Compute the total size of dataset */
+ tmp_size = H5S_GET_EXTENT_NPOINTS(dset->shared->space) * H5T_get_size(dset->shared->type);
+ H5_ASSIGN_OVERFLOW(dset->shared->layout.u.contig.size, tmp_size, hssize_t, hsize_t);
+
+ /* Get the sieve buffer size for this dataset */
+ dset->shared->cache.contig.sieve_buf_size = H5F_SIEVE_BUF_SIZE(f);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_contig_new() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_contig_io_init
+ *
+ * Purpose: Performs initialization before any sort of I/O on the raw data
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, March 20, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_contig_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t UNUSED *type_info,
+ hsize_t UNUSED nelmts, const H5S_t UNUSED *file_space, const H5S_t UNUSED *mem_space,
+ H5D_chunk_map_t UNUSED *cm)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_contig_io_init)
+
+ io_info->store->contig.dset_addr = io_info->dset->shared->layout.u.contig.addr;
+ io_info->store->contig.dset_size = io_info->dset->shared->layout.u.contig.size;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5D_contig_io_init() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_contig_read
+ *
+ * Purpose: Read from a contiguous dataset.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Raymond Lu
+ * Thursday, April 10, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_contig_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
+ H5D_chunk_map_t UNUSED *fm)
+{
+ herr_t ret_value = SUCCEED; /*return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_contig_read)
+
+ /* Sanity check */
+ HDassert(io_info);
+ HDassert(io_info->u.rbuf);
+ HDassert(type_info);
+ HDassert(mem_space);
+ HDassert(file_space);
+
+ /* Read data */
+ if((io_info->io_ops.single_read)(io_info, type_info, nelmts, file_space, mem_space) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "contiguous read failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_contig_read() */
/*-------------------------------------------------------------------------
* Function: H5D_contig_write
*
+ * Purpose: Write to a contiguous dataset.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Raymond Lu
+ * Thursday, April 10, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_contig_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
+ H5D_chunk_map_t UNUSED *fm)
+{
+ herr_t ret_value = SUCCEED; /*return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_contig_write)
+
+ /* Sanity check */
+ HDassert(io_info);
+ HDassert(io_info->u.wbuf);
+ HDassert(type_info);
+ HDassert(mem_space);
+ HDassert(file_space);
+
+ /* Write data */
+ if((io_info->io_ops.single_write)(io_info, type_info, nelmts, file_space, mem_space) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "contiguous write failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_contig_write() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_contig_write_one
+ *
* Purpose: Writes some data from a dataset into a buffer.
* The data is contiguous. The address is relative to the base
* address for the file.
@@ -338,34 +528,27 @@ H5D_contig_get_addr(const H5D_t *dset)
*-------------------------------------------------------------------------
*/
static herr_t
-H5D_contig_write(H5D_t *dset, const H5D_dxpl_cache_t *dxpl_cache,
- hid_t dxpl_id, const H5D_storage_t *store,
- hsize_t offset, size_t size, const void *buf)
+H5D_contig_write_one(H5D_io_info_t *io_info, hsize_t offset, size_t size)
{
- H5D_io_info_t io_info; /* Dataset I/O info */
- hsize_t dset_off=offset; /* Offset in dataset */
- size_t dset_len=size; /* Length in dataset */
- size_t dset_curr_seq=0; /* "Current sequence" in dataset */
- hsize_t mem_off=0; /* Offset in memory */
- size_t mem_len=size; /* Length in memory */
- size_t mem_curr_seq=0; /* "Current sequence" in memory */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5D_contig_write, FAIL)
-
- assert (dset);
- assert (dxpl_cache);
- assert (store);
- assert (buf);
-
- H5D_BUILD_IO_INFO(&io_info,dset,dxpl_cache,dxpl_id,store);
- if(H5D_contig_writevv(&io_info, (size_t)1, &dset_curr_seq, &dset_len, &dset_off,
- (size_t)1, &mem_curr_seq, &mem_len, &mem_off, (haddr_t)0, NULL, buf) < 0)
+ hsize_t dset_off = offset; /* Offset in dataset */
+ size_t dset_len = size; /* Length in dataset */
+ size_t dset_curr_seq = 0; /* "Current sequence" in dataset */
+ hsize_t mem_off = 0; /* Offset in memory */
+ size_t mem_len = size; /* Length in memory */
+ size_t mem_curr_seq = 0; /* "Current sequence" in memory */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_contig_write_one)
+
+ HDassert(io_info);
+
+ if(H5D_contig_writevv(io_info, (size_t)1, &dset_curr_seq, &dset_len, &dset_off,
+ (size_t)1, &mem_curr_seq, &mem_len, &mem_off) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vector write failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_contig_write() */
+} /* end H5D_contig_write_one() */
/*-------------------------------------------------------------------------
@@ -389,67 +572,75 @@ done:
ssize_t
H5D_contig_readvv(const H5D_io_info_t *io_info,
size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[],
- haddr_t UNUSED address, void UNUSED *pointer, void *_buf)
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[])
{
H5F_t *file = io_info->dset->oloc.file; /* File for dataset */
- H5D_rdcdc_t *dset_contig=&(io_info->dset->shared->cache.contig); /* Cached information about contiguous data */
- const H5D_contig_storage_t *store_contig=&(io_info->store->contig); /* Contiguous storage info for this I/O operation */
- unsigned char *buf=(unsigned char *)_buf; /* Pointer to buffer to fill */
+ H5D_rdcdc_t *dset_contig = &(io_info->dset->shared->cache.contig); /* Cached information about contiguous data */
+ const H5D_contig_storage_t *store_contig = &(io_info->store->contig); /* Contiguous storage info for this I/O operation */
+ unsigned char *buf = (unsigned char *)io_info->u.rbuf; /* Pointer to buffer to fill */
haddr_t addr; /* Actual address to read */
- size_t total_size=0; /* Total size of sequence in bytes */
+ size_t total_size = 0; /* Total size of sequence in bytes */
size_t size; /* Size of sequence in bytes */
size_t u; /* Counting variable */
size_t v; /* Counting variable */
ssize_t ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5D_contig_readvv, FAIL)
+#ifdef QAK
+HDfprintf(stderr, "%s: dset_max_nseq = %Zu\n", FUNC, dset_max_nseq);
+HDfprintf(stderr, "%s: mem_max_nseq = %Zu\n", FUNC, mem_max_nseq);
+HDfprintf(stderr, "%s: *dset_curr_seq= %Zu\n", FUNC, *dset_curr_seq);
+HDfprintf(stderr, "%s: *mem_curr_seq= %Zu\n", FUNC, *mem_curr_seq);
+for(u = 0; u < dset_max_nseq; u++)
+ HDfprintf(stderr, "%s: dset_len_arr[%Zu] = %Zu, dset_offset_arr[%Zu] = %Hu\n", FUNC, u, dset_len_arr[u], u, dset_offset_arr[u]);
+for(u = 0; u < mem_max_nseq; u++)
+ HDfprintf(stderr, "%s: mem_len_arr[%Zu] = %Zu, mem_offset_arr[%Zu] = %Hu\n", FUNC, u, mem_len_arr[u], u, mem_offset_arr[u]);
+#endif /* QAK */
/* Check args */
- assert(io_info);
- assert(io_info->dset);
- assert(io_info->store);
- assert(buf);
+ HDassert(io_info);
+ HDassert(io_info->dset);
+ HDassert(io_info->store);
+ HDassert(buf);
/* Check if data sieving is enabled */
- if(H5F_HAS_FEATURE(file,H5FD_FEAT_DATA_SIEVE)) {
- haddr_t sieve_start=HADDR_UNDEF, sieve_end=HADDR_UNDEF; /* Start & end locations of sieve buffer */
+ if(H5F_HAS_FEATURE(file, H5FD_FEAT_DATA_SIEVE)) {
+ haddr_t sieve_start = HADDR_UNDEF, sieve_end = HADDR_UNDEF; /* Start & end locations of sieve buffer */
haddr_t contig_end; /* End locations of block to write */
- size_t sieve_size=(size_t)-1; /* size of sieve buffer */
- haddr_t abs_eoa; /* Absolute end of file address */
+ size_t sieve_size = (size_t)-1; /* size of sieve buffer */
haddr_t rel_eoa; /* Relative end of file address */
hsize_t max_data; /* Actual maximum size of data to cache */
/* Set offsets in sequence lists */
- u=*dset_curr_seq;
- v=*mem_curr_seq;
+ u = *dset_curr_seq;
+ v = *mem_curr_seq;
/* Stash local copies of these value */
- if(dset_contig->sieve_buf!=NULL) {
- sieve_start=dset_contig->sieve_loc;
- sieve_size=dset_contig->sieve_size;
- sieve_end=sieve_start+sieve_size;
+ if(dset_contig->sieve_buf != NULL) {
+ sieve_start = dset_contig->sieve_loc;
+ sieve_size = dset_contig->sieve_size;
+ sieve_end = sieve_start+sieve_size;
} /* end if */
/* Works through sequences as fast as possible */
- for(; u<dset_max_nseq && v<mem_max_nseq; ) {
+ for(; u < dset_max_nseq && v < mem_max_nseq; ) {
/* Choose smallest buffer to write */
- if(mem_len_arr[v]<dset_len_arr[u])
- size=mem_len_arr[v];
+ if(mem_len_arr[v] < dset_len_arr[u])
+ size = mem_len_arr[v];
else
- size=dset_len_arr[u];
+ size = dset_len_arr[u];
/* Compute offset on disk */
- addr=store_contig->dset_addr+dset_offset_arr[u];
+ addr = store_contig->dset_addr + dset_offset_arr[u];
/* Compute offset in memory */
- buf = (unsigned char *)_buf + mem_offset_arr[v];
+ buf = (unsigned char *)io_info->u.rbuf + mem_offset_arr[v];
/* Check if the sieve buffer is allocated yet */
- if(dset_contig->sieve_buf==NULL) {
+ if(dset_contig->sieve_buf == NULL) {
/* Check if we can actually hold the I/O request in the sieve buffer */
if(size>dset_contig->sieve_buf_size) {
- if (H5F_block_read(file, H5FD_MEM_DRAW, addr, size, io_info->dxpl_id, buf)<0)
+ if(H5F_block_read(file, H5FD_MEM_DRAW, addr, size, io_info->dxpl_id, buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed")
} /* end if */
else {
@@ -461,44 +652,41 @@ H5D_contig_readvv(const H5D_io_info_t *io_info,
dset_contig->sieve_loc=addr;
/* Make certain we don't read off the end of the file */
- if (HADDR_UNDEF==(abs_eoa=H5F_get_eoa(file)))
+ if(HADDR_UNDEF == (rel_eoa = H5F_get_eoa(file, H5FD_MEM_DRAW)))
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size")
- /* Adjust absolute EOA address to relative EOA address */
- rel_eoa=abs_eoa-H5F_get_base_addr(file);
-
/* Set up the buffer parameters */
- max_data=store_contig->dset_size-dset_offset_arr[u];
+ max_data = store_contig->dset_size-dset_offset_arr[u];
/* Compute the size of the sieve buffer */
- H5_ASSIGN_OVERFLOW(dset_contig->sieve_size,MIN3(rel_eoa-dset_contig->sieve_loc,max_data,dset_contig->sieve_buf_size),hsize_t,size_t);
+ H5_ASSIGN_OVERFLOW(dset_contig->sieve_size, MIN3(rel_eoa-dset_contig->sieve_loc, max_data, dset_contig->sieve_buf_size), hsize_t, size_t);
/* Read the new sieve buffer */
- if (H5F_block_read(file, H5FD_MEM_DRAW, dset_contig->sieve_loc, dset_contig->sieve_size, io_info->dxpl_id, dset_contig->sieve_buf)<0)
+ if(H5F_block_read(file, H5FD_MEM_DRAW, dset_contig->sieve_loc, dset_contig->sieve_size, io_info->dxpl_id, dset_contig->sieve_buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed")
/* Grab the data out of the buffer (must be first piece of data in buffer ) */
- HDmemcpy(buf,dset_contig->sieve_buf,size);
+ HDmemcpy(buf, dset_contig->sieve_buf, size);
/* Reset sieve buffer dirty flag */
- dset_contig->sieve_dirty=0;
+ dset_contig->sieve_dirty = 0;
/* Stash local copies of these value */
- sieve_start=dset_contig->sieve_loc;
- sieve_size=dset_contig->sieve_size;
- sieve_end=sieve_start+sieve_size;
+ sieve_start = dset_contig->sieve_loc;
+ sieve_size = dset_contig->sieve_size;
+ sieve_end = sieve_start+sieve_size;
} /* end else */
} /* end if */
else {
/* Compute end of sequence to retrieve */
- contig_end=addr+size-1;
+ contig_end = addr + size - 1;
/* If entire read is within the sieve buffer, read it from the buffer */
if(addr>=sieve_start && contig_end<sieve_end) {
unsigned char *base_sieve_buf=dset_contig->sieve_buf+(addr-sieve_start);
/* Grab the data out of the buffer */
- HDmemcpy(buf,base_sieve_buf,size);
+ HDmemcpy(buf, base_sieve_buf, size);
} /* end if */
/* Entire request is not within this data sieve buffer */
else {
@@ -510,16 +698,16 @@ H5D_contig_readvv(const H5D_io_info_t *io_info,
/* Flush the sieve buffer, if it's dirty */
if(dset_contig->sieve_dirty) {
/* Write to file */
- if (H5F_block_write(file, H5FD_MEM_DRAW, sieve_start, sieve_size, io_info->dxpl_id, dset_contig->sieve_buf)<0)
+ if(H5F_block_write(file, H5FD_MEM_DRAW, sieve_start, sieve_size, io_info->dxpl_id, dset_contig->sieve_buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed")
/* Reset sieve buffer dirty flag */
- dset_contig->sieve_dirty=0;
+ dset_contig->sieve_dirty = 0;
} /* end if */
} /* end if */
/* Read directly into the user's buffer */
- if (H5F_block_read(file, H5FD_MEM_DRAW, addr, size, io_info->dxpl_id, buf)<0)
+ if(H5F_block_read(file, H5FD_MEM_DRAW, addr, size, io_info->dxpl_id, buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed")
} /* end if */
/* Element size fits within the buffer size */
@@ -538,12 +726,9 @@ H5D_contig_readvv(const H5D_io_info_t *io_info,
dset_contig->sieve_loc=addr;
/* Make certain we don't read off the end of the file */
- if (HADDR_UNDEF==(abs_eoa=H5F_get_eoa(file)))
+ if(HADDR_UNDEF == (rel_eoa = H5F_get_eoa(file, H5FD_MEM_DRAW)))
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size")
- /* Adjust absolute EOA address to relative EOA address */
- rel_eoa=abs_eoa-H5F_get_base_addr(file);
-
/* Only need this when resizing sieve buffer */
max_data=store_contig->dset_size-dset_offset_arr[u];
@@ -561,72 +746,72 @@ H5D_contig_readvv(const H5D_io_info_t *io_info,
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed")
/* Grab the data out of the buffer (must be first piece of data in buffer ) */
- HDmemcpy(buf,dset_contig->sieve_buf,size);
+ HDmemcpy(buf, dset_contig->sieve_buf, size);
/* Reset sieve buffer dirty flag */
- dset_contig->sieve_dirty=0;
+ dset_contig->sieve_dirty = 0;
} /* end else */
} /* end else */
} /* end else */
/* Update memory information */
- mem_len_arr[v]-=size;
- mem_offset_arr[v]+=size;
- if(mem_len_arr[v]==0)
+ mem_len_arr[v] -= size;
+ mem_offset_arr[v] += size;
+ if(mem_len_arr[v] == 0)
v++;
/* Update file information */
- dset_len_arr[u]-=size;
- dset_offset_arr[u]+=size;
- if(dset_len_arr[u]==0)
+ dset_len_arr[u] -= size;
+ dset_offset_arr[u] += size;
+ if(dset_len_arr[u] == 0)
u++;
/* Increment number of bytes copied */
- total_size+=size;
+ total_size += size;
} /* end for */
} /* end if */
else {
/* Work through all the sequences */
- for(u=*dset_curr_seq, v=*mem_curr_seq; u<dset_max_nseq && v<mem_max_nseq; ) {
+ for(u = *dset_curr_seq, v = *mem_curr_seq; u < dset_max_nseq && v < mem_max_nseq; ) {
/* Choose smallest buffer to write */
- if(mem_len_arr[v]<dset_len_arr[u])
- size=mem_len_arr[v];
+ if(mem_len_arr[v] < dset_len_arr[u])
+ size = mem_len_arr[v];
else
- size=dset_len_arr[u];
+ size = dset_len_arr[u];
/* Compute offset on disk */
- addr=store_contig->dset_addr+dset_offset_arr[u];
+ addr = store_contig->dset_addr + dset_offset_arr[u];
/* Compute offset in memory */
- buf = (unsigned char *)_buf + mem_offset_arr[v];
+ buf = (unsigned char *)io_info->u.rbuf + mem_offset_arr[v];
/* Write data */
- if (H5F_block_read(file, H5FD_MEM_DRAW, addr, size, io_info->dxpl_id, buf)<0)
+ if(H5F_block_read(file, H5FD_MEM_DRAW, addr, size, io_info->dxpl_id, buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed")
/* Update memory information */
- mem_len_arr[v]-=size;
- mem_offset_arr[v]+=size;
- if(mem_len_arr[v]==0)
+ mem_len_arr[v] -= size;
+ mem_offset_arr[v] += size;
+ if(mem_len_arr[v] == 0)
v++;
/* Update file information */
- dset_len_arr[u]-=size;
- dset_offset_arr[u]+=size;
- if(dset_len_arr[u]==0)
+ dset_len_arr[u] -= size;
+ dset_offset_arr[u] += size;
+ if(dset_len_arr[u] == 0)
u++;
/* Increment number of bytes copied */
- total_size+=size;
+ total_size += size;
} /* end for */
} /* end else */
/* Update current sequence vectors */
- *dset_curr_seq=u;
- *mem_curr_seq=v;
+ *dset_curr_seq = u;
+ *mem_curr_seq = v;
/* Set return value */
- H5_ASSIGN_OVERFLOW(ret_value,total_size,size_t,ssize_t);
+ H5_ASSIGN_OVERFLOW(ret_value, total_size, size_t, ssize_t);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -654,15 +839,14 @@ done:
ssize_t
H5D_contig_writevv(const H5D_io_info_t *io_info,
size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[],
- haddr_t UNUSED address, void UNUSED *pointer, const void *_buf)
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[])
{
H5F_t *file = io_info->dset->oloc.file; /* File for dataset */
- H5D_rdcdc_t *dset_contig=&(io_info->dset->shared->cache.contig); /* Cached information about contiguous data */
- const H5D_contig_storage_t *store_contig=&(io_info->store->contig); /* Contiguous storage info for this I/O operation */
- const unsigned char *buf=_buf; /* Pointer to buffer to fill */
+ H5D_rdcdc_t *dset_contig = &(io_info->dset->shared->cache.contig); /* Cached information about contiguous data */
+ const H5D_contig_storage_t *store_contig = &(io_info->store->contig); /* Contiguous storage info for this I/O operation */
+ const unsigned char *buf = (const unsigned char *)io_info->u.wbuf; /* Pointer to buffer to fill */
haddr_t addr; /* Actual address to read */
- size_t total_size=0; /* Size of sequence in bytes */
+ size_t total_size = 0; /* Size of sequence in bytes */
size_t size; /* Size of sequence in bytes */
size_t u; /* Counting variable */
size_t v; /* Counting variable */
@@ -671,17 +855,16 @@ H5D_contig_writevv(const H5D_io_info_t *io_info,
FUNC_ENTER_NOAPI(H5D_contig_writevv, FAIL)
/* Check args */
- assert(io_info);
- assert(io_info->dset);
- assert(io_info->store);
- assert(buf);
+ HDassert(io_info);
+ HDassert(io_info->dset);
+ HDassert(io_info->store);
+ HDassert(buf);
/* Check if data sieving is enabled */
if(H5F_HAS_FEATURE(file,H5FD_FEAT_DATA_SIEVE)) {
haddr_t sieve_start=HADDR_UNDEF, sieve_end=HADDR_UNDEF; /* Start & end locations of sieve buffer */
haddr_t contig_end; /* End locations of block to write */
size_t sieve_size=(size_t)-1; /* size of sieve buffer */
- haddr_t abs_eoa; /* Absolute end of file address */
haddr_t rel_eoa; /* Relative end of file address */
hsize_t max_data; /* Actual maximum size of data to cache */
@@ -708,18 +891,18 @@ H5D_contig_writevv(const H5D_io_info_t *io_info,
addr=store_contig->dset_addr+dset_offset_arr[u];
/* Compute offset in memory */
- buf = (const unsigned char *)_buf + mem_offset_arr[v];
+ buf = (const unsigned char *)io_info->u.wbuf + mem_offset_arr[v];
/* No data sieve buffer yet, go allocate one */
if(dset_contig->sieve_buf==NULL) {
/* Check if we can actually hold the I/O request in the sieve buffer */
if(size>dset_contig->sieve_buf_size) {
- if (H5F_block_write(file, H5FD_MEM_DRAW, addr, size, io_info->dxpl_id, buf)<0)
+ if(H5F_block_write(file, H5FD_MEM_DRAW, addr, size, io_info->dxpl_id, buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed")
} /* end if */
else {
/* Allocate room for the data sieve buffer */
- if (NULL==(dset_contig->sieve_buf=H5FL_BLK_MALLOC(sieve_buf,dset_contig->sieve_buf_size)))
+ if(NULL == (dset_contig->sieve_buf = H5FL_BLK_MALLOC(sieve_buf, dset_contig->sieve_buf_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
#ifdef H5_CLEAR_MEMORY
if(dset_contig->sieve_size > size)
@@ -730,12 +913,9 @@ if(dset_contig->sieve_size > size)
dset_contig->sieve_loc=addr;
/* Make certain we don't read off the end of the file */
- if (HADDR_UNDEF==(abs_eoa=H5F_get_eoa(file)))
+ if(HADDR_UNDEF == (rel_eoa = H5F_get_eoa(file, H5FD_MEM_DRAW)))
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size")
- /* Adjust absolute EOA address to relative EOA address */
- rel_eoa=abs_eoa-H5F_get_base_addr(file);
-
/* Set up the buffer parameters */
max_data=store_contig->dset_size-dset_offset_arr[u];
@@ -750,15 +930,15 @@ if(dset_contig->sieve_size > size)
} /* end if */
/* Grab the data out of the buffer (must be first piece of data in buffer ) */
- HDmemcpy(dset_contig->sieve_buf,buf,size);
+ HDmemcpy(dset_contig->sieve_buf, buf, size);
/* Set sieve buffer dirty flag */
- dset_contig->sieve_dirty=1;
+ dset_contig->sieve_dirty = 1;
/* Stash local copies of these values */
- sieve_start=dset_contig->sieve_loc;
- sieve_size=dset_contig->sieve_size;
- sieve_end=sieve_start+sieve_size;
+ sieve_start = dset_contig->sieve_loc;
+ sieve_size = dset_contig->sieve_size;
+ sieve_end = sieve_start + sieve_size;
} /* end else */
} /* end if */
else {
@@ -767,13 +947,13 @@ if(dset_contig->sieve_size > size)
/* If entire write is within the sieve buffer, write it to the buffer */
if(addr>=sieve_start && contig_end<sieve_end) {
- unsigned char *base_sieve_buf=dset_contig->sieve_buf+(addr-sieve_start);
+ unsigned char *base_sieve_buf = dset_contig->sieve_buf + (addr - sieve_start);
/* Put the data into the sieve buffer */
- HDmemcpy(base_sieve_buf,buf,size);
+ HDmemcpy(base_sieve_buf, buf, size);
/* Set sieve buffer dirty flag */
- dset_contig->sieve_dirty=1;
+ dset_contig->sieve_dirty = 1;
} /* end if */
/* Entire request is not within this data sieve buffer */
else {
@@ -798,7 +978,7 @@ if(dset_contig->sieve_size > size)
} /* end if */
/* Write directly from the user's buffer */
- if (H5F_block_write(file, H5FD_MEM_DRAW, addr, size, io_info->dxpl_id, buf)<0)
+ if(H5F_block_write(file, H5FD_MEM_DRAW, addr, size, io_info->dxpl_id, buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed")
} /* end if */
/* Element size fits within the buffer size */
@@ -808,30 +988,30 @@ if(dset_contig->sieve_size > size)
(size+sieve_size)<=dset_contig->sieve_buf_size &&
dset_contig->sieve_dirty) {
/* Prepend to existing sieve buffer */
- if((addr+size)==sieve_start) {
+ if((addr + size) == sieve_start) {
/* Move existing sieve information to correct location */
- HDmemmove(dset_contig->sieve_buf+size,dset_contig->sieve_buf,dset_contig->sieve_size);
+ HDmemmove(dset_contig->sieve_buf + size, dset_contig->sieve_buf, dset_contig->sieve_size);
/* Copy in new information (must be first in sieve buffer) */
- HDmemcpy(dset_contig->sieve_buf,buf,size);
+ HDmemcpy(dset_contig->sieve_buf, buf, size);
/* Adjust sieve location */
- dset_contig->sieve_loc=addr;
+ dset_contig->sieve_loc = addr;
} /* end if */
/* Append to existing sieve buffer */
else {
/* Copy in new information */
- HDmemcpy(dset_contig->sieve_buf+sieve_size,buf,size);
+ HDmemcpy(dset_contig->sieve_buf + sieve_size, buf, size);
} /* end else */
/* Adjust sieve size */
dset_contig->sieve_size += size;
/* Update local copies of sieve information */
- sieve_start=dset_contig->sieve_loc;
- sieve_size=dset_contig->sieve_size;
- sieve_end=sieve_start+sieve_size;
+ sieve_start = dset_contig->sieve_loc;
+ sieve_size = dset_contig->sieve_size;
+ sieve_end = sieve_start + sieve_size;
} /* end if */
/* Can't add the new data onto the existing sieve buffer */
else {
@@ -849,12 +1029,9 @@ if(dset_contig->sieve_size > size)
dset_contig->sieve_loc=addr;
/* Make certain we don't read off the end of the file */
- if (HADDR_UNDEF==(abs_eoa=H5F_get_eoa(file)))
+ if(HADDR_UNDEF == (rel_eoa = H5F_get_eoa(file, H5FD_MEM_DRAW)))
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size")
- /* Adjust absolute EOA address to relative EOA address */
- rel_eoa=abs_eoa-H5F_get_base_addr(file);
-
/* Only need this when resizing sieve buffer */
max_data=store_contig->dset_size-dset_offset_arr[u];
@@ -875,73 +1052,73 @@ if(dset_contig->sieve_size > size)
} /* end if */
/* Grab the data out of the buffer (must be first piece of data in buffer ) */
- HDmemcpy(dset_contig->sieve_buf,buf,size);
+ HDmemcpy(dset_contig->sieve_buf, buf, size);
/* Set sieve buffer dirty flag */
- dset_contig->sieve_dirty=1;
+ dset_contig->sieve_dirty = 1;
} /* end else */
} /* end else */
} /* end else */
} /* end else */
/* Update memory information */
- mem_len_arr[v]-=size;
- mem_offset_arr[v]+=size;
- if(mem_len_arr[v]==0)
+ mem_len_arr[v] -= size;
+ mem_offset_arr[v] += size;
+ if(mem_len_arr[v] == 0)
v++;
/* Update file information */
- dset_len_arr[u]-=size;
- dset_offset_arr[u]+=size;
- if(dset_len_arr[u]==0)
+ dset_len_arr[u] -= size;
+ dset_offset_arr[u] += size;
+ if(dset_len_arr[u] == 0)
u++;
/* Increment number of bytes copied */
- total_size+=size;
+ total_size += size;
} /* end for */
} /* end if */
else {
/* Work through all the sequences */
- for(u=*dset_curr_seq, v=*mem_curr_seq; u<dset_max_nseq && v<mem_max_nseq; ) {
+ for(u = *dset_curr_seq, v = *mem_curr_seq; u < dset_max_nseq && v < mem_max_nseq; ) {
/* Choose smallest buffer to write */
- if(mem_len_arr[v]<dset_len_arr[u])
- size=mem_len_arr[v];
+ if(mem_len_arr[v] < dset_len_arr[u])
+ size = mem_len_arr[v];
else
- size=dset_len_arr[u];
+ size = dset_len_arr[u];
/* Compute offset on disk */
- addr=store_contig->dset_addr+dset_offset_arr[u];
+ addr = store_contig->dset_addr + dset_offset_arr[u];
/* Compute offset in memory */
- buf = (const unsigned char *)_buf + mem_offset_arr[v];
+ buf = (const unsigned char *)io_info->u.wbuf + mem_offset_arr[v];
/* Write data */
- if (H5F_block_write(file, H5FD_MEM_DRAW, addr, size, io_info->dxpl_id, buf)<0)
+ if(H5F_block_write(file, H5FD_MEM_DRAW, addr, size, io_info->dxpl_id, buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed")
/* Update memory information */
- mem_len_arr[v]-=size;
- mem_offset_arr[v]+=size;
- if(mem_len_arr[v]==0)
+ mem_len_arr[v] -= size;
+ mem_offset_arr[v] += size;
+ if(mem_len_arr[v] == 0)
v++;
/* Update file information */
- dset_len_arr[u]-=size;
- dset_offset_arr[u]+=size;
- if(dset_len_arr[u]==0)
+ dset_len_arr[u] -= size;
+ dset_offset_arr[u] += size;
+ if(dset_len_arr[u] == 0)
u++;
/* Increment number of bytes copied */
- total_size+=size;
+ total_size += size;
} /* end for */
} /* end else */
/* Update current sequence vectors */
- *dset_curr_seq=u;
- *mem_curr_seq=v;
+ *dset_curr_seq = u;
+ *mem_curr_seq = v;
/* Set return value */
- H5_ASSIGN_OVERFLOW(ret_value,total_size,size_t,ssize_t);
+ H5_ASSIGN_OVERFLOW(ret_value, total_size, size_t, ssize_t);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -964,7 +1141,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5D_contig_copy(H5F_t *f_src, const H5O_layout_t *layout_src, H5F_t *f_dst,
+H5D_contig_copy(H5F_t *f_src, const H5O_layout_t *layout_src, H5F_t *f_dst,
H5O_layout_t *layout_dst, H5T_t *dt_src, H5O_copy_t *cpy_info, hid_t dxpl_id)
{
haddr_t addr_src; /* File offset in source dataset */
@@ -1005,7 +1182,7 @@ H5D_contig_copy(H5F_t *f_src, const H5O_layout_t *layout_src, H5F_t *f_dst,
HDassert(dt_src);
/* Allocate space for destination raw data */
- if(H5D_contig_create(f_dst, dxpl_id, layout_dst) < 0)
+ if(H5D_contig_alloc(f_dst, dxpl_id, layout_dst) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to allocate contiguous storage")
/* Set up number of bytes to copy, and initial buffer size */
@@ -1017,7 +1194,7 @@ H5D_contig_copy(H5F_t *f_src, const H5O_layout_t *layout_src, H5F_t *f_dst,
/* Create datatype ID for src datatype. We may or may not use this ID,
* but this ensures that the src datatype will be freed.
*/
- if((tid_src = H5I_register(H5I_DATATYPE, dt_src)) < 0)
+ if((tid_src = H5I_register(H5I_DATATYPE, dt_src, FALSE)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register source file datatype")
/* If there's a VLEN source datatype, set up type conversion information */
@@ -1025,31 +1202,31 @@ H5D_contig_copy(H5F_t *f_src, const H5O_layout_t *layout_src, H5F_t *f_dst,
/* create a memory copy of the variable-length datatype */
if(NULL == (dt_mem = H5T_copy(dt_src, H5T_COPY_TRANSIENT)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy")
- if((tid_mem = H5I_register(H5I_DATATYPE, dt_mem)) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register memory datatype")
+ if((tid_mem = H5I_register(H5I_DATATYPE, dt_mem, FALSE)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register memory datatype")
/* create variable-length datatype at the destinaton file */
if(NULL == (dt_dst = H5T_copy(dt_src, H5T_COPY_TRANSIENT)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy")
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to copy")
if(H5T_set_loc(dt_dst, f_dst, H5T_LOC_DISK) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "cannot mark datatype on disk")
- if((tid_dst = H5I_register(H5I_DATATYPE, dt_dst)) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register destination file datatype")
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "cannot mark datatype on disk")
+ if((tid_dst = H5I_register(H5I_DATATYPE, dt_dst, FALSE)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register destination file datatype")
/* Set up the conversion functions */
if(NULL == (tpath_src_mem = H5T_path_find(dt_src, dt_mem, NULL, NULL, dxpl_id, FALSE)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert between src and mem datatypes")
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to convert between src and mem datatypes")
if(NULL == (tpath_mem_dst = H5T_path_find(dt_mem, dt_dst, NULL, NULL, dxpl_id, FALSE)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert between mem and dst datatypes")
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to convert between mem and dst datatypes")
/* Determine largest datatype size */
if(0 == (src_dt_size = H5T_get_size(dt_src)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to determine datatype size")
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to determine datatype size")
if(0 == (mem_dt_size = H5T_get_size(dt_mem)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to determine datatype size")
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to determine datatype size")
max_dt_size = MAX(src_dt_size, mem_dt_size);
if(0 == (dst_dt_size = H5T_get_size(dt_dst)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to determine datatype size")
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to determine datatype size")
max_dt_size = MAX(max_dt_size, dst_dt_size);
/* Set maximum number of whole elements that fit in buffer */
@@ -1072,7 +1249,7 @@ H5D_contig_copy(H5F_t *f_src, const H5O_layout_t *layout_src, H5F_t *f_dst,
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create simple dataspace")
/* Atomize */
- if((buf_sid = H5I_register(H5I_DATASPACE, buf_space)) < 0) {
+ if((buf_sid = H5I_register(H5I_DATASPACE, buf_space, FALSE)) < 0) {
H5S_close(buf_space);
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace ID")
} /* end if */
@@ -1085,7 +1262,7 @@ H5D_contig_copy(H5F_t *f_src, const H5O_layout_t *layout_src, H5F_t *f_dst,
if(H5T_get_class(dt_src, FALSE) == H5T_REFERENCE) {
/* Need to fix values of references when copying across files */
if(f_src != f_dst)
- fix_ref = TRUE;
+ fix_ref = TRUE;
} /* end if */
/* Set the number of bytes to read & write to the buffer size */
@@ -1190,24 +1367,23 @@ H5D_contig_copy(H5F_t *f_src, const H5O_layout_t *layout_src, H5F_t *f_dst,
} /* end while */
done:
- if(buf_sid > 0)
- if(H5I_dec_ref(buf_sid) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary dataspace ID")
+ if(buf_sid > 0 && H5I_dec_ref(buf_sid, FALSE) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "can't decrement temporary dataspace ID")
if(tid_src > 0)
- if(H5I_dec_ref(tid_src) < 0)
+ if(H5I_dec_ref(tid_src, FALSE) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
if(tid_dst > 0)
- if(H5I_dec_ref(tid_dst) < 0)
+ if(H5I_dec_ref(tid_dst, FALSE) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
if(tid_mem > 0)
- if(H5I_dec_ref(tid_mem) < 0)
+ if(H5I_dec_ref(tid_mem, FALSE) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
if(buf)
- H5FL_BLK_FREE(type_conv, buf);
+ (void)H5FL_BLK_FREE(type_conv, buf);
if(reclaim_buf)
- H5FL_BLK_FREE(type_conv, reclaim_buf);
+ (void)H5FL_BLK_FREE(type_conv, reclaim_buf);
if(bkg)
- H5FL_BLK_FREE(type_conv, bkg);
+ (void)H5FL_BLK_FREE(type_conv, bkg);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_contig_copy() */
diff --git a/src/H5Ddbg.c b/src/H5Ddbg.c
index 4ca5b21..714c2e3 100644
--- a/src/H5Ddbg.c
+++ b/src/H5Ddbg.c
@@ -113,7 +113,7 @@ H5Ddebug(hid_t dset_id)
/* Print B-tree information */
if(H5D_CHUNKED == dset->shared->layout.type)
- (void)H5D_istore_dump_btree(dset->oloc.file, H5AC_dxpl_id, stdout, dset->shared->layout.u.chunk.ndims, dset->shared->layout.u.chunk.addr);
+ (void)H5D_chunk_dump_index(dset, H5AC_dxpl_id, stdout);
else if(H5D_CONTIGUOUS == dset->shared->layout.type)
HDfprintf(stdout, " %-10s %a\n", "Address:", dset->shared->layout.u.contig.addr);
diff --git a/src/H5Ddeprec.c b/src/H5Ddeprec.c
index 95f89cf..5b0621e 100644
--- a/src/H5Ddeprec.c
+++ b/src/H5Ddeprec.c
@@ -156,7 +156,7 @@ H5Dcreate1(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id,
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name")
if(H5I_DATATYPE != H5I_get_type(type_id))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype ID")
- if(NULL == (space = H5I_object_verify(space_id,H5I_DATASPACE)))
+ if(NULL == (space = (const H5S_t *)H5I_object_verify(space_id,H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace ID")
if(H5P_DEFAULT == dcpl_id)
dcpl_id = H5P_DATASET_CREATE_DEFAULT;
@@ -170,7 +170,7 @@ H5Dcreate1(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id,
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create dataset")
/* Register the new dataset to get an ID for it */
- if((ret_value = H5I_register(H5I_DATASET, dset)) < 0)
+ if((ret_value = H5I_register(H5I_DATASET, dset, TRUE)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register dataset")
done:
@@ -209,6 +209,7 @@ H5Dopen1(hid_t loc_id, const char *name)
H5O_loc_t oloc; /* Dataset object location */
H5O_type_t obj_type; /* Type of object at location */
hbool_t loc_found = FALSE; /* Location at 'name' found */
+ hid_t dapl_id = H5P_DATASET_ACCESS_DEFAULT; /* dapl to use to open dataset */
hid_t dxpl_id = H5AC_dxpl_id; /* dxpl to use to open datset */
hid_t ret_value;
@@ -238,11 +239,11 @@ H5Dopen1(hid_t loc_id, const char *name)
HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, FAIL, "not a dataset")
/* Open the dataset */
- if((dset = H5D_open(&dset_loc, dxpl_id)) == NULL)
+ if((dset = H5D_open(&dset_loc, dapl_id, dxpl_id)) == NULL)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't open dataset")
/* Register an atom for the dataset */
- if((ret_value = H5I_register(H5I_DATASET, dset)) < 0)
+ if((ret_value = H5I_register(H5I_DATASET, dset, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "can't register dataset atom")
done:
@@ -278,7 +279,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5Dextend(hid_t dset_id, const hsize_t *size)
+H5Dextend(hid_t dset_id, const hsize_t size[])
{
H5D_t *dset;
herr_t ret_value = SUCCEED; /* Return value */
@@ -344,20 +345,19 @@ H5D_extend(H5D_t *dataset, const hsize_t *size, hid_t dxpl_id)
/* Updated the dataset's info if the dataspace was successfully extended */
if(changed) {
- /* Save the new dataspace in the file if necessary */
- if(H5S_write(&(dataset->oloc), space, TRUE, dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to update file with new dataspace")
-
/* Update the index values for the cached chunks for this dataset */
if(H5D_CHUNKED == dataset->shared->layout.type)
- if(H5D_istore_update_cache(dataset, dxpl_id) < 0)
+ if(H5D_chunk_update_cache(dataset, dxpl_id) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to update cached chunk indices")
/* Allocate space for the new parts of the dataset, if appropriate */
fill = &dataset->shared->dcpl_cache.fill;
if(fill->alloc_time == H5D_ALLOC_TIME_EARLY)
- if(H5D_alloc_storage(dataset->oloc.file, dxpl_id, dataset, H5D_ALLOC_EXTEND, TRUE, FALSE) < 0)
+ if(H5D_alloc_storage(dataset, dxpl_id, H5D_ALLOC_EXTEND, FALSE) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize dataset with fill value")
+
+ /* Mark the dataspace as dirty, for later writing to the file */
+ dataset->shared->space_dirty = TRUE;
} /* end if */
done:
diff --git a/src/H5Defl.c b/src/H5Defl.c
index c8d1098..2dcad4d 100644
--- a/src/H5Defl.c
+++ b/src/H5Defl.c
@@ -33,30 +33,166 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5Fprivate.h" /* Files */
+
/****************/
/* Local Macros */
/****************/
+
/******************/
/* Local Typedefs */
/******************/
+
/********************/
/* Local Prototypes */
/********************/
-static herr_t H5D_efl_read (const H5O_efl_t *efl, haddr_t addr, size_t size,
+
+/* Layout operation callbacks */
+static herr_t H5D_efl_new(H5F_t *f, hid_t dapl_id, hid_t dxpl_id, H5D_t *dset,
+ const H5P_genplist_t *dc_plist);
+static herr_t H5D_efl_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
+ H5D_chunk_map_t *cm);
+static ssize_t H5D_efl_readvv(const H5D_io_info_t *io_info,
+ size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[],
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[]);
+static ssize_t H5D_efl_writevv(const H5D_io_info_t *io_info,
+ size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[],
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[]);
+
+/* Helper routines */
+static herr_t H5D_efl_read(const H5O_efl_t *efl, haddr_t addr, size_t size,
uint8_t *buf);
static herr_t H5D_efl_write(const H5O_efl_t *efl, haddr_t addr, size_t size,
const uint8_t *buf);
+
/*********************/
/* Package Variables */
/*********************/
+/* External File List (EFL) storage layout I/O ops */
+const H5D_layout_ops_t H5D_LOPS_EFL[1] = {{
+ H5D_efl_new,
+ H5D_efl_io_init,
+ H5D_contig_read,
+ H5D_contig_write,
+#ifdef H5_HAVE_PARALLEL
+ NULL,
+ NULL,
+#endif /* H5_HAVE_PARALLEL */
+ H5D_efl_readvv,
+ H5D_efl_writevv,
+ NULL
+}};
+
+
/*******************/
/* Local Variables */
/*******************/
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_efl_new
+ *
+ * Purpose: Constructs new EFL layout information for dataset
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, May 22, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_efl_new(H5F_t *f, hid_t UNUSED dapl_id, hid_t UNUSED dxpl_id, H5D_t *dset,
+ const H5P_genplist_t *dc_plist)
+{
+ size_t dt_size; /* Size of datatype */
+ hsize_t dim[H5O_LAYOUT_NDIMS]; /* Current size of data in elements */
+ hsize_t max_dim[H5O_LAYOUT_NDIMS]; /* Maximum size of data in elements */
+ hssize_t tmp_size; /* Temporary holder for raw data size */
+ hsize_t max_points; /* Maximum elements */
+ hsize_t max_storage; /* Maximum storage size */
+ int ndims; /* Rank of dataspace */
+ int i; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_efl_new)
+
+ /* Sanity checks */
+ HDassert(f);
+ HDassert(dset);
+ HDassert(dc_plist);
+
+ /*
+ * The maximum size of the dataset cannot exceed the storage size.
+ * Also, only the slowest varying dimension of a simple data space
+ * can be extendible (currently only for external data storage).
+ */
+ dset->shared->layout.u.contig.addr = HADDR_UNDEF; /* Initialize to no address */
+
+ /* Check for invalid dataset dimensions */
+ if((ndims = H5S_get_simple_extent_dims(dset->shared->space, dim, max_dim)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize contiguous storage")
+ for(i = 1; i < ndims; i++)
+ if(max_dim[i] > dim[i])
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "only the first dimension can be extendible")
+
+ /* Retrieve the size of the dataset's datatype */
+ if(0 == (dt_size = H5T_get_size(dset->shared->type)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to determine datatype size")
+
+ /* Check for storage overflows */
+ max_points = H5S_get_npoints_max(dset->shared->space);
+ max_storage = H5O_efl_total_size(&dset->shared->dcpl_cache.efl);
+ if(H5S_UNLIMITED == max_points) {
+ if(H5O_EFL_UNLIMITED != max_storage)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unlimited data space but finite storage")
+ } /* end if */
+ else if((max_points * dt_size) < max_points)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "data space * type size overflowed")
+ else if((max_points * dt_size) > max_storage)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "data space size exceeds external storage size")
+
+ /* Compute the total size of dataset */
+ tmp_size = H5S_GET_EXTENT_NPOINTS(dset->shared->space) * dt_size;
+ H5_ASSIGN_OVERFLOW(dset->shared->layout.u.contig.size, tmp_size, hssize_t, hsize_t);
+
+ /* Get the sieve buffer size for this dataset */
+ dset->shared->cache.contig.sieve_buf_size = H5F_SIEVE_BUF_SIZE(f);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_efl_new() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_efl_io_init
+ *
+ * Purpose: Performs initialization before any sort of I/O on the raw data
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, March 20, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_efl_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t UNUSED *type_info,
+ hsize_t UNUSED nelmts, const H5S_t UNUSED *file_space, const H5S_t UNUSED *mem_space,
+ H5D_chunk_map_t UNUSED *cm)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_efl_io_init)
+
+ HDmemcpy(&io_info->store->efl, &(io_info->dset->shared->dcpl_cache.efl), sizeof(H5O_efl_t));
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5D_efl_io_init() */
+
/*-------------------------------------------------------------------------
* Function: H5D_efl_read
@@ -77,26 +213,26 @@ static herr_t H5D_efl_write(const H5O_efl_t *efl, haddr_t addr, size_t size,
*-------------------------------------------------------------------------
*/
static herr_t
-H5D_efl_read (const H5O_efl_t *efl, haddr_t addr, size_t size, uint8_t *buf)
+H5D_efl_read(const H5O_efl_t *efl, haddr_t addr, size_t size, uint8_t *buf)
{
- int fd=-1;
+ int fd = -1;
size_t to_read;
#ifndef NDEBUG
hsize_t tempto_read;
#endif /* NDEBUG */
- hsize_t skip=0;
+ hsize_t skip = 0;
haddr_t cur;
ssize_t n;
size_t u; /* Local index variable */
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5D_efl_read)
/* Check args */
- assert (efl && efl->nused>0);
- assert (H5F_addr_defined (addr));
- assert (size < SIZET_MAX);
- assert (buf || 0==size);
+ HDassert(efl && efl->nused>0);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(size < SIZET_MAX);
+ HDassert(buf || 0 == size);
/* Find the first efl member from which to read */
for (u=0, cur=0; u<efl->nused; u++) {
@@ -109,7 +245,7 @@ H5D_efl_read (const H5O_efl_t *efl, haddr_t addr, size_t size, uint8_t *buf)
/* Read the data */
while (size) {
- assert(buf);
+ HDassert(buf);
if (u>=efl->nused)
HGOTO_ERROR (H5E_EFL, H5E_OVERFLOW, FAIL, "read past logical end of file")
if (H5F_OVERFLOW_HSIZET2OFFT (efl->slot[u].offset+skip))
@@ -165,25 +301,25 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5D_efl_write (const H5O_efl_t *efl, haddr_t addr, size_t size, const uint8_t *buf)
+H5D_efl_write(const H5O_efl_t *efl, haddr_t addr, size_t size, const uint8_t *buf)
{
- int fd=-1;
+ int fd = -1;
size_t to_write;
#ifndef NDEBUG
hsize_t tempto_write;
#endif /* NDEBUG */
haddr_t cur;
- hsize_t skip=0;
+ hsize_t skip = 0;
size_t u; /* Local index variable */
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5D_efl_write)
/* Check args */
- assert (efl && efl->nused>0);
- assert (H5F_addr_defined (addr));
- assert (size < SIZET_MAX);
- assert (buf || 0==size);
+ HDassert(efl && efl->nused>0);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(size < SIZET_MAX);
+ HDassert(buf || 0 == size);
/* Find the first efl member in which to write */
for (u=0, cur=0; u<efl->nused; u++) {
@@ -248,71 +384,68 @@ done:
* Programmer: Quincey Koziol
* Wednesday, May 7, 2003
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
-ssize_t
+static ssize_t
H5D_efl_readvv(const H5D_io_info_t *io_info,
size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[],
- haddr_t UNUSED address, void UNUSED *pointer/*in*/, void *_buf)
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[])
{
- const H5O_efl_t *efl=&(io_info->store->efl); /* Pointer to efl info */
+ const H5O_efl_t *efl = &(io_info->store->efl); /* Pointer to efl info */
unsigned char *buf; /* Pointer to buffer to write */
haddr_t addr; /* Actual address to read */
- size_t total_size=0; /* Total size of sequence in bytes */
+ size_t total_size = 0; /* Total size of sequence in bytes */
size_t size; /* Size of sequence in bytes */
size_t u; /* Counting variable */
size_t v; /* Counting variable */
ssize_t ret_value; /* Return value */
- FUNC_ENTER_NOAPI(H5D_efl_readvv, FAIL)
+ FUNC_ENTER_NOAPI_NOINIT(H5D_efl_readvv)
/* Check args */
- assert (efl && efl->nused>0);
- assert (_buf);
+ HDassert(efl && efl->nused > 0);
+ HDassert(io_info->u.rbuf);
/* Work through all the sequences */
- for(u=*dset_curr_seq, v=*mem_curr_seq; u<dset_max_nseq && v<mem_max_nseq; ) {
+ for(u = *dset_curr_seq, v = *mem_curr_seq; u < dset_max_nseq && v < mem_max_nseq; ) {
/* Choose smallest buffer to write */
- if(mem_len_arr[v]<dset_len_arr[u])
- size=mem_len_arr[v];
+ if(mem_len_arr[v] < dset_len_arr[u])
+ size = mem_len_arr[v];
else
- size=dset_len_arr[u];
+ size = dset_len_arr[u];
/* Compute offset on disk */
- addr=dset_offset_arr[u];
+ addr = dset_offset_arr[u];
/* Compute offset in memory */
- buf = (unsigned char *)_buf + mem_offset_arr[v];
+ buf = (unsigned char *)io_info->u.rbuf + mem_offset_arr[v];
/* Read data */
- if (H5D_efl_read(efl, addr, size, buf)<0)
+ if(H5D_efl_read(efl, addr, size, buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed")
/* Update memory information */
- mem_len_arr[v]-=size;
- mem_offset_arr[v]+=size;
- if(mem_len_arr[v]==0)
+ mem_len_arr[v] -= size;
+ mem_offset_arr[v] += size;
+ if(mem_len_arr[v] == 0)
v++;
/* Update file information */
- dset_len_arr[u]-=size;
- dset_offset_arr[u]+=size;
- if(dset_len_arr[u]==0)
+ dset_len_arr[u] -= size;
+ dset_offset_arr[u] += size;
+ if(dset_len_arr[u] == 0)
u++;
/* Increment number of bytes copied */
- total_size+=size;
+ total_size += size;
} /* end for */
/* Update current sequence vectors */
- *dset_curr_seq=u;
- *mem_curr_seq=v;
+ *dset_curr_seq = u;
+ *mem_curr_seq = v;
/* Set return value */
- H5_ASSIGN_OVERFLOW(ret_value,total_size,size_t,ssize_t);
+ H5_ASSIGN_OVERFLOW(ret_value, total_size, size_t, ssize_t);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -332,71 +465,68 @@ done:
* Programmer: Quincey Koziol
* Friday, May 2, 2003
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
-ssize_t
+static ssize_t
H5D_efl_writevv(const H5D_io_info_t *io_info,
size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[],
- haddr_t UNUSED address, void UNUSED *pointer/*in*/, const void *_buf)
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[])
{
- const H5O_efl_t *efl=&(io_info->store->efl); /* Pointer to efl info */
+ const H5O_efl_t *efl = &(io_info->store->efl); /* Pointer to efl info */
const unsigned char *buf; /* Pointer to buffer to write */
haddr_t addr; /* Actual address to read */
- size_t total_size=0; /* Total size of sequence in bytes */
+ size_t total_size = 0; /* Total size of sequence in bytes */
size_t size; /* Size of sequence in bytes */
size_t u; /* Counting variable */
size_t v; /* Counting variable */
ssize_t ret_value; /* Return value */
- FUNC_ENTER_NOAPI(H5D_efl_writevv, FAIL)
+ FUNC_ENTER_NOAPI_NOINIT(H5D_efl_writevv)
/* Check args */
- assert (efl && efl->nused>0);
- assert (_buf);
+ HDassert(efl && efl->nused > 0);
+ HDassert(io_info->u.wbuf);
/* Work through all the sequences */
- for(u=*dset_curr_seq, v=*mem_curr_seq; u<dset_max_nseq && v<mem_max_nseq; ) {
+ for(u = *dset_curr_seq, v = *mem_curr_seq; u < dset_max_nseq && v < mem_max_nseq; ) {
/* Choose smallest buffer to write */
- if(mem_len_arr[v]<dset_len_arr[u])
- size=mem_len_arr[v];
+ if(mem_len_arr[v] < dset_len_arr[u])
+ size = mem_len_arr[v];
else
- size=dset_len_arr[u];
+ size = dset_len_arr[u];
/* Compute offset on disk */
- addr=dset_offset_arr[u];
+ addr = dset_offset_arr[u];
/* Compute offset in memory */
- buf = (const unsigned char *)_buf + mem_offset_arr[v];
+ buf = (const unsigned char *)io_info->u.wbuf + mem_offset_arr[v];
/* Write data */
- if (H5D_efl_write(efl, addr, size, buf)<0)
+ if(H5D_efl_write(efl, addr, size, buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed")
/* Update memory information */
- mem_len_arr[v]-=size;
- mem_offset_arr[v]+=size;
- if(mem_len_arr[v]==0)
+ mem_len_arr[v] -= size;
+ mem_offset_arr[v] += size;
+ if(mem_len_arr[v] == 0)
v++;
/* Update file information */
- dset_len_arr[u]-=size;
- dset_offset_arr[u]+=size;
- if(dset_len_arr[u]==0)
+ dset_len_arr[u] -= size;
+ dset_offset_arr[u] += size;
+ if(dset_len_arr[u] == 0)
u++;
/* Increment number of bytes copied */
- total_size+=size;
+ total_size += size;
} /* end for */
/* Update current sequence vectors */
- *dset_curr_seq=u;
- *mem_curr_seq=v;
+ *dset_curr_seq = u;
+ *mem_curr_seq = v;
/* Set return value */
- H5_ASSIGN_OVERFLOW(ret_value,total_size,size_t,ssize_t);
+ H5_ASSIGN_OVERFLOW(ret_value, total_size, size_t, ssize_t);
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5Dfill.c b/src/H5Dfill.c
index bfb4354..e8990b9 100644
--- a/src/H5Dfill.c
+++ b/src/H5Dfill.c
@@ -123,11 +123,11 @@ H5Dfill(const void *fill, hid_t fill_type_id, void *buf, hid_t buf_type_id, hid_
/* Check args */
if(buf == NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid buffer")
- if(NULL == (space = H5I_object_verify(space_id, H5I_DATASPACE)))
+ if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a dataspace")
- if(NULL == (fill_type = H5I_object_verify(fill_type_id, H5I_DATATYPE)))
+ if(NULL == (fill_type = (H5T_t *)H5I_object_verify(fill_type_id, H5I_DATATYPE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a datatype")
- if(NULL == (buf_type = H5I_object_verify(buf_type_id, H5I_DATATYPE)))
+ if(NULL == (buf_type = (H5T_t *)H5I_object_verify(buf_type_id, H5I_DATATYPE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a datatype")
/* Fill the selection in the memory buffer */
@@ -165,7 +165,7 @@ done:
If there's VL type of data, the address of the data is copied multiple
times into the buffer, causing some trouble when the data is released.
Instead, make multiple copies of fill value first, then do conversion
- on each element so that each of them has a copy of the VL data.
+ on each element so that each of them has a copy of the VL data.
--------------------------------------------------------------------------*/
herr_t
H5D_fill(const void *fill, const H5T_t *fill_type, void *buf,
@@ -229,16 +229,16 @@ H5D_fill(const void *fill, const H5T_t *fill_type, void *buf,
/* Construct source & destination datatype IDs, if we will need them */
if(!H5T_path_noop(tpath)) {
- if((src_id = H5I_register(H5I_DATATYPE, H5T_copy(fill_type, H5T_COPY_ALL))) < 0)
+ if((src_id = H5I_register(H5I_DATATYPE, H5T_copy(fill_type, H5T_COPY_ALL), FALSE)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register types for conversion")
- if((dst_id = H5I_register(H5I_DATATYPE, H5T_copy(buf_type, H5T_COPY_ALL))) < 0)
+ if((dst_id = H5I_register(H5I_DATATYPE, H5T_copy(buf_type, H5T_COPY_ALL), FALSE)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register types for conversion")
} /* end if */
- /* If there's VL type of data, make multiple copies of fill value first,
- * then do conversion on each element so that each of them has a copy
- * of the VL data.
+ /* If there's VL type of data, make multiple copies of fill value first,
+ * then do conversion on each element so that each of them has a copy
+ * of the VL data.
*/
if(TRUE == H5T_detect_class(fill_type, H5T_VLEN)) {
H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */
@@ -275,7 +275,7 @@ H5D_fill(const void *fill, const H5T_t *fill_type, void *buf,
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize memory selection information")
/* Scatter the data into memory */
- if(H5D_select_mscat(tmp_buf, space, &mem_iter, (size_t)nelmts, dxpl_cache, buf/*out*/) < 0) {
+ if(H5D_scatter_mem(tmp_buf, space, &mem_iter, (size_t)nelmts, dxpl_cache, buf/*out*/) < 0) {
H5S_SELECT_ITER_RELEASE(&mem_iter);
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "scatter failed")
} /* end if */
@@ -320,10 +320,10 @@ H5D_fill(const void *fill, const H5T_t *fill_type, void *buf,
HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "data type conversion failed")
/* Point at element buffer */
- fill_buf = elem_ptr;
+ fill_buf = (const uint8_t *)elem_ptr;
} /* end if */
else
- fill_buf = fill;
+ fill_buf = (const uint8_t *)fill;
/* Fill the selection in the memory buffer */
if(H5S_select_fill(fill_buf, dst_type_size, space, buf) < 0)
@@ -332,18 +332,18 @@ H5D_fill(const void *fill, const H5T_t *fill_type, void *buf,
} /* end else */
done:
- if(src_id != (-1) && H5I_dec_ref(src_id) < 0)
+ if(src_id != (-1) && H5I_dec_ref(src_id, FALSE) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
- if(dst_id != (-1) && H5I_dec_ref(dst_id) < 0)
+ if(dst_id != (-1) && H5I_dec_ref(dst_id, FALSE) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
if(tmp_buf)
- H5FL_BLK_FREE(type_conv, tmp_buf);
+ (void)H5FL_BLK_FREE(type_conv, tmp_buf);
if(elem_wb && H5WB_unwrap(elem_wb) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close wrapped buffer")
if(bkg_elem_wb && H5WB_unwrap(bkg_elem_wb) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close wrapped buffer")
if(bkg_buf)
- H5FL_BLK_FREE(type_conv, bkg_buf);
+ (void)H5FL_BLK_FREE(type_conv, bkg_buf);
FUNC_LEAVE_NOAPI(ret_value)
} /* H5D_fill() */
@@ -401,8 +401,8 @@ H5D_fill_init(H5D_fill_buf_info_t *fb_info, void *caller_fill_buf,
if(fb_info->has_vlen_fill_type) {
/* Create temporary datatype for conversion operation */
if(NULL == (fb_info->mem_type = H5T_copy(dset_type, H5T_COPY_REOPEN)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "unable to copy file datatype")
- if((fb_info->mem_tid = H5I_register(H5I_DATATYPE, fb_info->mem_type)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "unable to copy file datatype")
+ if((fb_info->mem_tid = H5I_register(H5I_DATATYPE, fb_info->mem_type, FALSE)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register memory datatype")
/* Retrieve sizes of memory & file datatypes */
@@ -636,9 +636,9 @@ H5D_fill_release(H5D_fill_buf_info_t *fb_info)
fb_info->fill_free_func(fb_info->fill_buf, fb_info->fill_free_info);
else {
if(fb_info->fill->buf)
- H5FL_BLK_FREE(non_zero_fill, fb_info->fill_buf);
+ (void)H5FL_BLK_FREE(non_zero_fill, fb_info->fill_buf);
else
- H5FL_BLK_FREE(zero_fill, fb_info->fill_buf);
+ (void)H5FL_BLK_FREE(zero_fill, fb_info->fill_buf);
} /* end else */
fb_info->fill_buf = NULL;
} /* end if */
@@ -673,11 +673,11 @@ H5D_fill_term(H5D_fill_buf_info_t *fb_info)
/* Free other resources for vlen fill values */
if(fb_info->has_vlen_fill_type) {
if(fb_info->mem_tid > 0)
- H5I_dec_ref(fb_info->mem_tid);
+ H5I_dec_ref(fb_info->mem_tid, FALSE);
else if(fb_info->mem_type)
H5T_close(fb_info->mem_type);
if(fb_info->bkg_buf)
- H5FL_BLK_FREE(type_conv, fb_info->bkg_buf);
+ (void)H5FL_BLK_FREE(type_conv, fb_info->bkg_buf);
} /* end if */
FUNC_LEAVE_NOAPI(SUCCEED)
diff --git a/src/H5Dint.c b/src/H5Dint.c
index aebc6f2..3018108 100644
--- a/src/H5Dint.c
+++ b/src/H5Dint.c
@@ -59,12 +59,15 @@ typedef struct {
/* General stuff */
static herr_t H5D_init_storage(H5D_t *dataset, hbool_t full_overwrite, hid_t dxpl_id);
+static herr_t H5D_get_dxpl_cache_real(hid_t dxpl_id, H5D_dxpl_cache_t *cache);
static H5D_shared_t *H5D_new(hid_t dcpl_id, hbool_t creating, hbool_t vl_type);
static herr_t H5D_init_type(H5F_t *file, const H5D_t *dset, hid_t type_id,
const H5T_t *type);
static herr_t H5D_init_space(H5F_t *file, const H5D_t *dset, const H5S_t *space);
+static herr_t H5D_set_io_ops(H5D_t *dataset);
static herr_t H5D_update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset);
-static herr_t H5D_open_oid(H5D_t *dataset, hid_t dxpl_id);
+static herr_t H5D_open_oid(H5D_t *dataset, hid_t dapl_id, hid_t dxpl_id);
+static herr_t H5D_flush_real(H5D_t *dataset, hid_t dxpl_id, unsigned flags);
/*********************/
@@ -97,6 +100,9 @@ H5FL_DEFINE_STATIC(H5D_shared_t);
/* Declare the external PQ free list for the sieve buffer information */
H5FL_BLK_EXTERN(sieve_buf);
+/* Declare the external free list to manage the H5D_chunk_info_t struct */
+H5FL_EXTERN(H5D_chunk_info_t);
+
/* Define a static "default" dataset structure to use to initialize new datasets */
static H5D_shared_t H5D_def_dset;
@@ -235,7 +241,7 @@ H5D_term_interface(void)
*
* QAK - 5/13/03
*/
- H5I_clear_type(H5I_DATASET, TRUE);
+ H5I_clear_type(H5I_DATASET, TRUE, FALSE);
} else {
H5I_dec_type_ref(H5I_DATASET);
H5_interface_initialize_g = 0;
@@ -246,6 +252,133 @@ H5D_term_interface(void)
} /* end H5D_term_interface() */
+/*--------------------------------------------------------------------------
+ NAME
+ H5D_get_dxpl_cache_real
+ PURPOSE
+ Get all the values for the DXPL cache.
+ USAGE
+ herr_t H5D_get_dxpl_cache_real(dxpl_id, cache)
+ hid_t dxpl_id; IN: DXPL to query
+ H5D_dxpl_cache_t *cache;IN/OUT: DXPL cache to fill with values
+ RETURNS
+ Non-negative on success/Negative on failure.
+ DESCRIPTION
+ Query all the values from a DXPL that are needed by internal routines
+ within the library.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static herr_t
+H5D_get_dxpl_cache_real(hid_t dxpl_id, H5D_dxpl_cache_t *cache)
+{
+ H5P_genplist_t *dx_plist; /* Data transfer property list */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_get_dxpl_cache_real)
+
+ /* Check args */
+ HDassert(cache);
+
+ /* Get the dataset transfer property list */
+ if(NULL == (dx_plist = (H5P_genplist_t *)H5I_object(dxpl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list")
+
+ /* Get maximum temporary buffer size */
+ if(H5P_get(dx_plist, H5D_XFER_MAX_TEMP_BUF_NAME, &cache->max_temp_buf) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve maximum temporary buffer size")
+
+ /* Get temporary buffer pointer */
+ if(H5P_get(dx_plist, H5D_XFER_TCONV_BUF_NAME, &cache->tconv_buf) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve temporary buffer pointer")
+
+ /* Get background buffer pointer */
+ if(H5P_get(dx_plist, H5D_XFER_BKGR_BUF_NAME, &cache->bkgr_buf) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve background buffer pointer")
+
+ /* Get background buffer type */
+ if(H5P_get(dx_plist, H5D_XFER_BKGR_BUF_TYPE_NAME, &cache->bkgr_buf_type) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve background buffer type")
+
+ /* Get B-tree split ratios */
+ if(H5P_get(dx_plist, H5D_XFER_BTREE_SPLIT_RATIO_NAME, &cache->btree_split_ratio) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve B-tree split ratios")
+
+ /* Get I/O vector size */
+ if(H5P_get(dx_plist, H5D_XFER_HYPER_VECTOR_SIZE_NAME, &cache->vec_size) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve I/O vector size")
+
+#ifdef H5_HAVE_PARALLEL
+ /* Collect Parallel I/O information for possible later use */
+ if(H5P_get(dx_plist, H5D_XFER_IO_XFER_MODE_NAME, &cache->xfer_mode) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve parallel transfer method")
+ if(H5P_get(dx_plist, H5D_XFER_MPIO_COLLECTIVE_OPT_NAME, &cache->coll_opt_mode) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve collective transfer option")
+#endif /* H5_HAVE_PARALLEL */
+
+ /* Get error detection properties */
+ if(H5P_get(dx_plist, H5D_XFER_EDC_NAME, &cache->err_detect) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve error detection info")
+
+ /* Get filter callback function */
+ if(H5P_get(dx_plist, H5D_XFER_FILTER_CB_NAME, &cache->filter_cb) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve filter callback function")
+
+ /* Get the data transform property */
+ if(H5P_get(dx_plist, H5D_XFER_XFORM_NAME, &cache->data_xform_prop) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve data transform info")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D_get_dxpl_cache_real() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5D_get_dxpl_cache
+ PURPOSE
+ Get all the values for the DXPL cache.
+ USAGE
+ herr_t H5D_get_dxpl_cache(dxpl_id, cache)
+ hid_t dxpl_id; IN: DXPL to query
+ H5D_dxpl_cache_t *cache;IN/OUT: DXPL cache to fill with values
+ RETURNS
+ Non-negative on success/Negative on failure.
+ DESCRIPTION
+ Query all the values from a DXPL that are needed by internal routines
+ within the library.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ The CACHE pointer should point at already allocated memory to place
+ non-default property list info. If a default property list is used, the
+ CACHE pointer will be changed to point at the default information.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5D_get_dxpl_cache(hid_t dxpl_id, H5D_dxpl_cache_t **cache)
+{
+ herr_t ret_value=SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5D_get_dxpl_cache,FAIL)
+
+ /* Check args */
+ assert(cache);
+
+ /* Check for the default DXPL */
+ if(dxpl_id==H5P_DATASET_XFER_DEFAULT)
+ *cache=&H5D_def_dxpl_cache;
+ else
+ if(H5D_get_dxpl_cache_real(dxpl_id,*cache) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "Can't retrieve DXPL values")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D_get_dxpl_cache() */
+
+
/*-------------------------------------------------------------------------
* Function: H5D_create_named
*
@@ -285,6 +418,7 @@ H5D_create_named(const H5G_loc_t *loc, const char *name, hid_t type_id,
dcrt_info.type_id = type_id;
dcrt_info.space = space;
dcrt_info.dcpl_id = dcpl_id;
+ dcrt_info.dapl_id = dapl_id;
/* Set up object creation information */
ocrt_info.obj_type = H5O_TYPE_DATASET;
@@ -402,7 +536,7 @@ H5D_new(hid_t dcpl_id, hbool_t creating, hbool_t vl_type)
* don't bother to copy it, just increment the reference count
*/
if(!vl_type && creating && dcpl_id == H5P_DATASET_CREATE_DEFAULT) {
- if(H5I_inc_ref(dcpl_id) < 0)
+ if(H5I_inc_ref(dcpl_id, FALSE) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINC, NULL, "Can't increment default DCPL ID")
new_dset->dcpl_id = dcpl_id;
} /* end if */
@@ -411,7 +545,7 @@ H5D_new(hid_t dcpl_id, hbool_t creating, hbool_t vl_type)
if(NULL == (plist = (H5P_genplist_t *)H5I_object(dcpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a property list")
- new_dset->dcpl_id = H5P_copy_plist(plist);
+ new_dset->dcpl_id = H5P_copy_plist(plist, FALSE);
} /* end else */
/* Set return value */
@@ -421,8 +555,8 @@ done:
if(ret_value == NULL)
if(new_dset != NULL) {
if(new_dset->dcpl_id != 0)
- (void)H5I_dec_ref(new_dset->dcpl_id);
- H5FL_FREE(H5D_shared_t, new_dset);
+ (void)H5I_dec_ref(new_dset->dcpl_id, FALSE);
+ (void)H5FL_FREE(H5D_shared_t, new_dset);
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
@@ -485,12 +619,12 @@ H5D_init_type(H5F_t *file, const H5D_t *dset, hid_t type_id, const H5T_t *type)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set latest version of datatype")
/* Get a datatype ID for the dataset's datatype */
- if((dset->shared->type_id = H5I_register(H5I_DATATYPE, dset->shared->type)) < 0)
+ if((dset->shared->type_id = H5I_register(H5I_DATATYPE, dset->shared->type, FALSE)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register type")
} /* end if */
/* Not a custom datatype, just use it directly */
else {
- if(H5I_inc_ref(type_id) < 0)
+ if(H5I_inc_ref(type_id, FALSE) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINC, FAIL, "Can't increment datatype ID")
/* Use existing datatype */
@@ -534,7 +668,7 @@ H5D_init_space(H5F_t *file, const H5D_t *dset, const H5S_t *space)
use_latest_format = H5F_USE_LATEST_FORMAT(file);
/* Copy dataspace for dataset */
- if(NULL == (dset->shared->space = H5S_copy(space, FALSE)))
+ if(NULL == (dset->shared->space = H5S_copy(space, FALSE, TRUE)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "can't copy dataspace")
/* Set the latest format, if requested */
@@ -552,6 +686,58 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5D_set_io_ops
+ *
+ * Purpose: Set the I/O operation function pointers for a dataset
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, March 20, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_set_io_ops(H5D_t *dataset)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_set_io_ops)
+
+ /* check args */
+ HDassert(dataset);
+
+ /* Set the I/O functions for each layout type */
+ switch(dataset->shared->layout.type) {
+ case H5D_CONTIGUOUS:
+ if(dataset->shared->dcpl_cache.efl.nused > 0)
+ dataset->shared->layout.ops = H5D_LOPS_EFL;
+ else
+ dataset->shared->layout.ops = H5D_LOPS_CONTIG;
+ break;
+
+ case H5D_CHUNKED:
+ dataset->shared->layout.ops = H5D_LOPS_CHUNK;
+
+ /* Set the chunk operations */
+ /* (Only "B-tree" indexing type currently supported */
+ dataset->shared->layout.u.chunk.ops = H5D_COPS_BTREE;
+ break;
+
+ case H5D_COMPACT:
+ dataset->shared->layout.ops = H5D_LOPS_COMPACT;
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unknown storage method")
+ } /* end switch */ /*lint !e788 All appropriate cases are covered */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_set_io_ops() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5D_update_oh_info
*
* Purpose: Create and fill object header for dataset
@@ -567,7 +753,7 @@ done:
static herr_t
H5D_update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset)
{
- struct H5O_t *oh = NULL; /* Pointer to dataset's object header */
+ H5O_t *oh = NULL; /* Pointer to dataset's object header */
size_t ohdr_size = H5D_MINHDR_SIZE; /* Size of dataset's object header */
H5O_loc_t *oloc = NULL; /* Dataset's object location */
H5O_layout_t *layout; /* Dataset's layout information */
@@ -650,13 +836,14 @@ H5D_update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset)
/* Create an object header for the dataset */
if(H5O_create(file, dxpl_id, ohdr_size, dset->shared->dcpl_id, oloc/*out*/) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create dataset object header")
+ HDassert(file == dset->oloc.file);
/* Get a pointer to the object header itself */
if((oh = H5O_protect(oloc, dxpl_id)) == NULL)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to protect dataset object header")
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTPROTECT, FAIL, "unable to protect dataset object header")
/* Write new fill value message */
- if(H5O_msg_append(file, dxpl_id, oh, H5O_FILL_NEW_ID, H5O_MSG_FLAG_CONSTANT, 0, fill_prop) < 0)
+ if(H5O_msg_append_oh(file, dxpl_id, oh, H5O_FILL_NEW_ID, H5O_MSG_FLAG_CONSTANT, 0, fill_prop) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update new fill value header message")
/* If there is valid information for the old fill value struct, add it */
@@ -672,12 +859,12 @@ H5D_update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset)
H5O_msg_reset_share(H5O_FILL_ID, &old_fill_prop);
/* Write old fill value */
- if(H5O_msg_append(file, dxpl_id, oh, H5O_FILL_ID, H5O_MSG_FLAG_CONSTANT, 0, &old_fill_prop) < 0)
+ if(H5O_msg_append_oh(file, dxpl_id, oh, H5O_FILL_ID, H5O_MSG_FLAG_CONSTANT, 0, &old_fill_prop) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update old fill value header message")
} /* end if */
/* Update the datatype and dataspace header messages */
- if(H5O_msg_append(file, dxpl_id, oh, H5O_DTYPE_ID, H5O_MSG_FLAG_CONSTANT, 0, type) < 0)
+ if(H5O_msg_append_oh(file, dxpl_id, oh, H5O_DTYPE_ID, H5O_MSG_FLAG_CONSTANT, 0, type) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update datatype header message")
if(H5S_append(file, dxpl_id, oh, dset->shared->space) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update dataspace header message")
@@ -687,7 +874,7 @@ H5D_update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset)
H5O_pline_t *pline; /* Dataset's I/O pipeline information */
pline = &dset->shared->dcpl_cache.pline;
- if(pline->nused > 0 && H5O_msg_append(file, dxpl_id, oh, H5O_PLINE_ID, H5O_MSG_FLAG_CONSTANT, 0, pline) < 0)
+ if(pline->nused > 0 && H5O_msg_append_oh(file, dxpl_id, oh, H5O_PLINE_ID, H5O_MSG_FLAG_CONSTANT, 0, pline) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update filter header message")
} /* end if */
@@ -696,7 +883,7 @@ H5D_update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset)
* allocation until later.
*/
if(fill_prop->alloc_time == H5D_ALLOC_TIME_EARLY)
- if(H5D_alloc_storage(file, dxpl_id, dset, H5D_ALLOC_CREATE, FALSE, FALSE) < 0)
+ if(H5D_alloc_storage(dset, dxpl_id, H5D_ALLOC_CREATE, FALSE) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize storage")
/* Update external storage message, if it's used */
@@ -716,7 +903,7 @@ H5D_update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset)
/* Pin the heap down in memory */
if(NULL == (heap = H5HL_protect(file, dxpl_id, efl->heap_addr, H5AC_WRITE)))
- HGOTO_ERROR(H5E_DATASET, H5E_PROTECT, FAIL, "unable to protect EFL file name heap")
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTPROTECT, FAIL, "unable to protect EFL file name heap")
/* Insert "empty" name first */
if((size_t)(-1) == H5HL_insert(file, dxpl_id, heap, (size_t)1, "")) {
@@ -741,18 +928,18 @@ H5D_update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset)
/* Release the heap */
if(H5HL_unprotect(file, dxpl_id, heap, efl->heap_addr) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_PROTECT, FAIL, "unable to unprotect EFL file name heap")
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTUNPROTECT, FAIL, "unable to unprotect EFL file name heap")
heap = NULL;
/* Insert EFL message into dataset object header */
- if(H5O_msg_append(file, dxpl_id, oh, H5O_EFL_ID, H5O_MSG_FLAG_CONSTANT, 0, efl) < 0)
+ if(H5O_msg_append_oh(file, dxpl_id, oh, H5O_EFL_ID, H5O_MSG_FLAG_CONSTANT, 0, efl) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update external file list message")
} /* end if */
/* Create layout message */
/* (Don't make layout message constant unless allocation time is early, since space may not be allocated) */
/* (Note: this is relying on H5D_alloc_storage not calling H5O_msg_write during dataset creation) */
- if(H5O_msg_append(file, dxpl_id, oh, H5O_LAYOUT_ID, ((fill_prop->alloc_time == H5D_ALLOC_TIME_EARLY && H5D_COMPACT != layout->type) ? H5O_MSG_FLAG_CONSTANT : 0), 0, layout) < 0)
+ if(H5O_msg_append_oh(file, dxpl_id, oh, H5O_LAYOUT_ID, ((fill_prop->alloc_time == H5D_ALLOC_TIME_EARLY && H5D_COMPACT != layout->type) ? H5O_MSG_FLAG_CONSTANT : 0), 0, layout) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update layout")
#ifdef H5O_ENABLE_BOGUS
@@ -778,15 +965,16 @@ H5D_update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset)
}
#endif /* H5O_ENABLE_BOGUS */
- /* Add a modification time message. */
- if(H5O_touch_oh(file, dxpl_id, oh, TRUE) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update modification time message")
+ /* Add a modification time message, if using older format. */
+ if(!use_latest_format)
+ if(H5O_touch_oh(file, dxpl_id, oh, TRUE) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update modification time message")
done:
/* Release pointer to object header itself */
if(oloc != NULL && oh != NULL)
if(H5O_unprotect(oloc, oh) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to unprotect dataset object header")
+ HDONE_ERROR(H5E_DATASET, H5E_CANTUNPROTECT, FAIL, "unable to unprotect dataset object header")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_update_oh_info() */
@@ -814,27 +1002,24 @@ done:
*/
H5D_t *
H5D_create(H5F_t *file, hid_t type_id, const H5S_t *space, hid_t dcpl_id,
- hid_t dxpl_id)
+ hid_t dapl_id, hid_t dxpl_id)
{
const H5T_t *type; /* Datatype for dataset */
H5D_t *new_dset = NULL;
- int i, ndims;
- unsigned chunk_ndims = 0; /* Dimensionality of chunk */
H5P_genplist_t *dc_plist = NULL; /* New Property list */
hbool_t has_vl_type = FALSE; /* Flag to indicate a VL-type for dataset */
- hbool_t chunk_init = FALSE; /* Flag to indicate that chunk information was initialized */
+ hbool_t layout_init = FALSE; /* Flag to indicate that chunk information was initialized */
H5G_loc_t dset_loc; /* Dataset location */
- unsigned u; /* Local index variable */
H5D_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5D_create, NULL)
/* check args */
HDassert(file);
- HDassert(H5I_DATATYPE==H5I_get_type(type_id));
+ HDassert(H5I_DATATYPE == H5I_get_type(type_id));
HDassert(space);
- HDassert(H5I_GENPROP_LST==H5I_get_type(dcpl_id));
- HDassert(H5I_GENPROP_LST==H5I_get_type(dxpl_id));
+ HDassert(H5I_GENPROP_LST == H5I_get_type(dcpl_id));
+ HDassert(H5I_GENPROP_LST == H5I_get_type(dxpl_id));
/* Get the dataset's datatype */
if(NULL == (type = (const H5T_t *)H5I_object(type_id)))
@@ -846,10 +1031,10 @@ H5D_create(H5F_t *file, hid_t type_id, const H5S_t *space, hid_t dcpl_id,
/* Check if the datatype is/contains a VL-type */
if(H5T_detect_class(type, H5T_VLEN))
- has_vl_type=TRUE;
+ has_vl_type = TRUE;
/* Check if the dataspace has an extent set (or is NULL) */
- if(!(H5S_has_extent(space)) )
+ if(!H5S_has_extent(space))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "dataspace extent has not been set.")
/* Initialize the dataset object */
@@ -919,10 +1104,6 @@ H5D_create(H5F_t *file, hid_t type_id, const H5S_t *space, hid_t dcpl_id,
if(IS_H5FD_MPI(file) && pline->nused > 0)
HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, NULL, "Parallel I/O does not support filters yet")
- /* Chunked datasets are non-default, so retrieve their info here */
- if(H5P_get(dc_plist, H5D_CRT_CHUNK_DIM_NAME, &chunk_ndims) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't retrieve chunk dimensions")
-
/* Get the dataset's external file list information */
if(H5P_get(dc_plist, H5D_CRT_EXT_FILE_LIST_NAME, &new_dset->shared->dcpl_cache.efl) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't retrieve external file list")
@@ -943,141 +1124,16 @@ H5D_create(H5F_t *file, hid_t type_id, const H5S_t *space, hid_t dcpl_id,
if(IS_H5FD_MPI(file))
new_dset->shared->dcpl_cache.fill.alloc_time = H5D_ALLOC_TIME_EARLY;
- switch(new_dset->shared->layout.type) {
- case H5D_CONTIGUOUS:
- {
- hssize_t tmp_size; /* Temporary holder for raw data size */
- hsize_t dim[H5O_LAYOUT_NDIMS]; /* Current size of data in elements */
- hsize_t max_dim[H5O_LAYOUT_NDIMS]; /* Maximum size of data in elements */
+ /* Set the dataset's I/O operations */
+ if(H5D_set_io_ops(new_dset) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to initialize I/O operations")
- /*
- * The maximum size of the dataset cannot exceed the storage size.
- * Also, only the slowest varying dimension of a simple data space
- * can be extendible (currently only for external data storage).
- */
- new_dset->shared->layout.u.contig.addr = HADDR_UNDEF; /* Initialize to no address */
-
- if((ndims = H5S_get_simple_extent_dims(new_dset->shared->space, dim, max_dim)) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to initialize contiguous storage")
- for(i = 1; i < ndims; i++)
- if(max_dim[i] > dim[i])
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "only the first dimension can be extendible")
- if(new_dset->shared->dcpl_cache.efl.nused > 0) {
- hsize_t max_points = H5S_get_npoints_max(new_dset->shared->space);
- hsize_t max_storage = H5O_efl_total_size(&new_dset->shared->dcpl_cache.efl);
-
- if(H5S_UNLIMITED == max_points) {
- if(H5O_EFL_UNLIMITED != max_storage)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unlimited data space but finite storage")
- } else if(max_points * H5T_get_size(type) < max_points) {
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "data space * type size overflowed")
- } else if(max_points * H5T_get_size(type) > max_storage) {
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "data space size exceeds external storage size")
- }
-
- /* Set the I/O functions for this layout type */
- new_dset->shared->io_ops.readvv = H5D_efl_readvv;
- new_dset->shared->io_ops.writevv = H5D_efl_writevv;
- } /* end if */
- else {
- if(ndims > 0 && max_dim[0] > dim[0])
- HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, NULL, "extendible contiguous non-external dataset")
-
- /* Set the I/O functions for this layout type */
- new_dset->shared->io_ops.readvv = H5D_contig_readvv;
- new_dset->shared->io_ops.writevv = H5D_contig_writevv;
- } /* end else */
-
- /* Compute the total size of a chunk */
- tmp_size = H5S_GET_EXTENT_NPOINTS(new_dset->shared->space) * H5T_get_size(new_dset->shared->type);
- H5_ASSIGN_OVERFLOW(new_dset->shared->layout.u.contig.size, tmp_size, hssize_t, hsize_t);
-
- /* Get the sieve buffer size for this dataset */
- new_dset->shared->cache.contig.sieve_buf_size = H5F_SIEVE_BUF_SIZE(file);
- } /* end case */
- break;
-
- case H5D_CHUNKED:
- {
- hsize_t max_dim[H5O_LAYOUT_NDIMS]; /* Maximum size of data in elements */
+ /* Create the layout information for the new dataset */
+ if((new_dset->shared->layout.ops->new)(file, dapl_id, dxpl_id, new_dset, dc_plist) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to initialize layout information")
- /* Set up layout information */
- if((ndims = H5S_GET_EXTENT_NDIMS(new_dset->shared->space)) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, NULL, "unable to get rank")
- new_dset->shared->layout.u.chunk.ndims = (unsigned)ndims + 1;
- HDassert((unsigned)(new_dset->shared->layout.u.chunk.ndims) <= NELMTS(new_dset->shared->layout.u.chunk.dim));
-
- /* Initialize to no address */
- new_dset->shared->layout.u.chunk.addr = HADDR_UNDEF;
-
- /*
- * Chunked storage allows any type of data space extension, so we
- * don't even bother checking.
- */
- if(chunk_ndims != (unsigned)ndims)
- HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, NULL, "dimensionality of chunks doesn't match the data space")
- if(new_dset->shared->dcpl_cache.efl.nused > 0)
- HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, NULL, "external storage not supported with chunked layout")
-
- /*
- * The chunk size of a dimension with a fixed size cannot exceed
- * the maximum dimension size
- */
- if(H5P_get(dc_plist, H5D_CRT_CHUNK_SIZE_NAME, new_dset->shared->layout.u.chunk.dim) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't retrieve chunk size")
- new_dset->shared->layout.u.chunk.dim[new_dset->shared->layout.u.chunk.ndims-1] = H5T_get_size(new_dset->shared->type);
-
- if(H5S_get_simple_extent_dims(new_dset->shared->space, NULL, max_dim) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to query maximum dimensions")
- for(u = 0; u < new_dset->shared->layout.u.chunk.ndims - 1; u++)
- if(max_dim[u] != H5S_UNLIMITED && max_dim[u] < new_dset->shared->layout.u.chunk.dim[u])
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "chunk size must be <= maximum dimension size for fixed-sized dimensions")
-
- /* Compute the total size of a chunk */
- for(u = 1, new_dset->shared->layout.u.chunk.size = new_dset->shared->layout.u.chunk.dim[0]; u < new_dset->shared->layout.u.chunk.ndims; u++)
- new_dset->shared->layout.u.chunk.size *= new_dset->shared->layout.u.chunk.dim[u];
-
- /* Set the I/O functions for this layout type */
- new_dset->shared->io_ops.readvv = H5D_istore_readvv;
- new_dset->shared->io_ops.writevv = H5D_istore_writevv;
-
- /* Initialize the chunk cache for the dataset */
- if(H5D_istore_init(file, new_dset) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "can't initialize chunk cache")
-
- /* Indicate that the chunk information was initialized */
- chunk_init = TRUE;
- } /* end case */
- break;
-
- case H5D_COMPACT:
- {
- hssize_t tmp_size; /* Temporary holder for raw data size */
- hsize_t comp_data_size;
-
- /*
- * Compact dataset is stored in dataset object header message of
- * layout.
- */
- tmp_size = H5S_GET_EXTENT_NPOINTS(space) * H5T_get_size(new_dset->shared->type);
- H5_ASSIGN_OVERFLOW(new_dset->shared->layout.u.compact.size, tmp_size, hssize_t, size_t);
-
- /* Verify data size is smaller than maximum header message size
- * (64KB) minus other layout message fields.
- */
- comp_data_size = H5O_MESG_MAX_SIZE - H5O_layout_meta_size(file, &(new_dset->shared->layout));
- if(new_dset->shared->layout.u.compact.size > comp_data_size)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "compact dataset size is bigger than header message maximum size")
-
- /* Set the I/O functions for this layout type */
- new_dset->shared->io_ops.readvv = H5D_compact_readvv;
- new_dset->shared->io_ops.writevv = H5D_compact_writevv;
- } /* end case */
- break;
-
- default:
- HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, NULL, "not implemented yet")
- } /* end switch */ /*lint !e788 All appropriate cases are covered */
+ /* Indicate that the layout information was initialized */
+ layout_init = TRUE;
/* Update the dataset's object header info. */
if(H5D_update_oh_info(file, dxpl_id, new_dset) != SUCCEED)
@@ -1087,7 +1143,7 @@ H5D_create(H5F_t *file, hid_t type_id, const H5S_t *space, hid_t dcpl_id,
if(H5FO_top_incr(new_dset->oloc.file, new_dset->oloc.addr) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINC, NULL, "can't incr object ref. count")
if(H5FO_insert(new_dset->oloc.file, new_dset->oloc.addr, new_dset->shared, TRUE) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, NULL, "can't insert dataset into list of open objects")
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, NULL, "can't insert dataset into list of open objects")
new_dset->shared->fo_count = 1;
@@ -1097,16 +1153,14 @@ H5D_create(H5F_t *file, hid_t type_id, const H5S_t *space, hid_t dcpl_id,
done:
if(!ret_value && new_dset && new_dset->shared) {
if(new_dset->shared) {
- if(new_dset->shared->layout.type == H5D_CHUNKED && chunk_init) {
- if(H5D_istore_dest(new_dset,H5AC_dxpl_id) < 0)
+ if(new_dset->shared->layout.type == H5D_CHUNKED && layout_init) {
+ if(H5D_chunk_dest(file, dxpl_id, new_dset) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, NULL, "unable to destroy chunk cache")
} /* end if */
- if(new_dset->shared->space) {
- if(H5S_close(new_dset->shared->space) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, NULL, "unable to release dataspace")
- } /* end if */
+ if(new_dset->shared->space && H5S_close(new_dset->shared->space) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, NULL, "unable to release dataspace")
if(new_dset->shared->type) {
- if(H5I_dec_ref(new_dset->shared->type_id) < 0)
+ if(H5I_dec_ref(new_dset->shared->type_id, FALSE) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, NULL, "unable to release datatype")
} /* end if */
if(H5F_addr_defined(new_dset->oloc.addr)) {
@@ -1117,14 +1171,12 @@ done:
HDONE_ERROR(H5E_DATASET, H5E_CANTDELETE, NULL, "unable to delete object header")
} /* end if */
} /* end if */
- if(new_dset->shared->dcpl_id != 0) {
- if(H5I_dec_ref(new_dset->shared->dcpl_id) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTDEC, NULL, "unable to decrement ref count on property list")
- } /* end if */
- H5FL_FREE(H5D_shared_t, new_dset->shared);
+ if(new_dset->shared->dcpl_id != 0 && H5I_dec_ref(new_dset->shared->dcpl_id, FALSE) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTDEC, NULL, "unable to decrement ref count on property list")
+ (void)H5FL_FREE(H5D_shared_t, new_dset->shared);
} /* end if */
new_dset->oloc.file = NULL;
- H5FL_FREE(H5D_t, new_dset);
+ (void)H5FL_FREE(H5D_t, new_dset);
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
@@ -1147,7 +1199,7 @@ done:
*-------------------------------------------------------------------------
*/
H5D_t *
-H5D_open(const H5G_loc_t *loc, hid_t dxpl_id)
+H5D_open(const H5G_loc_t *loc, hid_t dapl_id, hid_t dxpl_id)
{
H5D_shared_t *shared_fo = NULL;
H5D_t *dataset = NULL;
@@ -1176,7 +1228,7 @@ H5D_open(const H5G_loc_t *loc, hid_t dxpl_id)
H5E_clear_stack(NULL);
/* Open the dataset object */
- if(H5D_open_oid(dataset, dxpl_id) < 0)
+ if(H5D_open_oid(dataset, dapl_id, dxpl_id) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_NOTFOUND, NULL, "not found")
/* Add the dataset to the list of opened objects in the file */
@@ -1216,13 +1268,13 @@ done:
/* Free the location--casting away const*/
if(dataset) {
if(shared_fo == NULL) /* Need to free shared fo */
- H5FL_FREE(H5D_shared_t, dataset->shared);
+ (void)H5FL_FREE(H5D_shared_t, dataset->shared);
H5O_loc_free(&(dataset->oloc));
H5G_name_free(&(dataset->path));
- H5FL_FREE(H5D_t, dataset);
- }
+ (void)H5FL_FREE(H5D_t, dataset);
+ } /* end if */
if(shared_fo)
shared_fo->fo_count--;
} /* end if */
@@ -1244,12 +1296,12 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5D_open_oid(H5D_t *dataset, hid_t dxpl_id)
+H5D_open_oid(H5D_t *dataset, hid_t dapl_id, hid_t dxpl_id)
{
H5P_genplist_t *plist; /* Property list */
- H5O_pline_t *pline; /* I/O pipeline information */
H5O_fill_t *fill_prop; /* Pointer to dataset's fill value info */
unsigned alloc_time_state; /* Allocation time state */
+ htri_t msg_exists; /* Whether a particular type of message exists */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5D_open_oid)
@@ -1269,10 +1321,10 @@ H5D_open_oid(H5D_t *dataset, hid_t dxpl_id)
if(NULL == (dataset->shared->type = (H5T_t *)H5O_msg_read(&(dataset->oloc), H5O_DTYPE_ID, NULL, dxpl_id)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to load type info from dataset header")
if(NULL == (dataset->shared->space = H5S_read(&(dataset->oloc), dxpl_id)))
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to load space info from dataset header")
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to load dataspace info from dataset header")
/* Get a datatype ID for the dataset's datatype */
- if((dataset->shared->type_id = H5I_register(H5I_DATATYPE, dataset->shared->type)) < 0)
+ if((dataset->shared->type_id = H5I_register(H5I_DATATYPE, dataset->shared->type, FALSE)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register type")
/* Get dataset creation property list object */
@@ -1280,13 +1332,17 @@ H5D_open_oid(H5D_t *dataset, hid_t dxpl_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get dataset creation property list")
/* Get the optional filters message */
- pline = &dataset->shared->dcpl_cache.pline;
- if(NULL != H5O_msg_read(&(dataset->oloc), H5O_PLINE_ID, pline, dxpl_id)) {
- if(H5P_set(plist, H5D_CRT_DATA_PIPELINE_NAME, pline) < 0)
+ if((msg_exists = H5O_msg_exists(&(dataset->oloc), H5O_PLINE_ID, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't check if message exists")
+ if(msg_exists) {
+ /* Retrieve the I/O pipeline message */
+ if(NULL == H5O_msg_read(&(dataset->oloc), H5O_PLINE_ID, &dataset->shared->dcpl_cache.pline, dxpl_id))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve message")
+
+ /* Set the I/O pipeline info in the property list */
+ if(H5P_set(plist, H5D_CRT_DATA_PIPELINE_NAME, &dataset->shared->dcpl_cache.pline) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set pipeline")
} /* end if */
- else
- H5E_clear_stack(NULL);
/*
* Get the raw data layout info. It's actually stored in two locations:
@@ -1298,6 +1354,30 @@ H5D_open_oid(H5D_t *dataset, hid_t dxpl_id)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to read data layout message")
if(H5P_set(plist, H5D_CRT_LAYOUT_NAME, &dataset->shared->layout.type) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set layout")
+
+ /* Get the external file list message, which might not exist. Space is
+ * also undefined when space allocate time is H5D_ALLOC_TIME_LATE. */
+ if((dataset->shared->layout.type == H5D_CONTIGUOUS && !H5F_addr_defined(dataset->shared->layout.u.contig.addr))
+ || (dataset->shared->layout.type == H5D_CHUNKED && !H5F_addr_defined(dataset->shared->layout.u.chunk.addr))) {
+ if((msg_exists = H5O_msg_exists(&(dataset->oloc), H5O_EFL_ID, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't check if message exists")
+ if(msg_exists) {
+ /* Retrieve the EFL message */
+ if(NULL == H5O_msg_read(&(dataset->oloc), H5O_EFL_ID, &dataset->shared->dcpl_cache.efl, dxpl_id))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve message")
+
+ /* Set the EFL info in the property list */
+ if(H5P_set(plist, H5D_CRT_EXT_FILE_LIST_NAME, &dataset->shared->dcpl_cache.efl) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set external file list")
+
+ /* Set the dataset's I/O operations */
+ dataset->shared->layout.ops = H5D_LOPS_EFL;
+ } /* end if */
+ } /* end if */
+
+ /* Sanity check that the layout operations are set up */
+ HDassert(dataset->shared->layout.ops);
+
switch(dataset->shared->layout.type) {
case H5D_CONTIGUOUS:
/* Compute the size of the contiguous storage for versions of the
@@ -1311,10 +1391,6 @@ H5D_open_oid(H5D_t *dataset, hid_t dxpl_id)
H5_ASSIGN_OVERFLOW(dataset->shared->layout.u.contig.size, tmp_size, hssize_t, hsize_t);
} /* end if */
- /* Set the I/O functions for this layout type */
- dataset->shared->io_ops.readvv = H5D_contig_readvv;
- dataset->shared->io_ops.writevv = H5D_contig_writevv;
-
/* Get the sieve buffer size for this dataset */
dataset->shared->cache.contig.sieve_buf_size = H5F_SIEVE_BUF_SIZE(dataset->oloc.file);
break;
@@ -1336,36 +1412,37 @@ H5D_open_oid(H5D_t *dataset, hid_t dxpl_id)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set chunk size")
/* Initialize the chunk cache for the dataset */
- if(H5D_istore_init(dataset->oloc.file, dataset) < 0)
+ if(H5D_chunk_init(dataset->oloc.file, dapl_id, dxpl_id, dataset) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize chunk cache")
}
-
- /* Set the I/O functions for this layout type */
- dataset->shared->io_ops.readvv = H5D_istore_readvv;
- dataset->shared->io_ops.writevv = H5D_istore_writevv;
break;
case H5D_COMPACT:
- /* Set the I/O functions for this layout type */
- dataset->shared->io_ops.readvv = H5D_compact_readvv;
- dataset->shared->io_ops.writevv = H5D_compact_writevv;
break;
default:
- HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "not implemented yet")
+ HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unknown storage method")
} /* end switch */ /*lint !e788 All appropriate cases are covered */
/* Point at dataset's copy, to cache it for later */
fill_prop = &dataset->shared->dcpl_cache.fill;
/* Try to get the new fill value message from the object header */
- if(NULL == H5O_msg_read(&(dataset->oloc), H5O_FILL_NEW_ID, fill_prop, dxpl_id)) {
- H5E_clear_stack(NULL);
-
+ if((msg_exists = H5O_msg_exists(&(dataset->oloc), H5O_FILL_NEW_ID, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't check if message exists")
+ if(msg_exists) {
+ if(NULL == H5O_msg_read(&(dataset->oloc), H5O_FILL_NEW_ID, fill_prop, dxpl_id))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve message")
+ } /* end if */
+ else {
/* For backward compatibility, try to retrieve the old fill value message */
- if(NULL == H5O_msg_read(&(dataset->oloc), H5O_FILL_ID, fill_prop, dxpl_id)) {
- H5E_clear_stack(NULL);
-
+ if((msg_exists = H5O_msg_exists(&(dataset->oloc), H5O_FILL_ID, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't check if message exists")
+ if(msg_exists) {
+ if(NULL == H5O_msg_read(&(dataset->oloc), H5O_FILL_ID, fill_prop, dxpl_id))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve message")
+ } /* end if */
+ else {
/* Set the space allocation time appropriately, based on the type of dataset storage */
switch(dataset->shared->layout.type) {
case H5D_COMPACT:
@@ -1383,7 +1460,7 @@ H5D_open_oid(H5D_t *dataset, hid_t dxpl_id)
default:
HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "not implemented yet")
} /* end switch */ /*lint !e788 All appropriate cases are covered */
- } /* end if */
+ } /* end else */
/* If "old" fill value size is 0 (undefined), map it to -1 */
if(fill_prop->size == 0)
@@ -1403,48 +1480,28 @@ H5D_open_oid(H5D_t *dataset, hid_t dxpl_id)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set allocation time state")
} /* end if */
- /* Get the external file list message, which might not exist. Space is
- * also undefined when space allocate time is H5D_ALLOC_TIME_LATE. */
- if((dataset->shared->layout.type == H5D_CONTIGUOUS && !H5F_addr_defined(dataset->shared->layout.u.contig.addr))
- || (dataset->shared->layout.type == H5D_CHUNKED && !H5F_addr_defined(dataset->shared->layout.u.chunk.addr))) {
- if(NULL != H5O_msg_read(&(dataset->oloc), H5O_EFL_ID, &dataset->shared->dcpl_cache.efl, dxpl_id)) {
- if(H5P_set(plist, H5D_CRT_EXT_FILE_LIST_NAME, &dataset->shared->dcpl_cache.efl) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set external file list")
-
- /* Override the I/O functions for this layout type */
- dataset->shared->io_ops.readvv = H5D_efl_readvv;
- dataset->shared->io_ops.writevv = H5D_efl_writevv;
- } /* end if */
- else
- H5E_clear_stack(NULL);
- } /* end if */
-
/*
* Make sure all storage is properly initialized.
* This is important only for parallel I/O where the space must
* be fully allocated before I/O can happen.
*/
- if((H5F_get_intent(dataset->oloc.file) & H5F_ACC_RDWR)
+ if((H5F_INTENT(dataset->oloc.file) & H5F_ACC_RDWR)
&& ((dataset->shared->layout.type == H5D_CONTIGUOUS && !H5F_addr_defined(dataset->shared->layout.u.contig.addr))
|| (dataset->shared->layout.type == H5D_CHUNKED && !H5F_addr_defined(dataset->shared->layout.u.chunk.addr)))
&& IS_H5FD_MPI(dataset->oloc.file)) {
- if(H5D_alloc_storage(dataset->oloc.file, dxpl_id, dataset, H5D_ALLOC_OPEN, TRUE, FALSE) < 0)
+ if(H5D_alloc_storage(dataset, dxpl_id, H5D_ALLOC_OPEN, FALSE) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize file storage")
} /* end if */
done:
if(ret_value < 0) {
- if(H5F_addr_defined(dataset->oloc.addr)) {
- if(H5O_close(&(dataset->oloc)) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release object header")
- } /* end if */
- if(dataset->shared->space) {
- if(H5S_close(dataset->shared->space) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataspace")
- } /* end if */
+ if(H5F_addr_defined(dataset->oloc.addr) && H5O_close(&(dataset->oloc)) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release object header")
+ if(dataset->shared->space && H5S_close(dataset->shared->space) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataspace")
if(dataset->shared->type) {
if(dataset->shared->type_id > 0) {
- if(H5I_dec_ref(dataset->shared->type_id) < 0)
+ if(H5I_dec_ref(dataset->shared->type_id, FALSE) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release datatype")
} /* end if */
else {
@@ -1485,34 +1542,20 @@ H5D_close(H5D_t *dataset)
HDassert(dataset->shared->fo_count >0);
/* Dump debugging info */
-#ifdef H5D_ISTORE_DEBUG
- H5D_istore_stats(dataset, FALSE);
-#endif /* H5F_ISTORE_DEBUG */
+#ifdef H5D_CHUNK_DEBUG
+ H5D_chunk_stats(dataset, FALSE);
+#endif /* H5D_CHUNK_DEBUG */
dataset->shared->fo_count--;
if(dataset->shared->fo_count == 0) {
- /* Update the dataspace on disk, if it's been changed */
- if(dataset->shared->space_dirty) {
- if(H5S_write(&(dataset->oloc), dataset->shared->space, TRUE, H5AC_dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to update file with new dataspace")
- dataset->shared->space_dirty = FALSE;
- } /* end if */
+ /* Flush the dataset's information */
+ if(H5D_flush_real(dataset, H5AC_dxpl_id, H5F_FLUSH_NONE) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to flush cached dataset info")
/* Free the data sieve buffer, if it's been allocated */
if(dataset->shared->cache.contig.sieve_buf) {
HDassert(dataset->shared->layout.type != H5D_COMPACT); /* We should never have a sieve buffer for compact storage */
- /* Flush the raw data buffer, if its dirty */
- if(dataset->shared->cache.contig.sieve_dirty) {
- /* Write dirty data sieve buffer to file */
- if(H5F_block_write(dataset->oloc.file, H5FD_MEM_DRAW, dataset->shared->cache.contig.sieve_loc,
- dataset->shared->cache.contig.sieve_size, H5AC_dxpl_id, dataset->shared->cache.contig.sieve_buf) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed")
-
- /* Reset sieve buffer dirty flag */
- dataset->shared->cache.contig.sieve_dirty = FALSE;
- } /* end if */
-
dataset->shared->cache.contig.sieve_buf = (unsigned char *)H5FL_BLK_FREE(sieve_buf,dataset->shared->cache.contig.sieve_buf);
} /* end if */
@@ -1522,19 +1565,31 @@ H5D_close(H5D_t *dataset)
break;
case H5D_CHUNKED:
+ /* Check for skip list for iterating over chunks during I/O to close */
+ if(dataset->shared->cache.chunk.sel_chunks) {
+ HDassert(H5SL_count(dataset->shared->cache.chunk.sel_chunks) == 0);
+ H5SL_close(dataset->shared->cache.chunk.sel_chunks);
+ dataset->shared->cache.chunk.sel_chunks = NULL;
+ } /* end if */
+
+ /* Check for cached single chunk dataspace */
+ if(dataset->shared->cache.chunk.single_space) {
+ (void)H5S_close(dataset->shared->cache.chunk.single_space);
+ dataset->shared->cache.chunk.single_space = NULL;
+ } /* end if */
+
+ /* Check for cached single element chunk info */
+ if(dataset->shared->cache.chunk.single_chunk_info) {
+ (void)H5FL_FREE(H5D_chunk_info_t, dataset->shared->cache.chunk.single_chunk_info);
+ dataset->shared->cache.chunk.single_chunk_info = NULL;
+ } /* end if */
+
/* Flush and destroy chunks in the cache */
- if(H5D_istore_dest(dataset,H5AC_dxpl_id) < 0)
+ if(H5D_chunk_dest(dataset->oloc.file, H5AC_dxpl_id, dataset) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "unable to destroy chunk cache")
break;
case H5D_COMPACT:
- /* Update header message of layout for compact dataset. */
- if(dataset->shared->layout.u.compact.dirty) {
- if(H5O_msg_write(&(dataset->oloc), H5O_LAYOUT_ID, 0, H5O_UPDATE_TIME, &(dataset->shared->layout), H5AC_dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "unable to update layout message")
- dataset->shared->layout.u.compact.dirty = FALSE;
- } /* end if */
-
/* Free the buffer for the raw data for compact datasets */
dataset->shared->layout.u.compact.buf = H5MM_xfree(dataset->shared->layout.u.compact.buf);
break;
@@ -1550,8 +1605,8 @@ H5D_close(H5D_t *dataset)
* Release datatype, dataspace and creation property list -- there isn't
* much we can do if one of these fails, so we just continue.
*/
- free_failed = (H5I_dec_ref(dataset->shared->type_id) < 0 || H5S_close(dataset->shared->space) < 0 ||
- H5I_dec_ref(dataset->shared->dcpl_id) < 0);
+ free_failed = (H5I_dec_ref(dataset->shared->type_id, FALSE) < 0 || H5S_close(dataset->shared->space) < 0 ||
+ H5I_dec_ref(dataset->shared->dcpl_id, FALSE) < 0);
/* Remove the dataset from the list of opened objects in the file */
if(H5FO_top_decr(dataset->oloc.file, dataset->oloc.addr) < 0)
@@ -1572,7 +1627,7 @@ H5D_close(H5D_t *dataset)
*/
dataset->oloc.file = NULL;
- H5FL_FREE(H5D_shared_t, dataset->shared);
+ (void)H5FL_FREE(H5D_shared_t, dataset->shared);
} /* end if */
else {
/* Decrement the ref. count for this object in the top file */
@@ -1590,7 +1645,7 @@ H5D_close(H5D_t *dataset)
free_failed = TRUE;
/* Free the dataset's memory structure */
- H5FL_FREE(H5D_t, dataset);
+ (void)H5FL_FREE(H5D_t, dataset);
/* Check if anything failed in the middle... */
if(free_failed)
@@ -1654,7 +1709,6 @@ H5D_nameof(H5D_t *dataset)
* is not copied.
*
* Return: Success: Ptr to the dataset's datatype, uncopied.
- *
* Failure: NULL
*
* Programmer: Robb Matzke
@@ -1669,6 +1723,7 @@ H5D_typeof(const H5D_t *dset)
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_typeof)
HDassert(dset);
+ HDassert(dset->shared);
HDassert(dset->shared->type);
FUNC_LEAVE_NOAPI(dset->shared->type)
@@ -1676,33 +1731,6 @@ H5D_typeof(const H5D_t *dset)
/*-------------------------------------------------------------------------
- * Function: H5D_get_file
- *
- * Purpose: Returns the dataset's file pointer.
- *
- * Return: Success: Ptr to the dataset's file pointer.
- *
- * Failure: NULL
- *
- * Programmer: Quincey Koziol
- * Thursday, October 22, 1998
- *
- *-------------------------------------------------------------------------
- */
-static H5F_t *
-H5D_get_file(const H5D_t *dset)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_get_file)
-
- HDassert(dset);
- HDassert(dset->oloc.file);
-
- FUNC_LEAVE_NOAPI(dset->oloc.file)
-} /* end H5D_get_file() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5D_alloc_storage
*
* Purpose: Allocate storage for the raw data of a dataset.
@@ -1715,10 +1743,11 @@ H5D_get_file(const H5D_t *dset)
*-------------------------------------------------------------------------
*/
herr_t
-H5D_alloc_storage(H5F_t *f, hid_t dxpl_id, H5D_t *dset/*in,out*/, H5D_time_alloc_t time_alloc,
- hbool_t update_time, hbool_t full_overwrite)
+H5D_alloc_storage(H5D_t *dset/*in,out*/, hid_t dxpl_id, H5D_time_alloc_t time_alloc,
+ hbool_t full_overwrite)
{
- struct H5O_layout_t *layout; /* The dataset's layout information */
+ H5F_t *f = dset->oloc.file; /* The dataset's file pointer */
+ H5O_layout_t *layout; /* The dataset's layout information */
hbool_t must_init_space = FALSE; /* Flag to indicate that space should be initialized */
hbool_t addr_set = FALSE; /* Flag to indicate that the dataset's storage address was set */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1726,8 +1755,8 @@ H5D_alloc_storage(H5F_t *f, hid_t dxpl_id, H5D_t *dset/*in,out*/, H5D_time_alloc
FUNC_ENTER_NOAPI_NOINIT(H5D_alloc_storage)
/* check args */
- HDassert(f);
HDassert(dset);
+ HDassert(f);
/* If the data is stored in external files, don't set an address for the layout
* We assume that external storage is already
@@ -1741,7 +1770,7 @@ H5D_alloc_storage(H5F_t *f, hid_t dxpl_id, H5D_t *dset/*in,out*/, H5D_time_alloc
case H5D_CONTIGUOUS:
if(!H5F_addr_defined(layout->u.contig.addr)) {
/* Reserve space in the file for the entire array */
- if(H5D_contig_create(f, dxpl_id, layout/*out*/) < 0)
+ if(H5D_contig_alloc(f, dxpl_id, layout/*out*/) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to initialize contiguous storage")
/* Indicate that we set the storage addr */
@@ -1755,7 +1784,7 @@ H5D_alloc_storage(H5F_t *f, hid_t dxpl_id, H5D_t *dset/*in,out*/, H5D_time_alloc
case H5D_CHUNKED:
if(!H5F_addr_defined(layout->u.chunk.addr)) {
/* Create the root of the B-tree that describes chunked storage */
- if(H5D_istore_create(f, dxpl_id, layout/*out*/) < 0)
+ if(H5D_chunk_create(dset /*in,out*/, dxpl_id) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to initialize chunked storage")
/* Indicate that we set the storage addr */
@@ -1771,7 +1800,7 @@ H5D_alloc_storage(H5F_t *f, hid_t dxpl_id, H5D_t *dset/*in,out*/, H5D_time_alloc
*/
if(dset->shared->dcpl_cache.fill.alloc_time == H5D_ALLOC_TIME_EARLY
&& time_alloc == H5D_ALLOC_EXTEND)
- must_init_space = 1;
+ must_init_space = TRUE;
break;
case H5D_COMPACT:
@@ -1833,12 +1862,15 @@ H5D_alloc_storage(H5F_t *f, hid_t dxpl_id, H5D_t *dset/*in,out*/, H5D_time_alloc
} /* end else */
} /* end if */
- /* Also update header message for layout with new address, if we
- * set the address. (this is improves forward compatibility).
+ /* If we set the address (and aren't in the middle of creating the
+ * dataset), mark the layout header message for later writing to
+ * the file. (this improves forward compatibility).
+ */
+ /* (The layout message is already in the dataset's object header, this
+ * operation just sets the address and makes it constant)
*/
if(time_alloc != H5D_ALLOC_CREATE && addr_set)
- if(H5O_msg_write(&dset->oloc, H5O_LAYOUT_ID, H5O_MSG_FLAG_CONSTANT, update_time, &dset->shared->layout, dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update layout message")
+ dset->shared->layout_dirty = TRUE;
} /* end if */
done:
@@ -1892,7 +1924,7 @@ H5D_init_storage(H5D_t *dset, hbool_t full_overwrite, hid_t dxpl_id)
* Allocate file space
* for all chunks now and initialize each chunk with the fill value.
*/
- if(H5D_istore_allocate(dset, dxpl_id, full_overwrite) < 0)
+ if(H5D_chunk_allocate(dset, dxpl_id, full_overwrite) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to allocate all chunks of dataset")
break;
@@ -1935,7 +1967,8 @@ H5D_get_storage_size(H5D_t *dset, hid_t dxpl_id)
if(dset->shared->layout.u.chunk.addr == HADDR_UNDEF)
ret_value = 0;
else
- ret_value = H5D_istore_allocated(dset, dxpl_id);
+ if(H5D_chunk_allocated(dset, dxpl_id, &ret_value) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, 0, "can't retrieve chunked dataset allocated size")
break;
case H5D_CONTIGUOUS:
@@ -1977,8 +2010,6 @@ done:
haddr_t
H5D_get_offset(const H5D_t *dset)
{
- haddr_t base_addr;
- H5F_t *f;
haddr_t ret_value = HADDR_UNDEF;
FUNC_ENTER_NOAPI_NOINIT(H5D_get_offset)
@@ -1993,15 +2024,9 @@ H5D_get_offset(const H5D_t *dset)
case H5D_CONTIGUOUS:
/* If dataspace hasn't been allocated or dataset is stored in
* an external file, the value will be HADDR_UNDEF. */
- f = H5D_get_file(dset);
- base_addr = H5F_get_base_addr(f);
-
- /* If there's user block in file, returns the absolute dataset offset
- * from the beginning of file. */
- if(base_addr != HADDR_UNDEF)
- ret_value = dset->shared->layout.u.contig.addr + base_addr;
- else
- ret_value = dset->shared->layout.u.contig.addr;
+ if(dset->shared->dcpl_cache.efl.nused == 0 || H5F_addr_defined(dset->shared->layout.u.contig.addr))
+ /* Return the absolute dataset offset from the beginning of file. */
+ ret_value = dset->shared->layout.u.contig.addr + H5F_BASE_ADDR(dset->oloc.file);
break;
default:
@@ -2171,7 +2196,7 @@ H5D_vlen_get_buf_size(void UNUSED *elem, hid_t type_id, unsigned UNUSED ndim, co
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't resize tbuf")
/* Select point to read in */
- if(H5Sselect_elements(vlen_bufsize->fspace_id, H5S_SELECT_SET, (size_t)1, (const hsize_t **)point) < 0)
+ if(H5Sselect_elements(vlen_bufsize->fspace_id, H5S_SELECT_SET, (size_t)1, point) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't select point")
/* Read in the point (with the custom VL memory allocator) */
@@ -2241,7 +2266,7 @@ done:
* Function: H5D_set_extent
*
* Purpose: Based on H5D_extend, allows change to a lower dimension,
- * calls H5S_set_extent and H5D_istore_prune_by_extent instead
+ * calls H5S_set_extent and H5D_chunk_prune_by_extent instead
*
* Return: Non-negative on success, negative on failure
*
@@ -2254,9 +2279,9 @@ herr_t
H5D_set_extent(H5D_t *dset, const hsize_t *size, hid_t dxpl_id)
{
H5S_t *space; /* Dataset's dataspace */
- int rank; /* Dataspace # of dimensions */
- hsize_t curr_dims[H5O_LAYOUT_NDIMS]; /* Current dimension sizes */
- htri_t changed; /* Whether the dataspace changed size */
+ int rank; /* Dataspace # of dimensions */
+ hsize_t curr_dims[H5O_LAYOUT_NDIMS];/* Current dimension sizes */
+ htri_t changed; /* Whether the dataspace changed size */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5D_set_extent)
@@ -2265,6 +2290,10 @@ H5D_set_extent(H5D_t *dset, const hsize_t *size, hid_t dxpl_id)
HDassert(dset);
HDassert(size);
+ /* Check if we are allowed to modify this file */
+ if(0 == (H5F_INTENT(dset->oloc.file) & H5F_ACC_RDWR))
+ HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "no write intent on file")
+
/* Check if the filters in the DCPL will need to encode, and if so, can they? */
if(H5D_check_filters(dset) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't apply filters")
@@ -2274,20 +2303,22 @@ H5D_set_extent(H5D_t *dset, const hsize_t *size, hid_t dxpl_id)
/* Check if we are shrinking or expanding any of the dimensions */
if((rank = H5S_get_simple_extent_dims(space, curr_dims, NULL)) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get dataset dimensions")
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get dataset dimensions")
/* Modify the size of the data space */
if((changed = H5S_set_extent(space, size)) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to modify size of data space")
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to modify size of data space")
/* Don't bother updating things, unless they've changed */
- if(changed) {
+ if(changed)
+ {
hbool_t shrink = FALSE; /* Flag to indicate a dimension has shrank */
hbool_t expand = FALSE; /* Flag to indicate a dimension has grown */
unsigned u; /* Local index variable */
/* Determine if we are shrinking and/or expanding any dimensions */
- for(u = 0; u < (unsigned)rank; u++) {
+ for(u = 0; u < (unsigned)rank; u++)
+ {
if(size[u] < curr_dims[u])
shrink = TRUE;
if(size[u] > curr_dims[u])
@@ -2298,45 +2329,34 @@ H5D_set_extent(H5D_t *dset, const hsize_t *size, hid_t dxpl_id)
* Modify the dataset storage
*-------------------------------------------------------------------------
*/
- /* Mark the dataspace as dirty, for later writing to the file */
- dset->shared->space_dirty = TRUE;
-
/* Update the index values for the cached chunks for this dataset */
if(H5D_CHUNKED == dset->shared->layout.type)
- if(H5D_istore_update_cache(dset, dxpl_id) < 0)
+ if(H5D_chunk_update_cache(dset, dxpl_id) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to update cached chunk indices")
- /* Allocate space for the new parts of the dataset, if appropriate */
+ /* Allocate space for the new parts of the dataset, if appropriate */
if(expand && dset->shared->dcpl_cache.fill.alloc_time == H5D_ALLOC_TIME_EARLY)
- if(H5D_alloc_storage(dset->oloc.file, dxpl_id, dset, H5D_ALLOC_EXTEND, TRUE, FALSE) < 0)
+ if(H5D_alloc_storage(dset, dxpl_id, H5D_ALLOC_EXTEND, FALSE) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize dataset storage")
/*-------------------------------------------------------------------------
* Remove chunk information in the case of chunked datasets
* This removal takes place only in case we are shrinking the dateset
+ * and if the chunks are written
*-------------------------------------------------------------------------
*/
- if(shrink && H5D_CHUNKED == dset->shared->layout.type) {
- H5D_io_info_t io_info; /* Dataset I/O info */
- H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */
- H5D_dxpl_cache_t *dxpl_cache = &_dxpl_cache; /* Data transfer property cache */
-
- /* Fill the DXPL cache values for later use */
- if(H5D_get_dxpl_cache(dxpl_id, &dxpl_cache) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache")
+ if( shrink &&
+ H5D_CHUNKED == dset->shared->layout.type &&
+ H5F_addr_defined(dset->shared->layout.u.chunk.addr))
+ {
+ /* Remove excess chunks */
+ if(H5D_chunk_prune_by_extent(dset, dxpl_id, curr_dims) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to remove chunks ")
+ } /* end if */
- /* Construct dataset I/O info */
- H5D_BUILD_IO_INFO(&io_info, dset, dxpl_cache, dxpl_id, NULL);
-
- /* Remove excess chunks */
- if(H5D_istore_prune_by_extent(&io_info, curr_dims) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to remove chunks ")
-
- /* Reset the elements outsize the new dimensions, but in existing chunks */
- if(H5D_istore_initialize_by_extent(&io_info) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to initialize chunks ")
- } /* end if */
+ /* Mark the dataspace as dirty, for later writing to the file */
+ dset->shared->space_dirty = TRUE;
} /* end if */
done:
@@ -2345,7 +2365,7 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5D_flush_cb
+ * Function: H5D_flush_real
*
* Purpose: Flush any dataset information cached in memory
*
@@ -2353,69 +2373,132 @@ done:
* Failure: Negative
*
* Programmer: Quincey Koziol
- * November 8, 2007
+ * December 6, 2007
*
*-------------------------------------------------------------------------
*/
-static int
-H5D_flush_cb(void *_dataset, hid_t UNUSED id, void *_udata)
+static herr_t
+H5D_flush_real(H5D_t *dataset, hid_t dxpl_id, unsigned flags)
{
- H5D_t *dataset = (H5D_t *)_dataset; /* Dataset pointer */
- H5D_flush_ud_t *udata = (H5D_flush_ud_t *)_udata; /* User data for callback */
- int ret_value = H5_ITER_CONT; /* Return value */
+ H5O_t *oh = NULL; /* Pointer to dataset's object header */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5D_flush_cb)
+ FUNC_ENTER_NOAPI_NOINIT(H5D_flush_real)
/* Check args */
HDassert(dataset);
- /* Check for dataset in same file */
- if(udata->f == dataset->oloc.file) {
+ /* Check for metadata changes that will require updating the object's modification time */
+ if(dataset->shared->layout_dirty || dataset->shared->space_dirty) {
+ unsigned update_flags = H5O_UPDATE_TIME; /* Modification time flag */
+
+ /* Get a pointer to the dataset's object header */
+ if((oh = H5O_protect(&dataset->oloc, dxpl_id)) == NULL)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTPROTECT, FAIL, "unable to protect dataset object header")
+
+ /* Update the layout on disk, if it's been changed */
+ if(dataset->shared->layout_dirty) {
+ if(H5O_msg_write_oh(dataset->oloc.file, dxpl_id, oh, H5O_LAYOUT_ID, H5O_MSG_FLAG_CONSTANT, update_flags, &dataset->shared->layout) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to update layout message")
+ dataset->shared->layout_dirty = FALSE;
+
+ /* Reset the "update the modification time" flag, so we only do it once */
+ update_flags = 0;
+ } /* end if */
+
/* Update the dataspace on disk, if it's been changed */
if(dataset->shared->space_dirty) {
- if(H5S_write(&(dataset->oloc), dataset->shared->space, TRUE, udata->dxpl_id) < 0)
+ if(H5S_write(dataset->oloc.file, dxpl_id, oh, update_flags, dataset->shared->space) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to update file with new dataspace")
dataset->shared->space_dirty = FALSE;
+
+ /* Reset the "update the modification time" flag, so we only do it once */
+ update_flags = 0;
} /* end if */
- /* Flush the raw data buffer, if we have a dirty one */
- if(dataset->shared->cache.contig.sieve_buf && dataset->shared->cache.contig.sieve_dirty) {
- HDassert(dataset->shared->layout.type != H5D_COMPACT); /* We should never have a sieve buffer for compact storage */
+ /* _Somebody_ should have update the modification time! */
+ HDassert(update_flags == 0);
+ } /* end if */
- /* Write dirty data sieve buffer to file */
- if(H5F_block_write(udata->f, H5FD_MEM_DRAW, dataset->shared->cache.contig.sieve_loc,
- dataset->shared->cache.contig.sieve_size, udata->dxpl_id, dataset->shared->cache.contig.sieve_buf) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed")
+ /* Flush the raw data buffer, if we have a dirty one */
+ if(dataset->shared->cache.contig.sieve_buf && dataset->shared->cache.contig.sieve_dirty) {
+ HDassert(dataset->shared->layout.type != H5D_COMPACT); /* We should never have a sieve buffer for compact storage */
- /* Reset sieve buffer dirty flag */
- dataset->shared->cache.contig.sieve_dirty = FALSE;
- } /* end if */
+ /* Write dirty data sieve buffer to file */
+ if(H5F_block_write(dataset->oloc.file, H5FD_MEM_DRAW, dataset->shared->cache.contig.sieve_loc,
+ dataset->shared->cache.contig.sieve_size, dxpl_id, dataset->shared->cache.contig.sieve_buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed")
- /* Flush cached information for each kind of dataset */
- switch(dataset->shared->layout.type) {
- case H5D_CONTIGUOUS:
- break;
+ /* Reset sieve buffer dirty flag */
+ dataset->shared->cache.contig.sieve_dirty = FALSE;
+ } /* end if */
- case H5D_CHUNKED:
- /* Flush the raw data cache */
- if(H5D_istore_flush(dataset, udata->dxpl_id, udata->flags & H5F_FLUSH_INVALIDATE) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush raw data cache")
- break;
+ /* Flush cached information for each kind of dataset */
+ switch(dataset->shared->layout.type) {
+ case H5D_CONTIGUOUS:
+ break;
- case H5D_COMPACT:
- if(dataset->shared->layout.u.compact.dirty) {
- if(H5O_msg_write(&(dataset->oloc), H5O_LAYOUT_ID, 0, H5O_UPDATE_TIME, &(dataset->shared->layout), udata->dxpl_id) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to update layout message")
- dataset->shared->layout.u.compact.dirty = FALSE;
- } /* end if */
- break;
+ case H5D_CHUNKED:
+ /* Flush the raw data cache */
+ if(H5D_chunk_flush(dataset, dxpl_id, flags & H5F_FLUSH_INVALIDATE) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush raw data cache")
+ break;
- default:
- HDassert("not implemented yet" && 0);
+ case H5D_COMPACT:
+ if(dataset->shared->layout.u.compact.dirty) {
+ if(H5O_msg_write(&(dataset->oloc), H5O_LAYOUT_ID, 0, H5O_UPDATE_TIME, &(dataset->shared->layout), dxpl_id) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to update layout message")
+ dataset->shared->layout.u.compact.dirty = FALSE;
+ } /* end if */
+ break;
+
+ default:
+ HDassert("not implemented yet" && 0);
#ifdef NDEBUG
- HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "unsupported storage layout")
+ HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "unsupported storage layout")
#endif /* NDEBUG */
- } /* end switch */ /*lint !e788 All appropriate cases are covered */
+ } /* end switch */ /*lint !e788 All appropriate cases are covered */
+
+done:
+ /* Release pointer to object header */
+ if(oh != NULL)
+ if(H5O_unprotect(&(dataset->oloc), oh) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTUNPROTECT, FAIL, "unable to unprotect dataset object header")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_flush_real() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_flush_cb
+ *
+ * Purpose: Flush any dataset information cached in memory
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * November 8, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+H5D_flush_cb(void *_dataset, hid_t UNUSED id, void *_udata)
+{
+ H5D_t *dataset = (H5D_t *)_dataset; /* Dataset pointer */
+ H5D_flush_ud_t *udata = (H5D_flush_ud_t *)_udata; /* User data for callback */
+ int ret_value = H5_ITER_CONT; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_flush_cb)
+
+ /* Check args */
+ HDassert(dataset);
+
+ /* Check for dataset in same file */
+ if(udata->f == dataset->oloc.file) {
+ /* Flush the dataset's information */
+ if(H5D_flush_real(dataset, udata->dxpl_id, udata->flags) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, H5_ITER_ERROR, "unable to flush cached dataset info")
} /* end if */
done:
@@ -2453,10 +2536,9 @@ H5D_flush(const H5F_t *f, hid_t dxpl_id, unsigned flags)
udata.flags = flags;
/* Iterate over all the open datasets */
- H5I_search(H5I_DATASET, H5D_flush_cb, &udata);
+ H5I_search(H5I_DATASET, H5D_flush_cb, &udata, FALSE);
done:
-
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_flush() */
diff --git a/src/H5Dio.c b/src/H5Dio.c
index 6a6d532..b7c1d72 100644
--- a/src/H5Dio.c
+++ b/src/H5Dio.c
@@ -28,21 +28,17 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5FLprivate.h" /* Free Lists */
#include "H5Iprivate.h" /* IDs */
-#include "H5MMprivate.h" /* Memory management */
-#include "H5Sprivate.h" /* Dataspace functions */
-#include "H5SLprivate.h" /* Skip lists */
-#include "H5Vprivate.h" /* Vector and array functions */
#ifdef H5_HAVE_PARALLEL
/* Remove this if H5R_DATASET_REGION is no longer used in this file */
-# include "H5Rpublic.h"
+#include "H5Rpublic.h"
#endif /*H5_HAVE_PARALLEL*/
+
/****************/
/* Local Macros */
/****************/
-#define H5D_DEFAULT_SKIPLIST_HEIGHT 8
/******************/
/* Local Typedefs */
@@ -53,60 +49,36 @@
/* Local Prototypes */
/********************/
+/* Internal I/O routines */
static herr_t H5D_read(H5D_t *dataset, hid_t mem_type_id,
- const H5S_t *mem_space, const H5S_t *file_space,
- hid_t dset_xfer_plist, void *buf/*out*/);
+ const H5S_t *mem_space, const H5S_t *file_space, hid_t dset_xfer_plist,
+ void *buf/*out*/);
static herr_t H5D_write(H5D_t *dataset, hid_t mem_type_id,
- const H5S_t *mem_space, const H5S_t *file_space,
- hid_t dset_xfer_plist, const void *buf);
-static herr_t H5D_contig_read(H5D_io_info_t *io_info, hsize_t nelmts,
- const H5T_t *mem_type, const H5S_t *mem_space,
- const H5S_t *file_space, H5T_path_t *tpath,
- hid_t src_id, hid_t dst_id, void *buf/*out*/);
-static herr_t H5D_contig_write(H5D_io_info_t *io_info, hsize_t nelmts,
- const H5T_t *mem_type, const H5S_t *mem_space,
- const H5S_t *file_space, H5T_path_t *tpath,
- hid_t src_id, hid_t dst_id, const void *buf);
-static herr_t H5D_chunk_read(H5D_io_info_t *io_info, hsize_t nelmts,
- const H5T_t *mem_type, const H5S_t *mem_space,
- const H5S_t *file_space, H5T_path_t *tpath,
- hid_t src_id, hid_t dst_id, void *buf/*out*/);
-static herr_t H5D_chunk_write(H5D_io_info_t *io_info, hsize_t nelmts,
- const H5T_t *mem_type, const H5S_t *mem_space,
- const H5S_t *file_space, H5T_path_t *tpath,
- hid_t src_id, hid_t dst_id, const void *buf);
-static herr_t H5D_compound_opt_read(size_t nelmts, const H5S_t *mem_space,
- H5S_sel_iter_t *iter, const H5D_dxpl_cache_t *dxpl_cache,
- hid_t src_id, hid_t dst_id, H5T_subset_t subset, void *data_buf,
- void *user_buf/*out*/);
-static herr_t H5D_compound_opt_write(size_t nelmts, hid_t src_id, hid_t dst_id,
- void *data_buf);
+ const H5S_t *mem_space, const H5S_t *file_space, hid_t dset_xfer_plist,
+ const void *buf);
+/* Setup/teardown routines */
+static herr_t H5D_ioinfo_init(H5D_t *dset, const H5D_dxpl_cache_t *dxpl_cache,
+ hid_t dxpl_id, const H5D_type_info_t *type_info, H5D_storage_t *store,
+ H5D_io_info_t *io_info);
+static herr_t H5D_typeinfo_init(const H5D_t *dset, const H5D_dxpl_cache_t *dxpl_cache,
+ hid_t dxpl_id, hid_t mem_type_id, hbool_t do_write,
+ H5D_type_info_t *type_info);
#ifdef H5_HAVE_PARALLEL
+static herr_t H5D_ioinfo_adjust(H5D_io_info_t *io_info, const H5D_t *dset,
+ const H5D_dxpl_cache_t *dxpl_cache, hid_t dxpl_id,
+ const H5S_t *file_space, const H5S_t *mem_space,
+ const H5D_type_info_t *type_info, const H5D_chunk_map_t *fm);
static herr_t H5D_ioinfo_term(H5D_io_info_t *io_info);
#endif /* H5_HAVE_PARALLEL */
+static herr_t H5D_typeinfo_term(const H5D_type_info_t *type_info);
-/* I/O info operations */
-static herr_t H5D_ioinfo_init(H5D_t *dset, const H5D_dxpl_cache_t *dxpl_cache,
- hid_t dxpl_id, const H5S_t *mem_space, const H5S_t *file_space,
- H5T_path_t *tpath, H5D_io_info_t *io_info);
-
-/* Chunk operations */
-static herr_t H5D_create_chunk_map(const H5D_t *dataset, const H5T_t *mem_type,
- const H5S_t *file_space, const H5S_t *mem_space, fm_map *fm);
-static herr_t H5D_destroy_chunk_map(const fm_map *fm);
-static herr_t H5D_free_chunk_info(void *item, void *key, void *opdata);
-static herr_t H5D_create_chunk_file_map_hyper(fm_map *fm, const H5D_t *dset);
-static herr_t H5D_create_chunk_mem_map_hyper(const fm_map *fm);
-static herr_t H5D_chunk_file_cb(void *elem, hid_t type_id, unsigned ndims,
- const hsize_t *coords, void *fm);
-static herr_t H5D_chunk_mem_cb(void *elem, hid_t type_id, unsigned ndims,
- const hsize_t *coords, void *fm);
/*********************/
/* Package Variables */
/*********************/
+
/*******************/
/* Local Variables */
/*******************/
@@ -114,142 +86,6 @@ static herr_t H5D_chunk_mem_cb(void *elem, hid_t type_id, unsigned ndims,
/* Declare a free list to manage blocks of type conversion data */
H5FL_BLK_DEFINE(type_conv);
-/* Declare a free list to manage the H5D_chunk_info_t struct */
-H5FL_DEFINE_STATIC(H5D_chunk_info_t);
-
-/* Declare a free list to manage sequences of size_t */
-H5FL_SEQ_DEFINE_STATIC(size_t);
-
-/* Declare a free list to manage sequences of hsize_t */
-H5FL_SEQ_DEFINE_STATIC(hsize_t);
-
-
-
-/*--------------------------------------------------------------------------
- NAME
- H5D_get_dxpl_cache_real
- PURPOSE
- Get all the values for the DXPL cache.
- USAGE
- herr_t H5D_get_dxpl_cache_real(dxpl_id, cache)
- hid_t dxpl_id; IN: DXPL to query
- H5D_dxpl_cache_t *cache;IN/OUT: DXPL cache to fill with values
- RETURNS
- Non-negative on success/Negative on failure.
- DESCRIPTION
- Query all the values from a DXPL that are needed by internal routines
- within the library.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-herr_t
-H5D_get_dxpl_cache_real(hid_t dxpl_id, H5D_dxpl_cache_t *cache)
-{
- H5P_genplist_t *dx_plist; /* Data transfer property list */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5D_get_dxpl_cache_real,FAIL)
-
- /* Check args */
- assert(cache);
-
- /* Get the dataset transfer property list */
- if (NULL == (dx_plist = H5I_object(dxpl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list")
-
- /* Get maximum temporary buffer size */
- if(H5P_get(dx_plist, H5D_XFER_MAX_TEMP_BUF_NAME, &cache->max_temp_buf) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve maximum temporary buffer size")
-
- /* Get temporary buffer pointer */
- if(H5P_get(dx_plist, H5D_XFER_TCONV_BUF_NAME, &cache->tconv_buf) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve temporary buffer pointer")
-
- /* Get background buffer pointer */
- if(H5P_get(dx_plist, H5D_XFER_BKGR_BUF_NAME, &cache->bkgr_buf) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve background buffer pointer")
-
- /* Get background buffer type */
- if(H5P_get(dx_plist, H5D_XFER_BKGR_BUF_TYPE_NAME, &cache->bkgr_buf_type) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve background buffer type")
-
- /* Get B-tree split ratios */
- if(H5P_get(dx_plist, H5D_XFER_BTREE_SPLIT_RATIO_NAME, &cache->btree_split_ratio) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve B-tree split ratios")
-
- /* Get I/O vector size */
- if(H5P_get(dx_plist, H5D_XFER_HYPER_VECTOR_SIZE_NAME, &cache->vec_size) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve I/O vector size")
-
-#ifdef H5_HAVE_PARALLEL
- /* Collect Parallel I/O information for possible later use */
- if(H5P_get(dx_plist, H5D_XFER_IO_XFER_MODE_NAME, &cache->xfer_mode) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve parallel transfer method")
- if(H5P_get(dx_plist, H5D_XFER_IO_XFER_OPT_MODE_NAME, &cache->xfer_opt_mode) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve parallel transfer method")
-#endif /*H5_HAVE_PARALLEL*/
-
- /* Get error detection properties */
- if(H5P_get(dx_plist, H5D_XFER_EDC_NAME, &cache->err_detect) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve error detection info")
-
- /* Get filter callback function */
- if(H5P_get(dx_plist, H5D_XFER_FILTER_CB_NAME, &cache->filter_cb) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve filter callback function")
-
- /* Get the data transform property */
- if(H5P_get(dx_plist, H5D_XFER_XFORM_NAME, &cache->data_xform_prop) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve data transform info")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5D_get_dxpl_cache_real() */
-
-
-/*--------------------------------------------------------------------------
- NAME
- H5D_get_dxpl_cache
- PURPOSE
- Get all the values for the DXPL cache.
- USAGE
- herr_t H5D_get_dxpl_cache(dxpl_id, cache)
- hid_t dxpl_id; IN: DXPL to query
- H5D_dxpl_cache_t *cache;IN/OUT: DXPL cache to fill with values
- RETURNS
- Non-negative on success/Negative on failure.
- DESCRIPTION
- Query all the values from a DXPL that are needed by internal routines
- within the library.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- The CACHE pointer should point at already allocated memory to place
- non-default property list info. If a default property list is used, the
- CACHE pointer will be changed to point at the default information.
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-herr_t
-H5D_get_dxpl_cache(hid_t dxpl_id, H5D_dxpl_cache_t **cache)
-{
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5D_get_dxpl_cache,FAIL)
-
- /* Check args */
- assert(cache);
-
- /* Check for the default DXPL */
- if(dxpl_id==H5P_DATASET_XFER_DEFAULT)
- *cache=&H5D_def_dxpl_cache;
- else
- if(H5D_get_dxpl_cache_real(dxpl_id,*cache) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "Can't retrieve DXPL values")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5D_get_dxpl_cache() */
/*-------------------------------------------------------------------------
@@ -290,57 +126,57 @@ H5Dread(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id,
const H5S_t *mem_space = NULL;
const H5S_t *file_space = NULL;
char fake_char;
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(H5Dread, FAIL)
H5TRACE6("e", "iiiiix", dset_id, mem_type_id, mem_space_id, file_space_id,
plist_id, buf);
/* check arguments */
- if(NULL == (dset = H5I_object_verify(dset_id, H5I_DATASET)))
+ if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
if(NULL == dset->oloc.file)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
if(H5S_ALL != mem_space_id) {
- if(NULL == (mem_space = H5I_object_verify(mem_space_id, H5I_DATASPACE)))
+ if(NULL == (mem_space = (const H5S_t *)H5I_object_verify(mem_space_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space")
/* Check for valid selection */
- if(H5S_SELECT_VALID(mem_space)!=TRUE)
+ if(H5S_SELECT_VALID(mem_space) != TRUE)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "selection+offset not within extent")
} /* end if */
if(H5S_ALL != file_space_id) {
- if(NULL == (file_space = H5I_object_verify(file_space_id, H5I_DATASPACE)))
+ if(NULL == (file_space = (const H5S_t *)H5I_object_verify(file_space_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space")
/* Check for valid selection */
- if(H5S_SELECT_VALID(file_space)!=TRUE)
+ if(H5S_SELECT_VALID(file_space) != TRUE)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "selection+offset not within extent")
- }
+ } /* end if */
/* Get the default dataset transfer property list if the user didn't provide one */
if (H5P_DEFAULT == plist_id)
plist_id= H5P_DATASET_XFER_DEFAULT;
else
- if (TRUE!=H5P_isa_class(plist_id,H5P_DATASET_XFER))
+ if(TRUE != H5P_isa_class(plist_id, H5P_DATASET_XFER))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms")
- if (!buf && H5S_GET_SELECT_NPOINTS(file_space)!=0)
+ if(!buf && H5S_GET_SELECT_NPOINTS(file_space) != 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no output buffer")
/* If the buffer is nil, and 0 element is selected, make a fake buffer.
- * This is for some MPI package like ChaMPIon on NCSA's tungsten which
- * doesn't support this feature.
- */
- if (!buf)
+ * This is for some MPI package like ChaMPIon on NCSA's tungsten which
+ * doesn't support this feature.
+ */
+ if(!buf)
buf = &fake_char;
/* read raw data */
- if (H5D_read(dset, mem_type_id, mem_space, file_space, plist_id, buf/*out*/) < 0)
+ if(H5D_read(dset, mem_type_id, mem_space, file_space, plist_id, buf/*out*/) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read data")
done:
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5Dread() */
/*-------------------------------------------------------------------------
@@ -382,31 +218,31 @@ H5Dwrite(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id,
const H5S_t *mem_space = NULL;
const H5S_t *file_space = NULL;
char fake_char;
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(H5Dwrite, FAIL)
H5TRACE6("e", "iiiii*x", dset_id, mem_type_id, mem_space_id, file_space_id,
plist_id, buf);
/* check arguments */
- if(NULL == (dset = H5I_object_verify(dset_id, H5I_DATASET)))
+ if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
if(NULL == dset->oloc.file)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
if(H5S_ALL != mem_space_id) {
- if(NULL == (mem_space = H5I_object_verify(mem_space_id, H5I_DATASPACE)))
+ if(NULL == (mem_space = (const H5S_t *)H5I_object_verify(mem_space_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space")
/* Check for valid selection */
- if (H5S_SELECT_VALID(mem_space)!=TRUE)
+ if(H5S_SELECT_VALID(mem_space) != TRUE)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "memory selection+offset not within extent")
} /* end if */
if(H5S_ALL != file_space_id) {
- if(NULL == (file_space = H5I_object_verify(file_space_id, H5I_DATASPACE)))
+ if(NULL == (file_space = (const H5S_t *)H5I_object_verify(file_space_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space")
/* Check for valid selection */
- if(H5S_SELECT_VALID(file_space)!=TRUE)
+ if(H5S_SELECT_VALID(file_space) != TRUE)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "file selection+offset not within extent")
} /* end if */
@@ -414,16 +250,16 @@ H5Dwrite(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id,
if(H5P_DEFAULT == plist_id)
plist_id= H5P_DATASET_XFER_DEFAULT;
else
- if(TRUE!=H5P_isa_class(plist_id,H5P_DATASET_XFER))
+ if(TRUE != H5P_isa_class(plist_id, H5P_DATASET_XFER))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms")
- if(!buf && H5S_GET_SELECT_NPOINTS(file_space)!=0)
+ if(!buf && H5S_GET_SELECT_NPOINTS(file_space) != 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no output buffer")
-
+
/* If the buffer is nil, and 0 element is selected, make a fake buffer.
- * This is for some MPI package like ChaMPIon on NCSA's tungsten which
- * doesn't support this feature.
- */
- if (!buf)
+ * This is for some MPI package like ChaMPIon on NCSA's tungsten which
+ * doesn't support this feature.
+ */
+ if(!buf)
buf = &fake_char;
/* write raw data */
@@ -432,7 +268,7 @@ H5Dwrite(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id,
done:
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5Dwrite() */
/*-------------------------------------------------------------------------
@@ -452,16 +288,19 @@ static herr_t
H5D_read(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space,
const H5S_t *file_space, hid_t dxpl_id, void *buf/*out*/)
{
+ H5D_chunk_map_t fm; /* Chunk file<->memory mapping */
+ H5D_io_info_t io_info; /* Dataset I/O info */
+ H5D_type_info_t type_info; /* Datatype info for operation */
+ hbool_t type_info_init = FALSE; /* Whether the datatype info has been initialized */
+ H5D_storage_t store; /*union of EFL and chunk pointer in file space */
hssize_t snelmts; /*total number of elmts (signed) */
hsize_t nelmts; /*total number of elmts */
- H5T_path_t *tpath = NULL; /*type conversion info */
- const H5T_t *mem_type = NULL; /* Memory datatype */
- H5D_io_info_t io_info; /* Dataset I/O info */
#ifdef H5_HAVE_PARALLEL
hbool_t io_info_init = FALSE; /* Whether the I/O info has been initialized */
#endif /*H5_HAVE_PARALLEL*/
+ hbool_t io_op_init = FALSE; /* Whether the I/O op has been initialized */
H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */
- H5D_dxpl_cache_t *dxpl_cache=&_dxpl_cache; /* Data transfer property cache */
+ H5D_dxpl_cache_t *dxpl_cache = &_dxpl_cache; /* Data transfer property cache */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5D_read)
@@ -469,10 +308,6 @@ H5D_read(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space,
/* check args */
HDassert(dataset && dataset->oloc.file);
- /* Get memory datatype */
- if(NULL == (mem_type = H5I_object_verify(mem_type_id, H5I_DATATYPE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
-
if(!file_space)
file_space = dataset->shared->space;
if(!mem_space)
@@ -482,23 +317,28 @@ H5D_read(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space,
H5_ASSIGN_OVERFLOW(nelmts,snelmts,hssize_t,hsize_t);
/* Fill the DXPL cache values for later use */
- if(H5D_get_dxpl_cache(dxpl_id,&dxpl_cache) < 0)
+ if(H5D_get_dxpl_cache(dxpl_id, &dxpl_cache) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache")
+ /* Set up datatype info for operation */
+ if(H5D_typeinfo_init(dataset, dxpl_cache, dxpl_id, mem_type_id, FALSE, &type_info) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set up type info")
+ type_info_init = TRUE;
+
#ifdef H5_HAVE_PARALLEL
/* Collective access is not permissible without a MPI based VFD */
- if (dxpl_cache->xfer_mode==H5FD_MPIO_COLLECTIVE && !IS_H5FD_MPI(dataset->oloc.file))
+ if(dxpl_cache->xfer_mode == H5FD_MPIO_COLLECTIVE && !IS_H5FD_MPI(dataset->oloc.file))
HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "collective access for MPI-based drivers only")
#endif /*H5_HAVE_PARALLEL*/
/* Make certain that the number of elements in each selection is the same */
- if (nelmts!=(hsize_t)H5S_GET_SELECT_NPOINTS(file_space))
+ if(nelmts != (hsize_t)H5S_GET_SELECT_NPOINTS(file_space))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "src and dest data spaces have different sizes")
/* Make sure that both selections have their extents set */
- if( !(H5S_has_extent(file_space)) )
+ if(!(H5S_has_extent(file_space)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file dataspace does not have extent set")
- if( !(H5S_has_extent(mem_space)) )
+ if(!(H5S_has_extent(mem_space)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "memory dataspace does not have extent set")
/* Retrieve dataset properties */
@@ -529,49 +369,56 @@ H5D_read(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space,
HGOTO_DONE(SUCCEED)
/* Go fill the user's selection with the dataset's fill value */
- if(H5D_fill(dataset->shared->dcpl_cache.fill.buf, dataset->shared->type, buf, mem_type, mem_space, dxpl_id) < 0)
+ if(H5D_fill(dataset->shared->dcpl_cache.fill.buf, dataset->shared->type, buf, type_info.mem_type, mem_space, dxpl_id) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "filling buf failed")
else
HGOTO_DONE(SUCCEED)
} /* end if */
- /*
- * Locate the type conversion function and data space conversion
- * functions, and set up the element numbering information. If a data
- * type conversion is necessary then register datatype atoms. Data type
- * conversion is necessary if the user has set the `need_bkg' to a high
- * enough value in xfer_parms since turning off datatype conversion also
- * turns off background preservation.
- */
- if (NULL==(tpath=H5T_path_find(dataset->shared->type, mem_type, NULL, NULL, dxpl_id, FALSE)))
- HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest datatype")
-
/* Set up I/O operation */
- if(H5D_ioinfo_init(dataset,dxpl_cache,dxpl_id,mem_space,file_space,tpath,&io_info) < 0)
+ io_info.op_type = H5D_IO_OP_READ;
+ io_info.u.rbuf = buf;
+ if(H5D_ioinfo_init(dataset, dxpl_cache, dxpl_id, &type_info, &store, &io_info) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to set up I/O operation")
#ifdef H5_HAVE_PARALLEL
io_info_init = TRUE;
#endif /*H5_HAVE_PARALLEL*/
- /* Determine correct I/O routine to invoke */
- if(dataset->shared->layout.type!=H5D_CHUNKED) {
- if(H5D_contig_read(&io_info, nelmts, mem_type, mem_space, file_space, tpath,
- dataset->shared->type_id, mem_type_id, buf) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read data")
- } /* end if */
- else {
- if(H5D_chunk_read(&io_info, nelmts, mem_type, mem_space, file_space, tpath,
- dataset->shared->type_id, mem_type_id, buf) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read data")
- } /* end else */
+ /* Sanity check that space is allocated, if there are elements */
+ if(nelmts > 0)
+ HDassert(((dataset->shared->layout.type == H5D_CONTIGUOUS && H5F_addr_defined(dataset->shared->layout.u.contig.addr))
+ || (dataset->shared->layout.type == H5D_CHUNKED && H5F_addr_defined(dataset->shared->layout.u.chunk.addr)))
+ || dataset->shared->dcpl_cache.efl.nused > 0
+ || dataset->shared->layout.type == H5D_COMPACT);
+
+ /* Call storage method's I/O initialization routine */
+ if(io_info.layout_ops.io_init && (*io_info.layout_ops.io_init)(&io_info, &type_info, nelmts, file_space, mem_space, &fm) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize I/O info")
+ io_op_init = TRUE;
+
+#ifdef H5_HAVE_PARALLEL
+ /* Adjust I/O info for any parallel I/O */
+ if(H5D_ioinfo_adjust(&io_info, dataset, dxpl_cache, dxpl_id, file_space, mem_space, &type_info, &fm) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to adjust I/O info for parallel I/O")
+#endif /*H5_HAVE_PARALLEL*/
+
+ /* Invoke correct "high level" I/O routine */
+ if((*io_info.io_ops.multi_read)(&io_info, &type_info, nelmts, file_space, mem_space, &fm) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read data")
done:
+ /* Shut down the I/O op information */
+ if(io_op_init && io_info.layout_ops.io_term && (*io_info.layout_ops.io_term)(&fm) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to shut down I/O op info")
#ifdef H5_HAVE_PARALLEL
/* Shut down io_info struct */
- if (io_info_init)
+ if(io_info_init)
if(H5D_ioinfo_term(&io_info) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "can't shut down io_info")
#endif /*H5_HAVE_PARALLEL*/
+ /* Shut down datatype info for operation */
+ if(type_info_init && H5D_typeinfo_term(&type_info) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to shut down type info")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_read() */
@@ -594,16 +441,19 @@ static herr_t
H5D_write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space,
const H5S_t *file_space, hid_t dxpl_id, const void *buf)
{
+ H5D_chunk_map_t fm; /* Chunk file<->memory mapping */
+ H5D_io_info_t io_info; /* Dataset I/O info */
+ H5D_type_info_t type_info; /* Datatype info for operation */
+ hbool_t type_info_init = FALSE; /* Whether the datatype info has been initialized */
+ H5D_storage_t store; /*union of EFL and chunk pointer in file space */
hssize_t snelmts; /*total number of elmts (signed) */
hsize_t nelmts; /*total number of elmts */
- H5T_path_t *tpath = NULL; /*type conversion info */
- const H5T_t *mem_type = NULL; /* Memory datatype */
- H5D_io_info_t io_info; /* Dataset I/O info */
#ifdef H5_HAVE_PARALLEL
hbool_t io_info_init = FALSE; /* Whether the I/O info has been initialized */
#endif /*H5_HAVE_PARALLEL*/
+ hbool_t io_op_init = FALSE; /* Whether the I/O op has been initialized */
H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */
- H5D_dxpl_cache_t *dxpl_cache=&_dxpl_cache; /* Data transfer property cache */
+ H5D_dxpl_cache_t *dxpl_cache = &_dxpl_cache; /* Data transfer property cache */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5D_write)
@@ -611,32 +461,34 @@ H5D_write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space,
/* check args */
HDassert(dataset && dataset->oloc.file);
- /* Get the memory datatype */
- if(NULL == (mem_type = H5I_object_verify(mem_type_id, H5I_DATATYPE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
-
/* All filters in the DCPL must have encoding enabled. */
if(!dataset->shared->checked_filters) {
- if(H5Z_can_apply(dataset->shared->dcpl_id, dataset->shared->type_id) <0)
+ if(H5Z_can_apply(dataset->shared->dcpl_id, dataset->shared->type_id) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_CANAPPLY, FAIL, "can't apply filters")
dataset->shared->checked_filters = TRUE;
} /* end if */
/* Check if we are allowed to write to this file */
- if(0==(H5F_get_intent(dataset->oloc.file) & H5F_ACC_RDWR))
+ if(0 == (H5F_INTENT(dataset->oloc.file) & H5F_ACC_RDWR))
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "no write intent on file")
/* Fill the DXPL cache values for later use */
- if(H5D_get_dxpl_cache(dxpl_id,&dxpl_cache) < 0)
+ if(H5D_get_dxpl_cache(dxpl_id, &dxpl_cache) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache")
+ /* Set up datatype info for operation */
+ if(H5D_typeinfo_init(dataset, dxpl_cache, dxpl_id, mem_type_id, TRUE, &type_info) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set up type info")
+ type_info_init = TRUE;
+
/* Various MPI based checks */
+#ifdef H5_HAVE_PARALLEL
if(IS_H5FD_MPI(dataset->oloc.file)) {
/* If MPI based VFD is used, no VL datatype support yet. */
/* This is because they use the global heap in the file and we don't */
/* support parallel access of that yet */
- if(H5T_detect_class(mem_type, H5T_VLEN)>0)
+ if(H5T_detect_class(type_info.mem_type, H5T_VLEN) > 0)
HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "Parallel IO does not support writing VL datatypes yet")
/* If MPI based VFD is used, no VL datatype support yet. */
@@ -645,43 +497,48 @@ H5D_write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space,
/* We should really use H5T_detect_class() here, but it will be difficult
* to detect the type of the reference if it is nested... -QAK
*/
- if (H5T_get_class(mem_type, TRUE)==H5T_REFERENCE &&
- H5T_get_ref_type(mem_type)==H5R_DATASET_REGION)
+ if(H5T_get_class(type_info.mem_type, TRUE) == H5T_REFERENCE &&
+ H5T_get_ref_type(type_info.mem_type) == H5R_DATASET_REGION)
HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "Parallel IO does not support writing region reference datatypes yet")
+
+ /* Can't write to chunked datasets with filters, in parallel */
+ if(dataset->shared->layout.type == H5D_CHUNKED &&
+ dataset->shared->dcpl_cache.pline.nused > 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "cannot write to chunked storage with filters in parallel")
} /* end if */
-#ifdef H5_HAVE_PARALLEL
else {
/* Collective access is not permissible without a MPI based VFD */
- if (dxpl_cache->xfer_mode==H5FD_MPIO_COLLECTIVE)
+ if(dxpl_cache->xfer_mode == H5FD_MPIO_COLLECTIVE)
HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "collective access for MPI-based driver only")
} /* end else */
#endif /*H5_HAVE_PARALLEL*/
- if (!file_space)
+ /* Initialize dataspace information */
+ if(!file_space)
file_space = dataset->shared->space;
- if (!mem_space)
+ if(!mem_space)
mem_space = file_space;
if((snelmts = H5S_GET_SELECT_NPOINTS(mem_space)) < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "src dataspace has invalid selection")
- H5_ASSIGN_OVERFLOW(nelmts,snelmts,hssize_t,hsize_t);
+ H5_ASSIGN_OVERFLOW(nelmts, snelmts, hssize_t, hsize_t);
/* Make certain that the number of elements in each selection is the same */
- if (nelmts!=(hsize_t)H5S_GET_SELECT_NPOINTS(file_space))
+ if(nelmts != (hsize_t)H5S_GET_SELECT_NPOINTS(file_space))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "src and dest data spaces have different sizes")
/* Make sure that both selections have their extents set */
- if( !(H5S_has_extent(file_space)) )
+ if(!(H5S_has_extent(file_space)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file dataspace does not have extent set")
- if( !(H5S_has_extent(mem_space)) )
+ if(!(H5S_has_extent(mem_space)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "memory dataspace does not have extent set")
/* Retrieve dataset properties */
/* <none needed currently> */
/* Allocate data space and initialize it if it hasn't been. */
- if(nelmts > 0 && dataset->shared->dcpl_cache.efl.nused==0 &&
- ((dataset->shared->layout.type==H5D_CONTIGUOUS && !H5F_addr_defined(dataset->shared->layout.u.contig.addr))
- || (dataset->shared->layout.type==H5D_CHUNKED && !H5F_addr_defined(dataset->shared->layout.u.chunk.addr)))) {
+ if(nelmts > 0 && dataset->shared->dcpl_cache.efl.nused == 0 &&
+ ((dataset->shared->layout.type == H5D_CONTIGUOUS && !H5F_addr_defined(dataset->shared->layout.u.contig.addr))
+ || (dataset->shared->layout.type == H5D_CHUNKED && !H5F_addr_defined(dataset->shared->layout.u.chunk.addr)))) {
hssize_t file_nelmts; /* Number of elements in file dataset's dataspace */
hbool_t full_overwrite; /* Whether we are over-writing all the elements */
@@ -693,42 +550,36 @@ H5D_write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space,
if(H5T_detect_class(dataset->shared->type, H5T_VLEN))
full_overwrite = FALSE;
else
- full_overwrite = (hsize_t)file_nelmts==nelmts ? TRUE : FALSE;
+ full_overwrite = (hsize_t)file_nelmts == nelmts ? TRUE : FALSE;
/* Allocate storage */
- if(H5D_alloc_storage(dataset->oloc.file, dxpl_id, dataset, H5D_ALLOC_WRITE, TRUE, full_overwrite) < 0)
+ if(H5D_alloc_storage(dataset, dxpl_id, H5D_ALLOC_WRITE, full_overwrite) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize storage")
} /* end if */
- /*
- * Locate the type conversion function and data space conversion
- * functions, and set up the element numbering information. If a data
- * type conversion is necessary then register datatype atoms. Data type
- * conversion is necessary if the user has set the `need_bkg' to a high
- * enough value in xfer_parms since turning off datatype conversion also
- * turns off background preservation.
- */
- if (NULL==(tpath=H5T_path_find(mem_type, dataset->shared->type, NULL, NULL, dxpl_id, FALSE)))
- HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest datatype")
-
/* Set up I/O operation */
- if(H5D_ioinfo_init(dataset,dxpl_cache,dxpl_id,mem_space,file_space,tpath,&io_info) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to set up I/O operation")
+ io_info.op_type = H5D_IO_OP_WRITE;
+ io_info.u.wbuf = buf;
+ if(H5D_ioinfo_init(dataset, dxpl_cache, dxpl_id, &type_info, &store, &io_info) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to set up I/O operation")
#ifdef H5_HAVE_PARALLEL
io_info_init = TRUE;
#endif /*H5_HAVE_PARALLEL*/
- /* Determine correct I/O routine to invoke */
- if(dataset->shared->layout.type!=H5D_CHUNKED) {
- if(H5D_contig_write(&io_info, nelmts, mem_type, mem_space, file_space, tpath,
- mem_type_id, dataset->shared->type_id, buf) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data")
- } /* end if */
- else {
- if(H5D_chunk_write(&io_info, nelmts, mem_type, mem_space, file_space, tpath,
- mem_type_id, dataset->shared->type_id, buf) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data")
- } /* end else */
+ /* Call storage method's I/O initialization routine */
+ if(io_info.layout_ops.io_init && (*io_info.layout_ops.io_init)(&io_info, &type_info, nelmts, file_space, mem_space, &fm) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize I/O info")
+ io_op_init = TRUE;
+
+#ifdef H5_HAVE_PARALLEL
+ /* Adjust I/O info for any parallel I/O */
+ if(H5D_ioinfo_adjust(&io_info, dataset, dxpl_cache, dxpl_id, file_space, mem_space, &type_info, &fm) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to adjust I/O info for parallel I/O")
+#endif /*H5_HAVE_PARALLEL*/
+
+ /* Invoke correct "high level" I/O routine */
+ if((*io_info.io_ops.multi_write)(&io_info, &type_info, nelmts, file_space, mem_space, &fm) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data")
#ifdef OLD_WAY
/*
@@ -746,2543 +597,325 @@ H5D_write(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space,
#endif /* OLD_WAY */
done:
+ /* Shut down the I/O op information */
+ if(io_op_init && io_info.layout_ops.io_term && (*io_info.layout_ops.io_term)(&fm) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to shut down I/O op info")
#ifdef H5_HAVE_PARALLEL
/* Shut down io_info struct */
- if (io_info_init)
- if(H5D_ioinfo_term(&io_info) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "can't shut down io_info")
+ if(io_info_init && H5D_ioinfo_term(&io_info) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "can't shut down io_info")
#endif /*H5_HAVE_PARALLEL*/
+ /* Shut down datatype info for operation */
+ if(type_info_init && H5D_typeinfo_term(&type_info) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "unable to shut down type info")
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_write() */
/*-------------------------------------------------------------------------
- * Function: H5D_contig_read
+ * Function: H5D_ioinfo_init
*
- * Purpose: Read from a contiguous dataset.
+ * Purpose: Routine for determining correct I/O operations for
+ * each I/O action.
*
* Return: Non-negative on success/Negative on failure
*
- * Programmer: Raymond Lu
- * Thursday, April 10, 2003
+ * Programmer: Quincey Koziol
+ * Thursday, September 30, 2004
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5D_contig_read(H5D_io_info_t *io_info, hsize_t nelmts,
- const H5T_t *mem_type, const H5S_t *mem_space,
- const H5S_t *file_space, H5T_path_t *tpath,
- hid_t src_id, hid_t dst_id, void *buf/*out*/)
+H5D_ioinfo_init(H5D_t *dset, const H5D_dxpl_cache_t *dxpl_cache, hid_t dxpl_id,
+ const H5D_type_info_t *type_info, H5D_storage_t *store, H5D_io_info_t *io_info)
{
- H5D_t *dataset=io_info->dset; /* Local pointer to dataset info */
- const H5D_dxpl_cache_t *dxpl_cache=io_info->dxpl_cache; /* Local pointer to dataset transfer info */
- herr_t status; /*function return status*/
-#ifdef H5S_DEBUG
- H5_timer_t timer;
-#endif
- size_t src_type_size; /*size of source type */
- size_t dst_type_size; /*size of destination type*/
- size_t max_type_size; /* Size of largest source/destination type */
- size_t target_size; /*desired buffer size */
- size_t request_nelmts; /*requested strip mine */
- H5S_sel_iter_t mem_iter; /*memory selection iteration info*/
- hbool_t mem_iter_init=0; /*memory selection iteration info has been initialized */
- H5S_sel_iter_t bkg_iter; /*background iteration info*/
- hbool_t bkg_iter_init=0; /*background iteration info has been initialized */
- H5S_sel_iter_t file_iter; /*file selection iteration info*/
- hbool_t file_iter_init=0; /*file selection iteration info has been initialized */
- H5T_bkg_t need_bkg; /*type of background buf*/
- uint8_t *tconv_buf = NULL; /*datatype conv buffer */
- uint8_t *bkg_buf = NULL; /*background buffer */
- hsize_t smine_start; /*strip mine start loc */
- size_t n, smine_nelmts; /*elements per strip */
- H5D_storage_t store; /*union of storage info for dataset */
-
-
- herr_t ret_value = SUCCEED; /*return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_contig_read)
-
- assert (buf);
-
- /* Initialize storage info for this dataset */
- if (dataset->shared->dcpl_cache.efl.nused > 0)
- HDmemcpy(&store.efl, &(dataset->shared->dcpl_cache.efl), sizeof(H5O_efl_t));
- else {
- store.contig.dset_addr = dataset->shared->layout.u.contig.addr;
- store.contig.dset_size = dataset->shared->layout.u.contig.size;
- } /* end if */
-
- /* Set dataset storage for I/O info */
- io_info->store=&store;
-
- /*
- * If there is no type conversion then read directly into the
- * application's buffer. This saves at least one mem-to-mem copy.
- */
- if ( H5Z_xform_noop(dxpl_cache->data_xform_prop) && H5T_path_noop(tpath)) {
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
- /* Sanity check dataset, then read it */
- assert(((dataset->shared->layout.type == H5D_CONTIGUOUS && H5F_addr_defined(dataset->shared->layout.u.contig.addr))
- || (dataset->shared->layout.type == H5D_CHUNKED && H5F_addr_defined(dataset->shared->layout.u.chunk.addr)))
- || dataset->shared->dcpl_cache.efl.nused > 0 || 0 == nelmts
- || dataset->shared->layout.type==H5D_COMPACT);
- H5_CHECK_OVERFLOW(nelmts,hsize_t,size_t);
-
-#ifdef H5_HAVE_PARALLEL
- if(io_info->dxpl_cache->xfer_mode == H5FD_MPIO_COLLECTIVE) {
- if(H5D_contig_collective_io(io_info,file_space,mem_space,buf,FALSE) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "contiguous read failed in collective mode");
- }
- else
-#endif
- {
- if((io_info->ops.read)(io_info, (size_t)nelmts,
- H5T_get_size(dataset->shared->type), file_space, mem_space,
- (haddr_t)0, NULL, buf/*out*/) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "contiguous read failed ");
- }
-
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[1].read_timer), &timer);
- io_info->stats->stats[1].read_nbytes += nelmts * H5T_get_size(dataset->shared->type);
- io_info->stats->stats[1].read_ncalls++;
-#endif
-
- /* direct xfer accomplished successfully */
- HGOTO_DONE(SUCCEED)
- } /* end if */
-
- /*
- * This is the general case (type conversion, usually).
- */
- if(nelmts==0)
- HGOTO_DONE(SUCCEED)
-
- /* Compute element sizes and other parameters */
- src_type_size = H5T_get_size(dataset->shared->type);
- dst_type_size = H5T_get_size(mem_type);
- max_type_size = MAX(src_type_size, dst_type_size);
- target_size = dxpl_cache->max_temp_buf;
- /* XXX: This could cause a problem if the user sets their buffer size
- * to the same size as the default, and then the dataset elements are
- * too large for the buffer... - QAK
- */
- if(target_size == H5D_TEMP_BUF_SIZE) {
- /* If the buffer is too small to hold even one element, make it bigger */
- if(target_size<max_type_size)
- target_size = max_type_size;
- /* If the buffer is too large to hold all the elements, make it smaller */
- else if(target_size>(nelmts*max_type_size))
- target_size=(size_t)(nelmts*max_type_size);
- } /* end if */
- request_nelmts = target_size / max_type_size;
-
- /* Sanity check elements in temporary buffer */
- if (request_nelmts==0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "temporary buffer max size is too small")
-
- /* Figure out the strip mine size. */
- if (H5S_select_iter_init(&file_iter, file_space, src_type_size) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize file selection information")
- file_iter_init=1; /*file selection iteration info has been initialized */
- if (H5S_select_iter_init(&mem_iter, mem_space, dst_type_size) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize memory selection information")
- mem_iter_init=1; /*file selection iteration info has been initialized */
- if (H5S_select_iter_init(&bkg_iter, mem_space, dst_type_size) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize background selection information")
- bkg_iter_init=1; /*file selection iteration info has been initialized */
-
- /*
- * Get a temporary buffer for type conversion unless the app has already
- * supplied one through the xfer properties. Instead of allocating a
- * buffer which is the exact size, we allocate the target size. The
- * malloc() is usually less resource-intensive if we allocate/free the
- * same size over and over.
- */
- if (H5T_path_bkg(tpath)) {
- H5T_bkg_t path_bkg; /* Type conversion's background info */
-
- /* Retrieve the bkgr buffer property */
- need_bkg=dxpl_cache->bkgr_buf_type;
- path_bkg = H5T_path_bkg(tpath);
- need_bkg = MAX(path_bkg, need_bkg);
- } else {
- need_bkg = H5T_BKG_NO; /*never needed even if app says yes*/
- } /* end else */
- if (NULL==(tconv_buf=dxpl_cache->tconv_buf)) {
- /* Allocate temporary buffer */
- if((tconv_buf=H5FL_BLK_MALLOC(type_conv,target_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion")
- } /* end if */
- if (need_bkg && NULL==(bkg_buf=dxpl_cache->bkgr_buf)) {
- /* Allocate background buffer */
- /* (Need calloc()-like call since memory needs to be initialized) */
- if((bkg_buf=H5FL_BLK_CALLOC(type_conv,(request_nelmts*dst_type_size)))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for background conversion")
- } /* end if */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_ioinfo_init)
- /* Start strip mining... */
- for (smine_start=0; smine_start<nelmts; smine_start+=smine_nelmts) {
- /* Go figure out how many elements to read from the file */
- assert(H5S_SELECT_ITER_NELMTS(&file_iter)==(nelmts-smine_start));
- smine_nelmts = (size_t)MIN(request_nelmts, (nelmts-smine_start));
+ /* check args */
+ HDassert(dset);
+ HDassert(dset->oloc.file);
+ HDassert(type_info);
+ HDassert(type_info->tpath);
+ HDassert(io_info);
- /*
- * Gather the data from disk into the datatype conversion
- * buffer. Also gather data from application to background buffer
- * if necessary.
- */
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
- /* Sanity check that space is allocated, then read data from it */
- HDassert(((dataset->shared->layout.type == H5D_CONTIGUOUS && H5F_addr_defined(dataset->shared->layout.u.contig.addr))
- || (dataset->shared->layout.type == H5D_CHUNKED && H5F_addr_defined(dataset->shared->layout.u.chunk.addr)))
- || dataset->shared->dcpl_cache.efl.nused > 0 ||
- dataset->shared->layout.type == H5D_COMPACT);
- n = H5D_select_fgath(io_info, file_space, &file_iter, smine_nelmts, (haddr_t)0, NULL, tconv_buf/*out*/);
-
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[1].gath_timer), &timer);
- io_info->stats->stats[1].gath_nbytes += n * src_type_size;
- io_info->stats->stats[1].gath_ncalls++;
-#endif
- if (n!=smine_nelmts)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file gather failed")
-
- /* If the source and destination are compound types and subset of each other
- * and no conversion is needed, copy the data directly into user's buffer and
- * bypass the rest of steps. This optimization is for Chicago company */
- if(H5T_SUBSET_SRC==H5T_path_compound_subset(tpath)) {
- if(H5D_compound_opt_read(smine_nelmts, mem_space, &mem_iter, dxpl_cache,
- src_id, dst_id, H5T_SUBSET_SRC, tconv_buf, buf /*out*/)<0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
-
- continue;
- } else if(H5T_SUBSET_DST==H5T_path_compound_subset(tpath)) {
- if(H5D_compound_opt_read(smine_nelmts, mem_space, &mem_iter, dxpl_cache,
- src_id, dst_id, H5T_SUBSET_DST, tconv_buf, buf /*out*/)<0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
-
- continue;
- }
-
- if (H5T_BKG_YES==need_bkg) {
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
- n = H5D_select_mgath(buf, mem_space, &bkg_iter,
- smine_nelmts, dxpl_cache, bkg_buf/*out*/);
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[1].bkg_timer), &timer);
- io_info->stats->stats[1].bkg_nbytes += n * dst_type_size;
- io_info->stats->stats[1].bkg_ncalls++;
-#endif
- if (n!=smine_nelmts)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "mem gather failed")
- } /* end if */
+ /* Set up "normal" I/O fields */
+ io_info->dset = dset;
+ io_info->dxpl_cache = dxpl_cache;
+ io_info->dxpl_id = dxpl_id;
+ io_info->store = store;
- /*
- * Perform datatype conversion.
- */
- if (H5T_convert(tpath, src_id, dst_id, smine_nelmts, (size_t)0, (size_t)0, tconv_buf, bkg_buf, io_info->dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
+ /* Set I/O operations to initial values */
+ io_info->layout_ops = *dset->shared->layout.ops;
- /* Do the data transform after the conversion (since we're using type mem_type) */
- if(!H5Z_xform_noop(dxpl_cache->data_xform_prop))
- if( H5Z_xform_eval(dxpl_cache->data_xform_prop, tconv_buf, smine_nelmts, mem_type) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Error performing data transform")
+ /* Set the "high-level" I/O operations for the dataset */
+ io_info->io_ops.multi_read = dset->shared->layout.ops->ser_read;
+ io_info->io_ops.multi_write = dset->shared->layout.ops->ser_write;
+ /* Set the I/O operations for reading/writing single blocks on disk */
+ if(type_info->is_xform_noop && type_info->is_conv_noop) {
/*
- * Scatter the data into memory.
+ * If there is no data transform or type conversion then read directly into
+ * the application's buffer. This saves at least one mem-to-mem copy.
*/
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
- status = H5D_select_mscat(tconv_buf, mem_space,
- &mem_iter, smine_nelmts, dxpl_cache, buf/*out*/);
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[1].scat_timer), &timer);
- io_info->stats->stats[1].scat_nbytes += smine_nelmts * dst_type_size;
- io_info->stats->stats[1].scat_ncalls++;
-#endif
- if (status<0)
- HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "scatter failed")
- } /* end for */
-
-done:
- /* Release selection iterators */
- if(file_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&file_iter) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- } /* end if */
- if(mem_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&mem_iter) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
+ io_info->io_ops.single_read = H5D_select_read;
+ io_info->io_ops.single_write = H5D_select_write;
} /* end if */
- if(bkg_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&bkg_iter) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- } /* end if */
-
- if (tconv_buf && NULL==dxpl_cache->tconv_buf)
- H5FL_BLK_FREE(type_conv,tconv_buf);
- if (bkg_buf && NULL==dxpl_cache->bkgr_buf)
- H5FL_BLK_FREE(type_conv,bkg_buf);
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_contig_read() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_contig_write
- *
- * Purpose: Write to a contiguous dataset.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Raymond Lu
- * Thursday, April 10, 2003
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D_contig_write(H5D_io_info_t *io_info, hsize_t nelmts,
- const H5T_t *mem_type, const H5S_t *mem_space,
- const H5S_t *file_space, H5T_path_t *tpath,
- hid_t src_id, hid_t dst_id, const void *buf)
-{
- H5D_t *dataset=io_info->dset; /* Local pointer to dataset info */
- const H5D_dxpl_cache_t *dxpl_cache=io_info->dxpl_cache; /* Local pointer to dataset transfer info */
- herr_t status; /*function return status*/
-#ifdef H5S_DEBUG
- H5_timer_t timer;
-#endif
- size_t src_type_size; /*size of source type */
- size_t dst_type_size; /*size of destination type*/
- size_t max_type_size; /* Size of largest source/destination type */
- size_t target_size; /*desired buffer size */
- size_t request_nelmts; /*requested strip mine */
- H5S_sel_iter_t mem_iter; /*memory selection iteration info*/
- hbool_t mem_iter_init=0; /*memory selection iteration info has been initialized */
- H5S_sel_iter_t bkg_iter; /*background iteration info*/
- hbool_t bkg_iter_init=0; /*background iteration info has been initialized */
- H5S_sel_iter_t file_iter; /*file selection iteration info*/
- hbool_t file_iter_init=0; /*file selection iteration info has been initialized */
- H5T_bkg_t need_bkg; /*type of background buf*/
- uint8_t *tconv_buf = NULL; /*datatype conv buffer */
- uint8_t *bkg_buf = NULL; /*background buffer */
- hsize_t smine_start; /*strip mine start loc */
- size_t n, smine_nelmts; /*elements per strip */
- H5D_storage_t store; /*union of storage info for dataset */
-
- herr_t ret_value = SUCCEED; /*return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_contig_write)
-
- assert (buf);
-
- /* Initialize storage info for this dataset */
- if(dataset->shared->dcpl_cache.efl.nused > 0)
- HDmemcpy(&store.efl, &(dataset->shared->dcpl_cache.efl), sizeof(H5O_efl_t));
else {
- store.contig.dset_addr = dataset->shared->layout.u.contig.addr;
- store.contig.dset_size = dataset->shared->layout.u.contig.size;
- } /* end if */
-
- /* Set dataset storage for I/O info */
- io_info->store = &store;
-
- /*
- * If there is no type conversion then write directly from the
- * application's buffer. This saves at least one mem-to-mem copy.
- */
- if(H5Z_xform_noop(dxpl_cache->data_xform_prop) && H5T_path_noop(tpath)) {
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
- H5_CHECK_OVERFLOW(nelmts,hsize_t,size_t);
-#ifdef H5_HAVE_PARALLEL
- if(io_info->dxpl_cache->xfer_mode == H5FD_MPIO_COLLECTIVE) {
- if(H5D_contig_collective_io(io_info, file_space, mem_space, buf, TRUE) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "contiguous write failed in collective mode")
- }
- else
-#endif
- {
- if((io_info->ops.write)(io_info, (size_t)nelmts,
- H5T_get_size(dataset->shared->type), file_space, mem_space,
- (haddr_t)0, NULL, buf/*out*/) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "contiguous write failed ")
- }
-
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[0].write_timer), &timer);
- io_info->stats->stats[0].write_nbytes += nelmts * H5T_get_size(mem_type);
- io_info->stats->stats[0].write_ncalls++;
-#endif
-
- /* direct xfer accomplished successfully */
- HGOTO_DONE(SUCCEED)
- } /* end if */
-
- /*
- * This is the general case.
- */
- if(nelmts==0)
- HGOTO_DONE(SUCCEED)
-
- /* Compute element sizes and other parameters */
- src_type_size = H5T_get_size(mem_type);
- dst_type_size = H5T_get_size(dataset->shared->type);
- max_type_size = MAX(src_type_size, dst_type_size);
- target_size = dxpl_cache->max_temp_buf;
- /* XXX: This could cause a problem if the user sets their buffer size
- * to the same size as the default, and then the dataset elements are
- * too large for the buffer... - QAK
- */
- if(target_size == H5D_TEMP_BUF_SIZE) {
- /* If the buffer is too small to hold even one element, make it bigger */
- if(target_size<max_type_size)
- target_size = max_type_size;
- /* If the buffer is too large to hold all the elements, make it smaller */
- else if(target_size>(nelmts*max_type_size))
- target_size=(size_t)(nelmts*max_type_size);
- } /* end if */
- request_nelmts = target_size / max_type_size;
-
- /* Sanity check elements in temporary buffer */
- if (request_nelmts==0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "temporary buffer max size is too small")
-
- /* Figure out the strip mine size. */
- if (H5S_select_iter_init(&file_iter, file_space, dst_type_size) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize file selection information")
- file_iter_init=1; /*file selection iteration info has been initialized */
- if (H5S_select_iter_init(&mem_iter, mem_space, src_type_size) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize memory selection information")
- mem_iter_init=1; /*file selection iteration info has been initialized */
- if (H5S_select_iter_init(&bkg_iter, file_space, dst_type_size) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize background selection information")
- bkg_iter_init=1; /*file selection iteration info has been initialized */
-
- /*
- * Get a temporary buffer for type conversion unless the app has already
- * supplied one through the xfer properties. Instead of allocating a
- * buffer which is the exact size, we allocate the target size. The
- * malloc() is usually less resource-intensive if we allocate/free the
- * same size over and over.
- */
- if(H5T_detect_class(dataset->shared->type, H5T_VLEN)) {
- /* Old data is retrieved into background buffer for VL datatype. The
- * data is used later for freeing heap objects. */
- need_bkg = H5T_BKG_YES;
- } else if (H5T_path_bkg(tpath)) {
- H5T_bkg_t path_bkg; /* Type conversion's background info */
-
- /* Retrieve the bkgr buffer property */
- need_bkg=dxpl_cache->bkgr_buf_type;
- path_bkg = H5T_path_bkg(tpath);
- need_bkg = MAX (path_bkg, need_bkg);
- } else {
- need_bkg = H5T_BKG_NO; /*never needed even if app says yes*/
- } /* end else */
- if (NULL==(tconv_buf=dxpl_cache->tconv_buf)) {
- /* Allocate temporary buffer */
- if((tconv_buf=H5FL_BLK_MALLOC(type_conv,target_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion")
- } /* end if */
- if (need_bkg && NULL==(bkg_buf=dxpl_cache->bkgr_buf)) {
- /* Allocate background buffer */
- /* (Don't need calloc()-like call since file data is already initialized) */
- if((bkg_buf=H5FL_BLK_MALLOC(type_conv,(request_nelmts*dst_type_size)))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for background conversion")
- } /* end if */
-
- /* Start strip mining... */
- for (smine_start=0; smine_start<nelmts; smine_start+=smine_nelmts) {
- /* Go figure out how many elements to read from the file */
- assert(H5S_SELECT_ITER_NELMTS(&file_iter)==(nelmts-smine_start));
- smine_nelmts = (size_t)MIN(request_nelmts, (nelmts-smine_start));
-
- /*
- * Gather data from application buffer into the datatype conversion
- * buffer. Also gather data from the file into the background buffer
- * if necessary.
- */
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
- n = H5D_select_mgath(buf, mem_space, &mem_iter,
- smine_nelmts, dxpl_cache, tconv_buf/*out*/);
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[0].gath_timer), &timer);
- io_info->stats->stats[0].gath_nbytes += n * src_type_size;
- io_info->stats->stats[0].gath_ncalls++;
-#endif
- if (n!=smine_nelmts)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "mem gather failed")
-
- /* If the source and destination are compound types and the destination is
- * is a subset of the source and no conversion is needed, copy the data
- * directly into user's buffer and bypass the rest of steps. If the source
- * is a subset of the destination, the optimization is done in conversion
- * function H5T_conv_struct_opt to protect the background data. This
- * optimization is for Chicago company */
- if(H5T_SUBSET_DST==H5T_path_compound_subset(tpath)) {
- if(H5D_compound_opt_write(smine_nelmts, src_id, dst_id, tconv_buf)<0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
- } else {
- if (H5T_BKG_YES==need_bkg) {
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
- n = H5D_select_fgath(io_info, file_space, &bkg_iter, smine_nelmts,
- (haddr_t)0, NULL, bkg_buf/*out*/);
-
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[0].bkg_timer), &timer);
- io_info->stats->stats[0].bkg_nbytes += n * dst_type_size;
- io_info->stats->stats[0].bkg_ncalls++;
-#endif
- if (n!=smine_nelmts)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file gather failed")
- } /* end if */
-
- /*
- * Perform datatype conversion.
- */
- if(H5T_convert(tpath, src_id, dst_id, smine_nelmts, (size_t)0, (size_t)0, tconv_buf, bkg_buf, io_info->dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
-
- /* Do the data transform after the type conversion (since we're using dataset->shared->type). */
- if(!H5Z_xform_noop(dxpl_cache->data_xform_prop))
- if( H5Z_xform_eval(dxpl_cache->data_xform_prop, tconv_buf, smine_nelmts, dataset->shared->type) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Error performing data transform")
- }
-
/*
- * Scatter the data out to the file.
+ * This is the general case (type conversion, usually).
*/
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
- status = H5D_select_fscat(io_info, file_space, &file_iter, smine_nelmts,
- (haddr_t)0, NULL, tconv_buf);
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[0].scat_timer), &timer);
- io_info->stats->stats[0].scat_nbytes += smine_nelmts * dst_type_size;
- io_info->stats->stats[0].scat_ncalls++;
-#endif
- if (status<0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "scatter failed")
- } /* end for */
-
-done:
- /* Release selection iterators */
- if(file_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&file_iter) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- } /* end if */
- if(mem_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&mem_iter) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- } /* end if */
- if(bkg_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&bkg_iter) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- } /* end if */
-
- if (tconv_buf && NULL==dxpl_cache->tconv_buf)
- H5FL_BLK_FREE(type_conv,tconv_buf);
- if (bkg_buf && NULL==dxpl_cache->bkgr_buf)
- H5FL_BLK_FREE(type_conv,bkg_buf);
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_contig_write() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_chunk_read
- *
- * Purpose: Read from a chunked dataset.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Raymond Lu
- * Thursday, April 10, 2003
- *
- * Modification:
- * Raymond Lu
- * 20 July 2007
- * Moved H5D_istore_lock and H5D_istore_unlock to this level
- * from H5D_istore_readvv to avoid frequent lock and unlock
- * and to improve performance.
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D_chunk_read(H5D_io_info_t *io_info, hsize_t nelmts,
- const H5T_t *mem_type, const H5S_t *mem_space,
- const H5S_t *file_space, H5T_path_t *tpath,
- hid_t src_id, hid_t dst_id, void *buf/*out*/)
-{
- H5D_t *dataset=io_info->dset; /* Local pointer to dataset info */
- const H5D_dxpl_cache_t *dxpl_cache=io_info->dxpl_cache; /* Local pointer to dataset transfer info */
- fm_map fm; /* File<->memory mapping */
- H5SL_node_t *chunk_node; /* Current node in chunk skip list */
- herr_t status; /*function return status*/
-#ifdef H5S_DEBUG
- H5_timer_t timer;
-#endif
- size_t src_type_size; /*size of source type */
- size_t dst_type_size; /*size of destination type*/
- size_t max_type_size; /* Size of largest source/destination type */
- size_t target_size; /*desired buffer size */
- size_t request_nelmts; /*requested strip mine */
- hsize_t smine_start; /*strip mine start loc */
- size_t n, smine_nelmts; /*elements per strip */
- size_t accessed_bytes = 0; /*total accessed size in a chunk */
- H5S_sel_iter_t mem_iter; /*memory selection iteration info*/
- hbool_t mem_iter_init = FALSE; /*memory selection iteration info has been initialized */
- H5S_sel_iter_t bkg_iter; /*background iteration info*/
- hbool_t bkg_iter_init = FALSE; /*background iteration info has been initialized */
- H5S_sel_iter_t file_iter; /*file selection iteration info*/
- hbool_t file_iter_init = FALSE; /*file selection iteration info has been initialized */
- H5T_bkg_t need_bkg; /*type of background buf*/
- uint8_t *tconv_buf = NULL; /*datatype conv buffer */
- uint8_t *bkg_buf = NULL; /*background buffer */
- H5D_storage_t store; /*union of EFL and chunk pointer in file space */
- void *chunk = NULL;
- haddr_t chunk_addr; /* Chunk address on disk */
- H5D_istore_ud1_t udata; /*B-tree pass-through */
- unsigned idx_hint=0; /* Cache index hint */
- herr_t ret_value = SUCCEED; /*return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_read)
-
- assert (buf);
-
- /* Map elements between file and memory for each chunk*/
- if(H5D_create_chunk_map(dataset, mem_type, file_space, mem_space, &fm) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't build chunk mapping")
-
- /* Set dataset storage for I/O info */
- io_info->store=&store;
-
- /*
- * If there is no type conversion then read directly into the
- * application's buffer. This saves at least one mem-to-mem copy.
- */
- if ( H5Z_xform_noop(dxpl_cache->data_xform_prop) && H5T_path_noop(tpath)) {
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
- /* Sanity check dataset, then read it */
- HDassert(((dataset->shared->layout.type == H5D_CONTIGUOUS && H5F_addr_defined(dataset->shared->layout.u.contig.addr))
- || (dataset->shared->layout.type == H5D_CHUNKED && H5F_addr_defined(dataset->shared->layout.u.chunk.addr)))
- || dataset->shared->dcpl_cache.efl.nused > 0 || 0 == nelmts
- || dataset->shared->layout.type == H5D_COMPACT);
-
-#ifdef H5_HAVE_PARALLEL
- /* Check whether the collective mode can be turned off globally*/
-#ifndef H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS
- if(io_info->dxpl_cache->xfer_mode == H5FD_MPIO_COLLECTIVE) {
- if(H5D_mpio_chunk_adjust_iomode(io_info ,&fm))
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't adjust collective I/O")
- }
-#endif /* H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS */
- /* Temporarily shut down collective IO for chunking */
- if(io_info->dxpl_cache->xfer_mode == H5FD_MPIO_COLLECTIVE) {
- if(H5D_chunk_collective_io(io_info, &fm, buf, FALSE) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "chunked read failed in collective mode")
- }
- else {/* sequential or independent read */
-#endif
- /* Get first node in chunk skip list */
- chunk_node = H5SL_first(fm.fsel);
-
- while(chunk_node) {
- H5D_chunk_info_t *chunk_info; /* chunk information */
-
- /* Get the actual chunk information from the skip list node */
- chunk_info = H5SL_item(chunk_node);
-
- /* Pass in chunk's coordinates in a union. */
- store.chunk.offset = chunk_info->coords;
- store.chunk.index = chunk_info->index;
-
- /* Load the chunk into cache and lock it. */
- chunk_addr = H5D_istore_get_addr(io_info, &udata);
-
- if (H5D_istore_if_load(dataset, chunk_addr)) {
- if(NULL == (chunk = H5D_istore_lock(io_info, &udata, FALSE, &idx_hint)))
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk")
- } else
- chunk = NULL;
-
- /* Perform the actual read operation */
- if((io_info->ops.read)(io_info, chunk_info->chunk_points,
- H5T_get_size(dataset->shared->type), chunk_info->fspace,
- chunk_info->mspace, chunk_addr, chunk, buf) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, " chunked read failed")
-
- /* Release the cache lock on the chunk. */
- if (H5D_istore_if_load(dataset, chunk_addr)) {
- accessed_bytes = chunk_info->chunk_points * H5T_get_size(dataset->shared->type);
- if(H5D_istore_unlock(io_info, FALSE, idx_hint, chunk, accessed_bytes) < 0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk")
- }
-
- /* Advance to next chunk in list */
- chunk_node = H5SL_next(chunk_node);
- } /* end while */
-#ifdef H5_HAVE_PARALLEL
- }
-#endif
-
-
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[1].read_timer), &timer);
- io_info->stats->stats[1].read_nbytes += nelmts * H5T_get_size(dataset->shared->type);
- io_info->stats->stats[1].read_ncalls++;
-#endif
-
- /* direct xfer accomplished successfully */
- HGOTO_DONE(SUCCEED)
- } /* end if */
-
- /*
- * This is the general case (type conversion, usually).
- */
- if(nelmts==0)
- HGOTO_DONE(SUCCEED)
-
- /* Compute element sizes and other parameters */
- src_type_size = H5T_get_size(dataset->shared->type);
- dst_type_size = H5T_get_size(mem_type);
- max_type_size = MAX(src_type_size, dst_type_size);
- target_size = dxpl_cache->max_temp_buf;
- /* XXX: This could cause a problem if the user sets their buffer size
- * to the same size as the default, and then the dataset elements are
- * too large for the buffer... - QAK
- */
- if(target_size == H5D_TEMP_BUF_SIZE) {
- /* If the buffer is too small to hold even one element, make it bigger */
- if(target_size<max_type_size)
- target_size = max_type_size;
- /* If the buffer is too large to hold all the elements, make it smaller */
- else if(target_size>(nelmts*max_type_size))
- target_size=(size_t)(nelmts*max_type_size);
- } /* end if */
- request_nelmts = target_size / max_type_size;
-
- /* Sanity check elements in temporary buffer */
- if (request_nelmts==0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "temporary buffer max size is too small")
-
- /*
- * Get a temporary buffer for type conversion unless the app has already
- * supplied one through the xfer properties. Instead of allocating a
- * buffer which is the exact size, we allocate the target size. The
- * malloc() is usually less resource-intensive if we allocate/free the
- * same size over and over.
- */
- if (H5T_path_bkg(tpath)) {
- H5T_bkg_t path_bkg; /* Type conversion's background info */
-
- /* Retrieve the bkgr buffer property */
- need_bkg=dxpl_cache->bkgr_buf_type;
- path_bkg = H5T_path_bkg(tpath);
- need_bkg = MAX(path_bkg, need_bkg);
- } else {
- need_bkg = H5T_BKG_NO; /*never needed even if app says yes*/
+ io_info->io_ops.single_read = H5D_scatgath_read;
+ io_info->io_ops.single_write = H5D_scatgath_write;
} /* end else */
- if (NULL==(tconv_buf=dxpl_cache->tconv_buf)) {
- /* Allocate temporary buffer */
- if((tconv_buf=H5FL_BLK_MALLOC(type_conv,target_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion")
- } /* end if */
- if (need_bkg && NULL==(bkg_buf=dxpl_cache->bkgr_buf)) {
- /* Allocate background buffer */
- /* (Need calloc()-like call since memory needs to be initialized) */
- if((bkg_buf=H5FL_BLK_CALLOC(type_conv,(request_nelmts*dst_type_size)))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for background conversion")
- } /* end if */
-
- /* Loop over all the chunks, performing I/O on each */
-
- /* Get first node in chunk skip list */
- chunk_node=H5SL_first(fm.fsel);
-
- /* Iterate through chunks to be operated on */
- while(chunk_node) {
- H5D_chunk_info_t *chunk_info; /* chunk information */
-
- /* Get the actual chunk information from the skip list nodes */
- chunk_info=H5SL_item(chunk_node);
-
- /* initialize selection iterator */
- if (H5S_select_iter_init(&file_iter, chunk_info->fspace, src_type_size) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize file selection information")
- file_iter_init = TRUE; /*file selection iteration info has been initialized */
- if (H5S_select_iter_init(&mem_iter, chunk_info->mspace, dst_type_size) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize memory selection information")
- mem_iter_init = TRUE; /*file selection iteration info has been initialized */
- if (H5S_select_iter_init(&bkg_iter, chunk_info->mspace, dst_type_size) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize background selection information")
- bkg_iter_init = TRUE; /*file selection iteration info has been initialized */
-
- /* Pass in chunk's coordinates in a union*/
- store.chunk.offset = chunk_info->coords;
- store.chunk.index = chunk_info->index;
-
- /* Load the chunk into cache and lock it. */
- chunk_addr = H5D_istore_get_addr(io_info, &udata);
-
- if (H5D_istore_if_load(dataset, chunk_addr)) {
- if(NULL == (chunk = H5D_istore_lock(io_info, &udata, FALSE, &idx_hint)))
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk")
- } else
- chunk = NULL;
-
- for (smine_start=0; smine_start<chunk_info->chunk_points; smine_start+=smine_nelmts) {
- /* Go figure out how many elements to read from the file */
- assert(H5S_SELECT_ITER_NELMTS(&file_iter)==(chunk_info->chunk_points-smine_start));
- smine_nelmts = (size_t)MIN(request_nelmts, (chunk_info->chunk_points-smine_start));
-
- /*
- * Gather the data from disk into the datatype conversion
- * buffer. Also gather data from application to background buffer
- * if necessary.
- */
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
- /* Sanity check that space is allocated, then read data from it */
- HDassert(((dataset->shared->layout.type == H5D_CONTIGUOUS && H5F_addr_defined(dataset->shared->layout.u.contig.addr))
- || (dataset->shared->layout.type == H5D_CHUNKED && H5F_addr_defined(dataset->shared->layout.u.chunk.addr)))
- || dataset->shared->dcpl_cache.efl.nused > 0 || dataset->shared->layout.type == H5D_COMPACT);
-
- if(chunk) {
- n = H5D_select_mgath(chunk, chunk_info->fspace, &file_iter,
- smine_nelmts, dxpl_cache, tconv_buf/*out*/);
- } else {
- n = H5D_select_fgath(io_info, chunk_info->fspace, &file_iter, smine_nelmts,
- chunk_addr, NULL, tconv_buf/*out*/);
- }
-
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[1].gath_timer), &timer);
- io_info->stats->stats[1].gath_nbytes += n * src_type_size;
- io_info->stats->stats[1].gath_ncalls++;
-#endif
- if(n != smine_nelmts)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file gather failed")
-
- /* If the source and destination are compound types and subset of each other
- * and no conversion is needed, copy the data directly into user's buffer and
- * bypass the rest of steps. This optimization is for Chicago company */
- if(H5T_SUBSET_SRC==H5T_path_compound_subset(tpath)) {
- if(H5D_compound_opt_read(smine_nelmts, chunk_info->mspace, &mem_iter, dxpl_cache,
- src_id, dst_id, H5T_SUBSET_SRC, tconv_buf, buf /*out*/)<0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
-
- continue;
- } else if(H5T_SUBSET_DST==H5T_path_compound_subset(tpath)) {
- if(H5D_compound_opt_read(smine_nelmts, chunk_info->mspace, &mem_iter, dxpl_cache,
- src_id, dst_id, H5T_SUBSET_DST, tconv_buf, buf /*out*/)<0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
-
- continue;
- }
-
- if(H5T_BKG_YES == need_bkg) {
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
- n = H5D_select_mgath(buf, chunk_info->mspace, &bkg_iter, smine_nelmts, dxpl_cache, bkg_buf/*out*/);
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[1].bkg_timer), &timer);
- io_info->stats->stats[1].bkg_nbytes += n * dst_type_size;
- io_info->stats->stats[1].bkg_ncalls++;
-#endif
- if(n != smine_nelmts)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "mem gather failed")
- } /* end if */
-
- /*
- * Perform datatype conversion.
- */
- if(H5T_convert(tpath, src_id, dst_id, smine_nelmts, (size_t)0, (size_t)0, tconv_buf, bkg_buf, io_info->dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
-
- /* Do the data transform after the conversion (since we're using type mem_type) */
- if(!H5Z_xform_noop(dxpl_cache->data_xform_prop))
- if(H5Z_xform_eval(dxpl_cache->data_xform_prop, tconv_buf, smine_nelmts, mem_type) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Error performing data transform")
-
- /*
- * Scatter the data into memory.
- */
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
- status = H5D_select_mscat(tconv_buf, chunk_info->mspace, &mem_iter, smine_nelmts, dxpl_cache, buf/*out*/);
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[1].scat_timer), &timer);
- io_info->stats->stats[1].scat_nbytes += smine_nelmts * dst_type_size;
- io_info->stats->stats[1].scat_ncalls++;
-#endif
- if(status < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "scatter failed")
- } /* end for */
-
- /* Release the cache lock on the chunk. */
- if (H5D_istore_if_load(dataset, chunk_addr)) {
- accessed_bytes = chunk_info->chunk_points * H5T_get_size(dataset->shared->type);
- if(H5D_istore_unlock(io_info, FALSE, idx_hint, chunk, accessed_bytes) < 0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk")
- }
-
- /* Release selection iterators */
- if(file_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&file_iter) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- file_iter_init = FALSE;
- } /* end if */
- if(mem_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&mem_iter) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- mem_iter_init = FALSE;
- } /* end if */
- if(bkg_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&bkg_iter) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- bkg_iter_init = FALSE;
- } /* end if */
-
- /* Get the next chunk node in the skip list */
- chunk_node=H5SL_next(chunk_node);
- } /* end while */
-
-done:
- /* Release selection iterators, if necessary */
- if(file_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&file_iter) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- } /* end if */
- if(mem_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&mem_iter) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- } /* end if */
- if(bkg_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&bkg_iter) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- } /* end if */
-
- if(tconv_buf && NULL == dxpl_cache->tconv_buf)
- H5FL_BLK_FREE(type_conv, tconv_buf);
- if(bkg_buf && NULL == dxpl_cache->bkgr_buf)
- H5FL_BLK_FREE(type_conv, bkg_buf);
-
- /* Release chunk mapping information */
- if(H5D_destroy_chunk_map(&fm) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "can't release chunk mapping")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5D_chunk_read() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_chunk_write
- *
- * Purpose: Writes to a chunked dataset.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Raymond Lu
- * Thursday, April 10, 2003
- *
- * Modification:
- * Raymond Lu
- * 20 July 2007
- * Moved H5D_istore_lock and H5D_istore_unlock to this level
- * from H5D_istore_writevv to avoid frequent lock and unlock
- * and to improve performance.
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D_chunk_write(H5D_io_info_t *io_info, hsize_t nelmts,
- const H5T_t *mem_type, const H5S_t *mem_space,
- const H5S_t *file_space, H5T_path_t *tpath,
- hid_t src_id, hid_t dst_id, const void *buf)
-{
- H5D_t *dataset=io_info->dset; /* Local pointer to dataset info */
- const H5D_dxpl_cache_t *dxpl_cache=io_info->dxpl_cache; /* Local pointer to dataset transfer info */
- fm_map fm; /* File<->memory mapping */
- H5SL_node_t *chunk_node; /* Current node in chunk skip list */
- herr_t status; /*function return status*/
-#ifdef H5S_DEBUG
- H5_timer_t timer;
-#endif
- size_t src_type_size; /*size of source type */
- size_t dst_type_size; /*size of destination type*/
- size_t max_type_size; /* Size of largest source/destination type */
- size_t target_size; /*desired buffer size */
- size_t request_nelmts; /*requested strip mine */
- size_t accessed_bytes; /*total accessed size in a chunk */
- hsize_t smine_start; /*strip mine start loc */
- size_t n, smine_nelmts; /*elements per strip */
- H5S_sel_iter_t mem_iter; /*memory selection iteration info*/
- hbool_t mem_iter_init=0; /*memory selection iteration info has been initialized */
- H5S_sel_iter_t bkg_iter; /*background iteration info*/
- hbool_t bkg_iter_init=0; /*background iteration info has been initialized */
- H5S_sel_iter_t file_iter; /*file selection iteration info*/
- hbool_t file_iter_init=0; /*file selection iteration info has been initialized */
- H5T_bkg_t need_bkg; /*type of background buf*/
- uint8_t *tconv_buf = NULL; /*datatype conv buffer */
- uint8_t *bkg_buf = NULL; /*background buffer */
- H5D_storage_t store; /*union of EFL and chunk pointer in file space */
- void *chunk = NULL;
- haddr_t chunk_addr; /* Chunk address on disk */
- H5D_istore_ud1_t udata; /*B-tree pass-through */
- unsigned idx_hint=0; /* Cache index hint */
- hbool_t relax=TRUE; /* Whether whole chunk is selected */
- herr_t ret_value = SUCCEED; /*return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_write)
-
- assert (buf);
-
- /* Map elements between file and memory for each chunk*/
- if(H5D_create_chunk_map(dataset, mem_type, file_space, mem_space, &fm) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't build chunk mapping")
-
- /* Set dataset storage for I/O info */
- io_info->store=&store;
-
-#ifdef H5_HAVE_PARALLEL
- /* Additional sanity checks when operating in parallel */
- if(IS_H5FD_MPI(dataset->oloc.file)) {
- if (chunk_addr==HADDR_UNDEF)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to locate raw data chunk")
- if (dataset->shared->dcpl_cache.pline.nused>0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "cannot write to chunked storage with filters in parallel")
- } /* end if */
-#endif /* H5_HAVE_PARALLEL */
-
- /*
- * If there is no type conversion then write directly from the
- * application's buffer. This saves at least one mem-to-mem copy.
- */
- if ( H5Z_xform_noop(dxpl_cache->data_xform_prop) && H5T_path_noop(tpath)) {
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
#ifdef H5_HAVE_PARALLEL
- /* Check whether the collective mode can be turned off globally*/
-#ifndef H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS
- if(io_info->dxpl_cache->xfer_mode == H5FD_MPIO_COLLECTIVE) {
- if(H5D_mpio_chunk_adjust_iomode(io_info,&fm))
- HGOTO_ERROR(H5E_DATASET,H5E_CANTGET,FAIL,"can't adjust collective I/O")
- }
-#endif /* H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS */
- /* Temporarily shut down collective IO for chunking */
- if(io_info->dxpl_cache->xfer_mode == H5FD_MPIO_COLLECTIVE) {
- if(H5D_chunk_collective_io(io_info,&fm,buf,TRUE) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "chunked write failed in collective mode");
- }
- else {/* sequential or independent write */
+ /* Determine if the file was opened with an MPI VFD */
+ io_info->using_mpi_vfd = IS_H5FD_MPI(dset->oloc.file);
#endif /* H5_HAVE_PARALLEL */
- /* Get first node in chunk skip list */
- chunk_node=H5SL_first(fm.fsel);
-
- while(chunk_node) {
- H5D_chunk_info_t *chunk_info; /* Chunk information */
-
- /* Get the actual chunk information from the skip list node */
- chunk_info=H5SL_item(chunk_node);
-
- /* Pass in chunk's coordinates in a union. */
- store.chunk.offset = chunk_info->coords;
- store.chunk.index = chunk_info->index;
-
- /* Load the chunk into cache. But if the whole chunk is written,
- * simply allocate space instead of load the chunk. */
- chunk_addr = H5D_istore_get_addr(io_info, &udata);
-
- if (H5D_istore_if_load(dataset, chunk_addr)) {
- accessed_bytes = chunk_info->chunk_points * H5T_get_size(dataset->shared->type);
- if(accessed_bytes != dataset->shared->layout.u.chunk.size)
- relax=FALSE;
-
- if(NULL == (chunk = H5D_istore_lock(io_info, &udata, relax, &idx_hint)))
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk")
- } else
- chunk = NULL;
-
- /* Perform the actual read operation */
- if((io_info->ops.write)(io_info, chunk_info->chunk_points,
- H5T_get_size(dataset->shared->type), chunk_info->fspace,
- chunk_info->mspace, chunk_addr, chunk, buf) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, " chunked write failed")
-
- /* Release the cache lock on the chunk. */
- if (H5D_istore_if_load(dataset, chunk_addr)) {
- if(H5D_istore_unlock(io_info, TRUE, idx_hint, chunk, accessed_bytes) < 0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk")
- }
- relax=TRUE;
-
- /* Advance to next chunk in list */
- chunk_node = H5SL_next(chunk_node);
- } /* end while */
-#ifdef H5_HAVE_PARALLEL
- }
-#endif
-
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[0].write_timer), &timer);
- io_info->stats->stats[0].write_nbytes += nelmts * H5T_get_size(mem_type);
- io_info->stats->stats[0].write_ncalls++;
-#endif
-
- /* direct xfer accomplished successfully */
- HGOTO_DONE(SUCCEED)
- } /* end if */
-
- /*
- * This is the general case (type conversion, usually).
- */
- if(nelmts==0)
- HGOTO_DONE(SUCCEED)
-
- /* Compute element sizes and other parameters */
- src_type_size = H5T_get_size(mem_type);
- dst_type_size = H5T_get_size(dataset->shared->type);
- max_type_size = MAX(src_type_size, dst_type_size);
- target_size = dxpl_cache->max_temp_buf;
- /* XXX: This could cause a problem if the user sets their buffer size
- * to the same size as the default, and then the dataset elements are
- * too large for the buffer... - QAK
- */
- if(target_size == H5D_TEMP_BUF_SIZE) {
- /* If the buffer is too small to hold even one element, make it bigger */
- if(target_size<max_type_size)
- target_size = max_type_size;
- /* If the buffer is too large to hold all the elements, make it smaller */
- else if(target_size>(nelmts*max_type_size))
- target_size=(size_t)(nelmts*max_type_size);
- } /* end if */
- request_nelmts = target_size / max_type_size;
-
- /* Sanity check elements in temporary buffer */
- if (request_nelmts==0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "temporary buffer max size is too small")
-
- /*
- * Get a temporary buffer for type conversion unless the app has already
- * supplied one through the xfer properties. Instead of allocating a
- * buffer which is the exact size, we allocate the target size. The
- * malloc() is usually less resource-intensive if we allocate/free the
- * same size over and over.
- */
- if(H5T_detect_class(dataset->shared->type, H5T_VLEN)) {
- /* Old data is retrieved into background buffer for VL datatype. The
- * data is used later for freeing heap objects. */
- need_bkg = H5T_BKG_YES;
- } else if (H5T_path_bkg(tpath)) {
- H5T_bkg_t path_bkg; /* Type conversion's background info */
-
- /* Retrieve the bkgr buffer property */
- need_bkg=dxpl_cache->bkgr_buf_type;
- path_bkg = H5T_path_bkg(tpath);
- need_bkg = MAX (path_bkg, need_bkg);
- } else {
- need_bkg = H5T_BKG_NO; /*never needed even if app says yes*/
- } /* end else */
- if (NULL==(tconv_buf=dxpl_cache->tconv_buf)) {
- /* Allocate temporary buffer */
- if((tconv_buf=H5FL_BLK_MALLOC(type_conv,target_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion")
- } /* end if */
- if (need_bkg && NULL==(bkg_buf=dxpl_cache->bkgr_buf)) {
- /* Allocate background buffer */
- /* (Don't need calloc()-like call since file data is already initialized) */
- if((bkg_buf=H5FL_BLK_MALLOC(type_conv,(request_nelmts*dst_type_size)))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for background conversion")
- } /* end if */
-
- /* Loop over all the chunks, performing I/O on each */
-
- /* Get first node in chunk skip list */
- chunk_node=H5SL_first(fm.fsel);
-
- /* Iterate through chunks to be operated on */
- while(chunk_node) {
- H5D_chunk_info_t *chunk_info; /* chunk information */
-
- /* Get the actual chunk information from the skip list node */
- chunk_info=H5SL_item(chunk_node);
-
- /* initialize selection iterator */
- if (H5S_select_iter_init(&file_iter, chunk_info->fspace, dst_type_size) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize file selection information")
- file_iter_init=1; /*file selection iteration info has been initialized */
- if (H5S_select_iter_init(&mem_iter, chunk_info->mspace, src_type_size) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize memory selection information")
- mem_iter_init=1; /*file selection iteration info has been initialized */
- if (H5S_select_iter_init(&bkg_iter, chunk_info->fspace, dst_type_size) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize background selection information")
- bkg_iter_init=1; /*file selection iteration info has been initialized */
-
- /*pass in chunk's coordinates in a union*/
- store.chunk.offset = chunk_info->coords;
- store.chunk.index = chunk_info->index;
-
- /* Load the chunk into cache. But if the whole chunk is written,
- * simply allocate space instead of load the chunk. */
- chunk_addr = H5D_istore_get_addr(io_info, &udata);
-
- if (H5D_istore_if_load(dataset, chunk_addr)) {
- accessed_bytes = chunk_info->chunk_points * H5T_get_size(dataset->shared->type);
- if(accessed_bytes != dataset->shared->layout.u.chunk.size)
- relax=FALSE;
- if(relax) {
- accessed_bytes = H5S_GET_SELECT_NPOINTS(chunk_info->mspace)*H5T_get_size(mem_type);
- if(accessed_bytes != dataset->shared->layout.u.chunk.size)
- relax = FALSE;
- }
-
- if(NULL == (chunk = H5D_istore_lock(io_info, &udata, relax, &idx_hint)))
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk")
- } else
- chunk = NULL;
-
- for (smine_start=0; smine_start<chunk_info->chunk_points; smine_start+=smine_nelmts) {
- /* Go figure out how many elements to read from the file */
- assert(H5S_SELECT_ITER_NELMTS(&file_iter)==(chunk_info->chunk_points-smine_start));
- smine_nelmts = (size_t)MIN(request_nelmts, (chunk_info->chunk_points-smine_start));
-
- /*
- * Gather the data from disk into the datatype conversion
- * buffer. Also gather data from application to background buffer
- * if necessary.
- */
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
- n = H5D_select_mgath(buf, chunk_info->mspace, &mem_iter,
- smine_nelmts, dxpl_cache, tconv_buf/*out*/);
-
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[1].gath_timer), &timer);
- io_info->stats->stats[1].gath_nbytes += n * src_type_size;
- io_info->stats->stats[1].gath_ncalls++;
-#endif
- if (n!=smine_nelmts)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file gather failed")
-
- /* If the source and destination are compound types and the destination is
- * is a subset of the source and no conversion is needed, copy the data
- * directly into user's buffer and bypass the rest of steps. If the source
- * is a subset of the destination, the optimization is done in conversion
- * function H5T_conv_struct_opt to protect the background data. This
- * optimization is for Chicago company */
- if(H5T_SUBSET_DST==H5T_path_compound_subset(tpath)) {
- if(H5D_compound_opt_write(smine_nelmts, src_id, dst_id, tconv_buf)<0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
- } else {
- if (H5T_BKG_YES==need_bkg) {
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
- if(chunk) {
- n = H5D_select_mgath(chunk, chunk_info->fspace, &bkg_iter,
- smine_nelmts, dxpl_cache, bkg_buf/*out*/);
- } else {
- n = H5D_select_fgath(io_info, chunk_info->fspace, &bkg_iter, smine_nelmts,
- chunk_addr, NULL, bkg_buf/*out*/);
- }
-
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[0].bkg_timer), &timer);
- io_info->stats->stats[0].bkg_nbytes += n * dst_type_size;
- io_info->stats->stats[0].bkg_ncalls++;
-#endif
- if (n!=smine_nelmts)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file gather failed")
- } /* end if */
-
- /*
- * Perform datatype conversion.
- */
- if(H5T_convert(tpath, src_id, dst_id, smine_nelmts, (size_t)0, (size_t)0, tconv_buf, bkg_buf, io_info->dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
-
- /* Do the data transform after the type conversion (since we're using dataset->shared->type) */
- if(!H5Z_xform_noop(dxpl_cache->data_xform_prop))
- if( H5Z_xform_eval(dxpl_cache->data_xform_prop, tconv_buf, smine_nelmts, dataset->shared->type) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Error performing data transform")
- }
-
- /*
- * Scatter the data out to the file.
- */
-#ifdef H5S_DEBUG
- H5_timer_begin(&timer);
-#endif
- status = H5D_select_fscat(io_info,
- chunk_info->fspace, &file_iter, smine_nelmts,
- chunk_addr, chunk, tconv_buf);
-
-#ifdef H5S_DEBUG
- H5_timer_end(&(io_info->stats->stats[0].scat_timer), &timer);
- io_info->stats->stats[0].scat_nbytes += n * dst_type_size;
- io_info->stats->stats[0].scat_ncalls++;
-#endif
- if (status<0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "scatter failed")
- } /* end for */
-
- /* Release the cache lock on the chunk. */
- if (H5D_istore_if_load(dataset, chunk_addr)) {
- accessed_bytes = chunk_info->chunk_points * H5T_get_size(dataset->shared->type);
- if(H5D_istore_unlock(io_info, TRUE, idx_hint, chunk, accessed_bytes) < 0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk")
- }
- relax=TRUE;
-
- /* Release selection iterators */
- if(file_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&file_iter) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- file_iter_init=0;
- } /* end if */
- if(mem_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&mem_iter) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- mem_iter_init=0;
- } /* end if */
- if(bkg_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&bkg_iter) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- bkg_iter_init=0;
- } /* end if */
-
- /* Get the next chunk node in the skip list */
- chunk_node=H5SL_next(chunk_node);
- } /* end while */
-
-done:
- /* Release selection iterators, if necessary */
- if(file_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&file_iter) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- } /* end if */
- if(mem_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&mem_iter) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- } /* end if */
- if(bkg_iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&bkg_iter) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
- } /* end if */
-
- if (tconv_buf && NULL==dxpl_cache->tconv_buf)
- H5FL_BLK_FREE(type_conv,tconv_buf);
- if (bkg_buf && NULL==dxpl_cache->bkgr_buf)
- H5FL_BLK_FREE(type_conv,bkg_buf);
-
- /* Release chunk mapping information */
- if(H5D_destroy_chunk_map(&fm) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "can't release chunk mapping")
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5D_chunk_write() */
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5D_ioinfo_init() */
/*-------------------------------------------------------------------------
- * Function: H5D_compound_opt_read
+ * Function: H5D_typeinfo_init
*
- * Purpose: A shortcut optimization for the Chicago company for
- * a special optimization case when the source and
- * destination members are a subset of each other, and
- * the order is the same, and no conversion is needed.
- * For example:
- * struct source { struct destination {
- * TYPE1 A; --> TYPE1 A;
- * TYPE2 B; --> TYPE2 B;
- * TYPE3 C; --> TYPE3 C;
- * }; TYPE4 D;
- * TYPE5 E;
- * };
- * or
- * struct destination { struct source {
- * TYPE1 A; <-- TYPE1 A;
- * TYPE2 B; <-- TYPE2 B;
- * TYPE3 C; <-- TYPE3 C;
- * }; TYPE4 D;
- * TYPE5 E;
- * };
- * The optimization is simply moving data to the appropriate
- * places in the buffer.
+ * Purpose: Routine for determining correct datatype information for
+ * each I/O action.
*
* Return: Non-negative on success/Negative on failure
*
- * Programmer: Raymond Lu
- * 11 June 2007
+ * Programmer: Quincey Koziol
+ * Tuesday, March 4, 2008
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5D_compound_opt_read(size_t nelmts, const H5S_t *space,
- H5S_sel_iter_t *iter, const H5D_dxpl_cache_t *dxpl_cache,
- hid_t src_id, hid_t dst_id, H5T_subset_t subset,
- void *data_buf, void *user_buf/*out*/)
+H5D_typeinfo_init(const H5D_t *dset, const H5D_dxpl_cache_t *dxpl_cache,
+ hid_t dxpl_id, hid_t mem_type_id, hbool_t do_write,
+ H5D_type_info_t *type_info)
{
- uint8_t *dbuf = (uint8_t *)data_buf; /*cast for pointer arithmetic */
- uint8_t *ubuf = (uint8_t *)user_buf; /*cast for pointer arithmetic */
- uint8_t *xdbuf;
- uint8_t *xubuf;
-
- hsize_t _off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets */
- hsize_t *off=NULL; /* Pointer to sequence offsets */
- size_t _len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths */
- size_t *len=NULL; /* Pointer to sequence lengths */
- size_t nseq; /* Number of sequences generated */
- size_t curr_off; /* offset of bytes left to process in sequence */
- size_t curr_seq; /* Current sequence being processed */
- size_t curr_len; /* Length of bytes left to process in sequence */
- size_t curr_nelmts; /* number of elements to process in sequence */
- size_t i;
-
- H5T_t *src, *dst;
- size_t src_stride, dst_stride, type_size = 0;
- size_t elmtno; /*element counter */
-
- herr_t ret_value = SUCCEED; /*return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_compound_opt_read)
-
- /* Check args */
- assert (data_buf);
- assert (user_buf);
- assert (space);
- assert (iter);
- assert (nelmts>0);
-
- /* Allocate the vector I/O arrays */
- if(dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
- if((len = H5FL_SEQ_MALLOC(size_t,dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array");
- if((off = H5FL_SEQ_MALLOC(hsize_t,dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array");
- } /* end if */
- else {
- len=_len;
- off=_off;
- } /* end else */
-
- if (NULL == (src = H5I_object(src_id)) || NULL == (dst = H5I_object(dst_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
-
- src_stride = H5T_get_size(src);
- dst_stride = H5T_get_size(dst);
-
- if(H5T_SUBSET_SRC == subset)
- type_size = src_stride;
- else if(H5T_SUBSET_DST == subset)
- type_size = dst_stride;
+ const H5T_t *src_type; /* Source datatype */
+ const H5T_t *dst_type; /* Destination datatype */
+ herr_t ret_value = SUCCEED; /* Return value */
- xdbuf = dbuf;
+ FUNC_ENTER_NOAPI_NOINIT(H5D_typeinfo_init)
- /* Loop until all elements are written */
- while(nelmts>0) {
- /* Get list of sequences for selection to write */
- if(H5S_SELECT_GET_SEQ_LIST(space,0,iter,dxpl_cache->vec_size,nelmts,&nseq,&elmtno,off,len)<0)
- HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, 0, "sequence length generation failed");
-
- /* Loop, while sequences left to process */
- for(curr_seq=0; curr_seq<nseq; curr_seq++) {
- /* Get the number of bytes and offset in sequence */
- curr_len=len[curr_seq];
- curr_off=off[curr_seq];
-
- /* Decide the number of elements and position in the buffer. */
- curr_nelmts = curr_len/dst_stride;
- xubuf = ubuf + curr_off;
-
- /* Copy the data into the right place. */
- for(i=0; i<curr_nelmts; i++) {
- HDmemmove(xubuf, xdbuf, type_size);
-
- /* Update pointers */
- xdbuf += src_stride;
- xubuf += dst_stride;
- }
+ /* check args */
+ HDassert(type_info);
+ HDassert(dset);
- } /* end for */
+ /* Initialize type info safely */
+ HDmemset(type_info, 0, sizeof(*type_info));
- /* Decrement number of elements left to process */
- nelmts -= elmtno;
- } /* end while */
+ /* Get the memory & dataset datatypes */
+ if(NULL == (type_info->mem_type = (const H5T_t *)H5I_object_verify(mem_type_id, H5I_DATATYPE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
+ type_info->dset_type = dset->shared->type;
-done:
- if(dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
- if(len!=NULL)
- H5FL_SEQ_FREE(size_t,len);
- if(off!=NULL)
- H5FL_SEQ_FREE(hsize_t,off);
+ if(do_write) {
+ src_type = type_info->mem_type;
+ dst_type = dset->shared->type;
+ type_info->src_type_id = mem_type_id;
+ type_info->dst_type_id = dset->shared->type_id;
} /* end if */
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_compound_opt_read() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_compound_opt_write
- *
- * Purpose: A shortcut optimization for the Chicago company for
- * a special optimization case when the source and
- * destination members are a subset of each other, and
- * the order is the same, and no conversion is needed.
- * For example:
- * struct source { struct destination {
- * TYPE1 A; --> TYPE1 A;
- * TYPE2 B; --> TYPE2 B;
- * TYPE3 C; --> TYPE3 C;
- * }; TYPE4 D;
- * TYPE5 E;
- * };
- * or
- * struct destination { struct source {
- * TYPE1 A; <-- TYPE1 A;
- * TYPE2 B; <-- TYPE2 B;
- * TYPE3 C; <-- TYPE3 C;
- * }; TYPE4 D;
- * TYPE5 E;
- * };
- * The optimization is simply moving data to the appropriate
- * places in the buffer.
- *
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Raymond Lu
- * 11 June 2007
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D_compound_opt_write(size_t nelmts, hid_t src_id, hid_t dst_id, void *data_buf)
-{
- uint8_t *dbuf = (uint8_t *)data_buf; /*cast for pointer arithmetic */
- uint8_t *xsbuf, *xdbuf;
- size_t i;
- H5T_t *src, *dst;
- size_t src_stride, dst_stride;
- herr_t ret_value = SUCCEED; /*return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_compound_opt_write)
-
- /* Check args */
- assert (data_buf);
- assert (nelmts>0);
-
- if (NULL == (src = H5I_object(src_id)) || NULL == (dst = H5I_object(dst_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
-
- src_stride = H5T_get_size(src);
- dst_stride = H5T_get_size(dst);
-
- xsbuf = dbuf;
- xdbuf = dbuf;
-
- /* Loop until all elements are written */
- for(i=0; i<nelmts; i++) {
- HDmemmove(xdbuf, xsbuf, dst_stride);
-
- /* Update pointers */
- xsbuf += src_stride;
- xdbuf += dst_stride;
- }
-
-done:
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_compound_opt_write() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_create_chunk_map
- *
- * Purpose: Creates the mapping between elements selected in each chunk
- * and the elements in the memory selection.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Raymond Lu
- * Thursday, April 10, 2003
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D_create_chunk_map(const H5D_t *dataset, const H5T_t *mem_type, const H5S_t *file_space,
- const H5S_t *mem_space, fm_map *fm)
-{
- H5S_t *tmp_mspace = NULL; /* Temporary memory dataspace */
- H5S_t *equiv_mspace = NULL; /* Equivalent memory dataspace */
- hbool_t equiv_mspace_init = FALSE;/* Equivalent memory dataspace was created */
- hssize_t old_offset[H5O_LAYOUT_NDIMS]; /* Old selection offset */
- hbool_t file_space_normalized = FALSE; /* File dataspace was normalized */
- hid_t f_tid = (-1); /* Temporary copy of file datatype for iteration */
- hbool_t iter_init = FALSE; /* Selection iteration info has been initialized */
- unsigned f_ndims; /* The number of dimensions of the file's dataspace */
- int sm_ndims; /* The number of dimensions of the memory buffer's dataspace (signed) */
- H5SL_node_t *curr_node; /* Current node in skip list */
- H5S_sel_type fsel_type; /* Selection type on disk */
- char bogus; /* "bogus" buffer to pass to selection iterator */
- unsigned u; /* Local index variable */
- hbool_t sel_hyper_flag;
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_create_chunk_map)
-
- /* Get layout for dataset */
- fm->layout = &(dataset->shared->layout);
-
-
- /* Check if the memory space is scalar & make equivalent memory space */
- if((sm_ndims = H5S_GET_EXTENT_NDIMS(mem_space)) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimension number")
- if(sm_ndims==0) {
- hsize_t dims[H5O_LAYOUT_NDIMS]; /* Temporary dimension information */
-
- /* Set up "equivalent" n-dimensional dataspace with size '1' in each dimension */
- for(u=0; u<dataset->shared->layout.u.chunk.ndims-1; u++)
- dims[u]=1;
- if((equiv_mspace = H5S_create_simple(dataset->shared->layout.u.chunk.ndims-1,dims,NULL))==NULL)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "unable to create equivalent dataspace for scalar space")
-
- /* Indicate that this space needs to be released */
- equiv_mspace_init = TRUE;
-
- /* Set the number of dimensions for the memory dataspace */
- fm->m_ndims = dataset->shared->layout.u.chunk.ndims - 1;
- } /* end else */
else {
- equiv_mspace = (H5S_t *)mem_space; /* Casting away 'const' OK... */
-
- /* Set the number of dimensions for the memory dataspace */
- H5_ASSIGN_OVERFLOW(fm->m_ndims, sm_ndims, int, unsigned);
+ src_type = dset->shared->type;
+ dst_type = type_info->mem_type;
+ type_info->src_type_id = dset->shared->type_id;
+ type_info->dst_type_id = mem_type_id;
} /* end else */
- /* Get dim number and dimensionality for each dataspace */
- fm->f_ndims = f_ndims = dataset->shared->layout.u.chunk.ndims - 1;
-
- if(H5S_get_simple_extent_dims(file_space, fm->f_dims, NULL) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality")
-
- /* Normalize hyperslab selections by adjusting them by the offset */
- /* (It might be worthwhile to normalize both the file and memory dataspaces
- * before any (contiguous, chunked, etc) file I/O operation, in order to
- * speed up hyperslab calculations by removing the extra checks and/or
- * additions involving the offset and the hyperslab selection -QAK)
+ /*
+ * Locate the type conversion function and data space conversion
+ * functions, and set up the element numbering information. If a data
+ * type conversion is necessary then register datatype atoms. Data type
+ * conversion is necessary if the user has set the `need_bkg' to a high
+ * enough value in xfer_parms since turning off datatype conversion also
+ * turns off background preservation.
*/
- if(H5S_hyper_normalize_offset((H5S_t *)file_space, old_offset) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "unable to normalize dataspace by offset")
- file_space_normalized = TRUE;
-
- /* Decide the number of chunks in each dimension*/
- for(u=0; u<f_ndims; u++) {
- /* Keep the size of the chunk dimensions as hsize_t for various routines */
- fm->chunk_dim[u]=fm->layout->u.chunk.dim[u];
-
- /* Round up to the next integer # of chunks, to accomodate partial chunks */
- fm->chunks[u] = ((fm->f_dims[u]+dataset->shared->layout.u.chunk.dim[u])-1) / dataset->shared->layout.u.chunk.dim[u];
- } /* end for */
-
- /* Compute the "down" size of 'chunks' information */
- if(H5V_array_down(f_ndims,fm->chunks,fm->down_chunks) < 0)
- HGOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "can't compute 'down' sizes")
-
- /* calculate total chunk in file map*/
- fm->select_chunk = NULL;
- fm->total_chunks = 1;
- for(u=0; u<fm->f_ndims; u++)
- fm->total_chunks= fm->total_chunks*fm->chunks[u];
- if(IS_H5FD_MPI(dataset->oloc.file)) {
- H5_CHECK_OVERFLOW(fm->total_chunks, hsize_t, size_t);
- if(NULL == (fm->select_chunk = (hbool_t *) H5MM_calloc((size_t)fm->total_chunks * sizeof(hbool_t))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate chunk info")
- }
-
-
-
-
- /* Initialize skip list for chunk selections */
- if((fm->fsel = H5SL_create(H5SL_TYPE_HSIZE, 0.5, (size_t)H5D_DEFAULT_SKIPLIST_HEIGHT))==NULL)
- HGOTO_ERROR(H5E_DATASET,H5E_CANTCREATE,FAIL,"can't create skip list for chunk selections")
-
- /* Initialize "last chunk" information */
- fm->last_index=(hsize_t)-1;
- fm->last_chunk_info=NULL;
-
- /* Point at the dataspaces */
- fm->file_space = file_space;
- fm->mem_space = equiv_mspace;
- fm->mem_space_copy = equiv_mspace_init; /* Make certain to copy memory dataspace if necessary */
-
- /* Get type of selection on disk & in memory */
- if((fsel_type = H5S_GET_SELECT_TYPE(file_space)) < H5S_SEL_NONE)
- HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "unable to convert from file to memory data space")
- if((fm->msel_type = H5S_GET_SELECT_TYPE(equiv_mspace)) < H5S_SEL_NONE)
- HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "unable to convert from file to memory data space")
-
- /* If the selection is NONE or POINTS, set the flag to FALSE */
- if(fsel_type == H5S_SEL_POINTS || fsel_type == H5S_SEL_NONE)
- sel_hyper_flag = FALSE;
- else
- sel_hyper_flag = TRUE;
-
- /* Check if file selection is a point selection */
- if(!sel_hyper_flag) {
- /* Create temporary datatypes for selection iteration */
- if((f_tid = H5I_register(H5I_DATATYPE, H5T_copy(dataset->shared->type, H5T_COPY_ALL))) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register file datatype")
-
- /* Spaces aren't the same shape, iterate over the memory selection directly */
- if(H5S_select_iterate(&bogus, f_tid, file_space, H5D_chunk_file_cb, fm) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file chunk selections")
-
- /* Reset "last chunk" info */
- fm->last_index=(hsize_t)-1;
- fm->last_chunk_info=NULL;
- } /* end if */
- else {
- /* Build the file selection for each chunk */
- if(H5D_create_chunk_file_map_hyper(fm,dataset) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create file chunk selections")
-
- /* Clean file chunks' hyperslab span "scratch" information */
- curr_node=H5SL_first(fm->fsel);
- while(curr_node) {
- H5D_chunk_info_t *chunk_info; /* Pointer chunk information */
-
- /* Get pointer to chunk's information */
- chunk_info=H5SL_item(curr_node);
- assert(chunk_info);
-
- /* Clean hyperslab span's "scratch" information */
- if(H5S_hyper_reset_scratch(chunk_info->fspace) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "unable to reset span scratch info")
-
- /* Get the next chunk node in the skip list */
- curr_node=H5SL_next(curr_node);
- } /* end while */
- } /* end else */
-
- /* Build the memory selection for each chunk */
- if(sel_hyper_flag && H5S_select_shape_same(file_space,equiv_mspace)==TRUE) {
- /* Reset chunk template information */
- fm->mchunk_tmpl=NULL;
+ if(NULL == (type_info->tpath = H5T_path_find(src_type, dst_type, NULL, NULL, dxpl_id, FALSE)))
+ HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest datatype")
- /* If the selections are the same shape, use the file chunk information
- * to generate the memory chunk information quickly.
- */
- if(H5D_create_chunk_mem_map_hyper(fm) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create memory chunk selections")
+ /* Precompute some useful information */
+ type_info->src_type_size = H5T_get_size(src_type);
+ type_info->dst_type_size = H5T_get_size(dst_type);
+ type_info->max_type_size = MAX(type_info->src_type_size, type_info->dst_type_size);
+ type_info->is_conv_noop = H5T_path_noop(type_info->tpath);
+ type_info->is_xform_noop = H5Z_xform_noop(dxpl_cache->data_xform_prop);
+ if(type_info->is_xform_noop && type_info->is_conv_noop) {
+ type_info->cmpd_subset = NULL;
+ type_info->need_bkg = H5T_BKG_NO;
} /* end if */
else {
- size_t elmt_size; /* Memory datatype size */
-
- /* Make a copy of equivalent memory space */
- if((tmp_mspace = H5S_copy(equiv_mspace,TRUE))==NULL)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space")
-
- /* De-select the mem space copy */
- if(H5S_select_none(tmp_mspace) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to de-select memory space")
-
- /* Save chunk template information */
- fm->mchunk_tmpl=tmp_mspace;
-
- /* Create temporary datatypes for selection iteration */
- if(f_tid<0) {
- if((f_tid = H5I_register(H5I_DATATYPE, H5T_copy(dataset->shared->type, H5T_COPY_ALL))) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register file datatype")
- } /* end if */
-
- /* Create selection iterator for memory selection */
- if((elmt_size=H5T_get_size(mem_type))==0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_BADSIZE, FAIL, "datatype size invalid")
- if (H5S_select_iter_init(&(fm->mem_iter), equiv_mspace, elmt_size) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator")
- iter_init = TRUE; /* Selection iteration info has been initialized */
-
- /* Spaces aren't the same shape, iterate over the memory selection directly */
- if(H5S_select_iterate(&bogus, f_tid, file_space, H5D_chunk_mem_cb, fm) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create memory chunk selections")
-
- /* Clean up hyperslab stuff, if necessary */
- if(fm->msel_type != H5S_SEL_POINTS) {
- /* Clean memory chunks' hyperslab span "scratch" information */
- curr_node=H5SL_first(fm->fsel);
- while(curr_node) {
- H5D_chunk_info_t *chunk_info; /* Pointer chunk information */
-
- /* Get pointer to chunk's information */
- chunk_info=H5SL_item(curr_node);
- assert(chunk_info);
-
- /* Clean hyperslab span's "scratch" information */
- if(H5S_hyper_reset_scratch(chunk_info->mspace) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "unable to reset span scratch info")
-
- /* Get the next chunk node in the skip list */
- curr_node=H5SL_next(curr_node);
- } /* end while */
- } /* end if */
- } /* end else */
-
-done:
- /* Release the [potentially partially built] chunk mapping information if an error occurs */
- if(ret_value<0) {
- if(tmp_mspace && !fm->mchunk_tmpl) {
- if(H5S_close(tmp_mspace) < 0)
- HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "can't release memory chunk dataspace template")
- } /* end if */
-
- if (H5D_destroy_chunk_map(fm) < 0)
- HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release chunk mapping")
- } /* end if */
-
- /* Reset the global dataspace info */
- fm->file_space = NULL;
- fm->mem_space = NULL;
-
- if(equiv_mspace_init && equiv_mspace) {
- if(H5S_close(equiv_mspace) < 0)
- HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "can't release memory chunk dataspace template")
- } /* end if */
- if(iter_init) {
- if(H5S_SELECT_ITER_RELEASE(&(fm->mem_iter)) < 0)
- HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator")
- } /* end if */
- if(f_tid!=(-1)) {
- if(H5I_dec_ref(f_tid) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
- } /* end if */
- if(file_space_normalized) {
- if(H5S_hyper_denormalize_offset((H5S_t *)file_space, old_offset) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "unable to normalize dataspace by offset")
- } /* end if */
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_create_chunk_map() */
-
-
-/*--------------------------------------------------------------------------
- NAME
- H5D_free_chunk_info
- PURPOSE
- Internal routine to destroy a chunk info node
- USAGE
- void H5D_free_chunk_info(chunk_info)
- void *chunk_info; IN: Pointer to chunk info to destroy
- RETURNS
- No return value
- DESCRIPTION
- Releases all the memory for a chunk info node. Called by H5SL_iterate
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-static herr_t
-H5D_free_chunk_info(void *item, void UNUSED *key, void UNUSED *opdata)
-{
- H5D_chunk_info_t *chunk_info=(H5D_chunk_info_t *)item;
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_free_chunk_info)
-
- assert(chunk_info);
-
- /* Close the chunk's file dataspace */
- (void)H5S_close(chunk_info->fspace);
-
- /* Close the chunk's memory dataspace, if it's not shared */
- if(!chunk_info->mspace_shared)
- (void)H5S_close(chunk_info->mspace);
-
- /* Free the actual chunk info */
- H5FL_FREE(H5D_chunk_info_t,chunk_info);
-
- FUNC_LEAVE_NOAPI(0);
-} /* H5D_free_chunk_info() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_destroy_chunk_map
- *
- * Purpose: Destroy chunk mapping information.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Saturday, May 17, 2003
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D_destroy_chunk_map(const fm_map *fm)
-{
- herr_t ret_value = SUCCEED; /*return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_destroy_chunk_map)
-
- /* Free the chunk info skip list */
- if(fm->fsel) {
- if(H5SL_count(fm->fsel)>0)
- if(H5SL_iterate(fm->fsel,H5D_free_chunk_info,NULL) < 0)
- HGOTO_ERROR(H5E_PLIST,H5E_CANTNEXT,FAIL,"can't iterate over chunks")
-
- H5SL_close(fm->fsel);
- } /* end if */
+ size_t target_size; /* Desired buffer size */
- /* Free the memory chunk dataspace template */
- if(fm->mchunk_tmpl)
- if(H5S_close(fm->mchunk_tmpl) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "can't release memory chunk dataspace template")
- if(fm->select_chunk) H5MM_xfree(fm->select_chunk);
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_destroy_chunk_map() */
+ /* Check if the datatypes are compound subsets of one another */
+ type_info->cmpd_subset = H5T_path_compound_subset(type_info->tpath);
-
-/*-------------------------------------------------------------------------
- * Function: H5D_create_chunk_file_map_hyper
- *
- * Purpose: Create all chunk selections in file.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Thursday, May 29, 2003
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D_create_chunk_file_map_hyper(fm_map *fm,const H5D_t *dset)
-{
- hssize_t ssel_points; /* Number of elements in file selection */
- hsize_t sel_points; /* Number of elements in file selection */
- hsize_t sel_start[H5O_LAYOUT_NDIMS]; /* Offset of low bound of file selection */
- hsize_t sel_end[H5O_LAYOUT_NDIMS]; /* Offset of high bound of file selection */
- hsize_t start_coords[H5O_LAYOUT_NDIMS]; /* Starting coordinates of selection */
- hsize_t coords[H5O_LAYOUT_NDIMS]; /* Current coordinates of chunk */
- hsize_t end[H5O_LAYOUT_NDIMS]; /* Current coordinates of chunk */
- hsize_t chunk_index; /* Index of chunk */
- int curr_dim; /* Current dimension to increment */
- unsigned u; /* Local index variable */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_create_chunk_file_map_hyper)
-
- /* Sanity check */
- assert(fm->f_ndims>0);
-
- /* Get number of elements selected in file */
- if((ssel_points=H5S_GET_SELECT_NPOINTS(fm->file_space)) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection # of elements")
- H5_ASSIGN_OVERFLOW(sel_points,ssel_points,hssize_t,hsize_t);
-
- /* Get bounding box for selection (to reduce the number of chunks to iterate over) */
- if(H5S_SELECT_BOUNDS(fm->file_space, sel_start, sel_end) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info")
-
- /* Set initial chunk location & hyperslab size */
-
- for(u=0; u<fm->f_ndims; u++) {
- start_coords[u]=(sel_start[u]/fm->layout->u.chunk.dim[u])*fm->layout->u.chunk.dim[u];
- coords[u]=start_coords[u];
- end[u]=(coords[u]+fm->chunk_dim[u])-1;
- } /* end for */
-
-
- /* Calculate the index of this chunk */
- if(H5V_chunk_index(fm->f_ndims,coords,fm->layout->u.chunk.dim,fm->down_chunks,&chunk_index) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index")
-
- /* Iterate through each chunk in the dataset */
- while(sel_points) {
- /* Check for intersection of temporary chunk and file selection */
- /* (Casting away const OK - QAK) */
- if(H5S_hyper_intersect_block((H5S_t *)fm->file_space,coords,end)==TRUE) {
- H5S_t *tmp_fchunk; /* Temporary file dataspace */
- H5D_chunk_info_t *new_chunk_info; /* chunk information to insert into skip list */
- hssize_t schunk_points; /* Number of elements in chunk selection */
-
- /* Create "temporary" chunk for selection operations (copy file space) */
- if((tmp_fchunk = H5S_copy(fm->file_space,TRUE))==NULL)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space")
-
- /* Make certain selections are stored in span tree form (not "optimized hyperslab" or "all") */
- if(H5S_hyper_convert(tmp_fchunk) < 0) {
- (void)H5S_close(tmp_fchunk);
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to convert selection to span trees")
- } /* end if */
-
- /* "AND" temporary chunk and current chunk */
- if(H5S_select_hyperslab(tmp_fchunk,H5S_SELECT_AND,coords,NULL,fm->chunk_dim,NULL) < 0) {
- (void)H5S_close(tmp_fchunk);
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't create chunk selection")
- } /* end if */
-
- /* Resize chunk's dataspace dimensions to size of chunk */
- if(H5S_set_extent_real(tmp_fchunk,fm->chunk_dim) < 0) {
- (void)H5S_close(tmp_fchunk);
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't adjust chunk dimensions")
- } /* end if */
-
- /* Move selection back to have correct offset in chunk */
- if(H5S_hyper_adjust_u(tmp_fchunk,coords) < 0) {
- (void)H5S_close(tmp_fchunk);
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't adjust chunk selection")
- } /* end if */
-
- /* Add temporary chunk to the list of chunks */
-
- /* Allocate the file & memory chunk information */
- if (NULL==(new_chunk_info = H5FL_MALLOC (H5D_chunk_info_t))) {
- (void)H5S_close(tmp_fchunk);
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate chunk info")
- } /* end if */
-
- /* Initialize the chunk information */
-
- /* Set the chunk index */
- new_chunk_info->index=chunk_index;
-
- /* store chunk selection information */
- if(IS_H5FD_MPI(dset->oloc.file))
- fm->select_chunk[chunk_index] = TRUE;
-
- /* Set the file chunk dataspace */
- new_chunk_info->fspace=tmp_fchunk;
-
- /* Set the memory chunk dataspace */
- new_chunk_info->mspace=NULL;
- new_chunk_info->mspace_shared=0;
-
- /* Copy the chunk's coordinates */
- for(u=0; u<fm->f_ndims; u++)
- new_chunk_info->coords[u]=coords[u];
- new_chunk_info->coords[fm->f_ndims]=0;
-
- /* Insert the new chunk into the skip list */
- if(H5SL_insert(fm->fsel,new_chunk_info,&new_chunk_info->index) < 0) {
- H5D_free_chunk_info(new_chunk_info,NULL,NULL);
- HGOTO_ERROR(H5E_DATASPACE,H5E_CANTINSERT,FAIL,"can't insert chunk into skip list")
- } /* end if */
-
- /* Get number of elements selected in chunk */
- if((schunk_points=H5S_GET_SELECT_NPOINTS(tmp_fchunk)) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection # of elements")
- H5_ASSIGN_OVERFLOW(new_chunk_info->chunk_points,schunk_points,hssize_t,size_t);
-
- /* Decrement # of points left in file selection */
- sel_points-=(hsize_t)schunk_points;
-
- /* Leave if we are done */
- if(sel_points==0)
- HGOTO_DONE(SUCCEED)
- assert(sel_points>0);
- } /* end if */
-
- /* Increment chunk index */
- chunk_index++;
-
- /* Set current increment dimension */
- curr_dim=(int)fm->f_ndims-1;
-
- /* Increment chunk location in fastest changing dimension */
- H5_CHECK_OVERFLOW(fm->chunk_dim[curr_dim],hsize_t,hssize_t);
- coords[curr_dim]+=fm->chunk_dim[curr_dim];
- end[curr_dim]+=fm->chunk_dim[curr_dim];
-
- /* Bring chunk location back into bounds, if necessary */
- if(coords[curr_dim]>sel_end[curr_dim]) {
- do {
- /* Reset current dimension's location to 0 */
- coords[curr_dim]=start_coords[curr_dim]; /*lint !e771 The start_coords will always be initialized */
- end[curr_dim]=(coords[curr_dim]+(hssize_t)fm->chunk_dim[curr_dim])-1;
-
- /* Decrement current dimension */
- curr_dim--;
-
- /* Increment chunk location in current dimension */
- coords[curr_dim]+=fm->chunk_dim[curr_dim];
- end[curr_dim]=(coords[curr_dim]+fm->chunk_dim[curr_dim])-1;
- } while(coords[curr_dim]>sel_end[curr_dim]);
-
- /* Re-Calculate the index of this chunk */
- if(H5V_chunk_index(fm->f_ndims,coords,fm->layout->u.chunk.dim,fm->down_chunks,&chunk_index) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index")
- } /* end if */
- } /* end while */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_create_chunk_file_map_hyper() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_create_chunk_mem_map_hyper
- *
- * Purpose: Create all chunk selections in memory by copying the file
- * chunk selections and adjusting their offsets to be correct
- * for the memory.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Thursday, May 29, 2003
- *
- * Assumptions: That the file and memory selections are the same shape.
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D_create_chunk_mem_map_hyper(const fm_map *fm)
-{
- H5SL_node_t *curr_node; /* Current node in skip list */
- hsize_t file_sel_start[H5O_LAYOUT_NDIMS]; /* Offset of low bound of file selection */
- hsize_t file_sel_end[H5O_LAYOUT_NDIMS]; /* Offset of high bound of file selection */
- hsize_t mem_sel_start[H5O_LAYOUT_NDIMS]; /* Offset of low bound of file selection */
- hsize_t mem_sel_end[H5O_LAYOUT_NDIMS]; /* Offset of high bound of file selection */
- hssize_t adjust[H5O_LAYOUT_NDIMS]; /* Adjustment to make to all file chunks */
- hssize_t chunk_adjust[H5O_LAYOUT_NDIMS]; /* Adjustment to make to a particular chunk */
- unsigned u; /* Local index variable */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_create_chunk_mem_map_hyper)
-
- /* Sanity check */
- assert(fm->f_ndims>0);
-
- /* Check for all I/O going to a single chunk */
- if(H5SL_count(fm->fsel)==1) {
- H5D_chunk_info_t *chunk_info; /* Pointer to chunk information */
-
- /* Get the node */
- curr_node=H5SL_first(fm->fsel);
-
- /* Get pointer to chunk's information */
- chunk_info=H5SL_item(curr_node);
- assert(chunk_info);
-
- /* Check if it's OK to share dataspace */
- if(fm->mem_space_copy) {
- /* Copy the memory dataspace & selection to be the chunk's dataspace & selection */
- if((chunk_info->mspace = H5S_copy(fm->mem_space,FALSE))==NULL)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space")
- } /* end if */
+ /* Check if we need a background buffer */
+ if(do_write && H5T_detect_class(dset->shared->type, H5T_VLEN))
+ type_info->need_bkg = H5T_BKG_YES;
else {
- /* Just point at the memory dataspace & selection */
- /* (Casting away const OK -QAK) */
- chunk_info->mspace=(H5S_t *)fm->mem_space;
-
- /* Indicate that the chunk's memory space is shared */
- chunk_info->mspace_shared=1;
- } /* end else */
- } /* end if */
- else {
- /* Get bounding box for file selection */
- if(H5S_SELECT_BOUNDS(fm->file_space, file_sel_start, file_sel_end) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info")
-
- /* Get bounding box for memory selection */
- if(H5S_SELECT_BOUNDS(fm->mem_space, mem_sel_start, mem_sel_end) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get file selection bound info")
-
- /* Calculate the adjustment for memory selection from file selection */
- assert(fm->m_ndims==fm->f_ndims);
- for(u=0; u<fm->f_ndims; u++) {
- H5_CHECK_OVERFLOW(file_sel_start[u],hsize_t,hssize_t);
- H5_CHECK_OVERFLOW(mem_sel_start[u],hsize_t,hssize_t);
- adjust[u]=(hssize_t)file_sel_start[u]-(hssize_t)mem_sel_start[u];
- } /* end for */
-
- /* Iterate over each chunk in the chunk list */
- curr_node=H5SL_first(fm->fsel);
- while(curr_node) {
- H5D_chunk_info_t *chunk_info; /* Pointer to chunk information */
-
- /* Get pointer to chunk's information */
- chunk_info=H5SL_item(curr_node);
- assert(chunk_info);
-
- /* Copy the information */
-
- /* Copy the memory dataspace */
- if((chunk_info->mspace = H5S_copy(fm->mem_space,TRUE))==NULL)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space")
-
- /* Release the current selection */
- if(H5S_SELECT_RELEASE(chunk_info->mspace) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection")
-
- /* Copy the file chunk's selection */
- if(H5S_select_copy(chunk_info->mspace,chunk_info->fspace,FALSE) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy selection")
-
- /* Compensate for the chunk offset */
- for(u=0; u<fm->f_ndims; u++) {
- H5_CHECK_OVERFLOW(chunk_info->coords[u],hsize_t,hssize_t);
- chunk_adjust[u]=adjust[u]-(hssize_t)chunk_info->coords[u]; /*lint !e771 The adjust array will always be initialized */
- } /* end for */
-
- /* Adjust the selection */
- if(H5S_hyper_adjust_s(chunk_info->mspace,chunk_adjust) < 0) /*lint !e772 The chunk_adjust array will always be initialized */
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't adjust chunk selection")
-
- /* Get the next chunk node in the skip list */
- curr_node=H5SL_next(curr_node);
- } /* end while */
- } /* end else */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_create_chunk_mem_map_hyper() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_chunk_file_cb
- *
- * Purpose: Callback routine for file selection iterator. Used when
- * creating selections in file for each point selected.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Wednesday, July 23, 2003
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D_chunk_file_cb(void UNUSED *elem, hid_t UNUSED type_id, unsigned ndims, const hsize_t *coords, void *_fm)
-{
- fm_map *fm = (fm_map*)_fm; /* File<->memory chunk mapping info */
- H5D_chunk_info_t *chunk_info; /* Chunk information for current chunk */
- hsize_t coords_in_chunk[H5O_LAYOUT_NDIMS]; /* Coordinates of element in chunk */
- hsize_t chunk_index; /* Chunk index */
- unsigned u; /* Local index variable */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_file_cb)
-
- /* Calculate the index of this chunk */
- if(H5V_chunk_index(ndims,coords,fm->layout->u.chunk.dim,fm->down_chunks,&chunk_index) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index")
-
- /* Find correct chunk in file & memory skip list */
- if(chunk_index==fm->last_index) {
- /* If the chunk index is the same as the last chunk index we used,
- * get the cached info to operate on.
- */
- chunk_info=fm->last_chunk_info;
- } /* end if */
- else {
- /* If the chunk index is not the same as the last chunk index we used,
- * find the chunk in the skip list.
- */
- /* Get the chunk node from the skip list */
- if((chunk_info=H5SL_search(fm->fsel,&chunk_index))==NULL) {
- H5S_t *fspace; /* Memory chunk's dataspace */
-
- /* Allocate the file & memory chunk information */
- if (NULL==(chunk_info = H5FL_MALLOC (H5D_chunk_info_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate chunk info")
-
- /* Initialize the chunk information */
-
- /* Set the chunk index */
- chunk_info->index=chunk_index;
+ H5T_bkg_t path_bkg; /* Type conversion's background info */
- /* Create a dataspace for the chunk */
- if((fspace = H5S_create_simple(fm->f_ndims,fm->chunk_dim,NULL))==NULL) {
- H5FL_FREE(H5D_chunk_info_t,chunk_info);
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "unable to create dataspace for chunk")
+ if((path_bkg = H5T_path_bkg(type_info->tpath))) {
+ /* Retrieve the bkgr buffer property */
+ type_info->need_bkg = dxpl_cache->bkgr_buf_type;
+ type_info->need_bkg = MAX(path_bkg, type_info->need_bkg);
} /* end if */
+ else
+ type_info->need_bkg = H5T_BKG_NO; /*never needed even if app says yes*/
+ } /* end else */
- /* De-select the chunk space */
- if(H5S_select_none(fspace) < 0) {
- (void)H5S_close(fspace);
- H5FL_FREE(H5D_chunk_info_t,chunk_info);
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to de-select dataspace")
- } /* end if */
- /* Set the file chunk dataspace */
- chunk_info->fspace=fspace;
+ /* Set up datatype conversion/background buffers */
- /* Set the memory chunk dataspace */
- chunk_info->mspace=NULL;
- chunk_info->mspace_shared=0;
+ /* Get buffer size from DXPL */
+ target_size = dxpl_cache->max_temp_buf;
- /* Set the number of selected elements in chunk to zero */
- chunk_info->chunk_points=0;
+ /* If the buffer is too small to hold even one element, try to make it bigger */
+ if(target_size < type_info->max_type_size) {
+ hbool_t default_buffer_info; /* Whether the buffer information are the defaults */
- /* Compute the chunk's coordinates */
- for(u=0; u<fm->f_ndims; u++) {
- H5_CHECK_OVERFLOW(fm->layout->u.chunk.dim[u],hsize_t,hssize_t);
- chunk_info->coords[u]=(coords[u]/(hssize_t)fm->layout->u.chunk.dim[u])*(hssize_t)fm->layout->u.chunk.dim[u];
- } /* end for */
- chunk_info->coords[fm->f_ndims]=0;
+ /* Detect if we have all default settings for buffers */
+ default_buffer_info = (H5D_TEMP_BUF_SIZE == dxpl_cache->max_temp_buf)
+ && (NULL == dxpl_cache->tconv_buf) && (NULL == dxpl_cache->bkgr_buf);
- /* Insert the new chunk into the skip list */
- if(H5SL_insert(fm->fsel,chunk_info,&chunk_info->index) < 0) {
- H5D_free_chunk_info(chunk_info,NULL,NULL);
- HGOTO_ERROR(H5E_DATASPACE,H5E_CANTINSERT,FAIL,"can't insert chunk into skip list")
- } /* end if */
+ /* Check if we are using the default buffer info */
+ if(default_buffer_info)
+ /* OK to get bigger for library default settings */
+ target_size = type_info->max_type_size;
+ else
+ /* Don't get bigger than the application has requested */
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "temporary buffer max size is too small")
} /* end if */
- /* Update the "last chunk seen" information */
- fm->last_index=chunk_index;
- fm->last_chunk_info=chunk_info;
- } /* end else */
-
- /* Get the coordinates of the element in the chunk */
- for(u=0; u<fm->f_ndims; u++)
- coords_in_chunk[u]=coords[u]%fm->layout->u.chunk.dim[u];
+ /* Compute the number of elements that will fit into buffer */
+ type_info->request_nelmts = target_size / type_info->max_type_size;
- /* Add point to file selection for chunk */
- if(H5S_select_elements(chunk_info->fspace, H5S_SELECT_APPEND, (size_t)1, (const hsize_t **)coords_in_chunk) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "unable to select element")
+ /* Sanity check elements in temporary buffer */
+ if(type_info->request_nelmts == 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "temporary buffer max size is too small")
- /* Increment the number of elemented selected in chunk */
- chunk_info->chunk_points++;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_chunk_file_cb() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_chunk_mem_cb
- *
- * Purpose: Callback routine for file selection iterator. Used when
- * creating selections in memory for each chunk.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Raymond Lu
- * Thursday, April 10, 2003
- *
- *-------------------------------------------------------------------------
- */
-/* ARGSUSED */
-static herr_t
-H5D_chunk_mem_cb(void UNUSED *elem, hid_t UNUSED type_id, unsigned ndims, const hsize_t *coords, void *_fm)
-{
- fm_map *fm = (fm_map*)_fm; /* File<->memory chunk mapping info */
- H5D_chunk_info_t *chunk_info; /* Chunk information for current chunk */
- hsize_t coords_in_mem[H5O_LAYOUT_NDIMS]; /* Coordinates of element in memory */
- hsize_t chunk_index; /* Chunk index */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_mem_cb)
-
- /* Calculate the index of this chunk */
- if(H5V_chunk_index(ndims,coords,fm->layout->u.chunk.dim,fm->down_chunks,&chunk_index) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index")
-
- /* Find correct chunk in file & memory skip list */
- if(chunk_index==fm->last_index) {
- /* If the chunk index is the same as the last chunk index we used,
- * get the cached spaces to operate on.
- */
- chunk_info=fm->last_chunk_info;
- } /* end if */
- else {
- /* If the chunk index is not the same as the last chunk index we used,
- * find the chunk in the skip list.
+ /*
+ * Get a temporary buffer for type conversion unless the app has already
+ * supplied one through the xfer properties. Instead of allocating a
+ * buffer which is the exact size, we allocate the target size. The
+ * malloc() is usually less resource-intensive if we allocate/free the
+ * same size over and over.
*/
- /* Get the chunk node from the skip list */
- if((chunk_info=H5SL_search(fm->fsel,&chunk_index))==NULL)
- HGOTO_ERROR(H5E_DATASPACE,H5E_NOTFOUND,FAIL,"can't locate chunk in skip list")
-
- /* Check if the chunk already has a memory space */
- if(chunk_info->mspace==NULL) {
- /* Copy the template memory chunk dataspace */
- if((chunk_info->mspace = H5S_copy(fm->mchunk_tmpl,FALSE))==NULL)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy file space")
- } /* end else */
-
- /* Update the "last chunk seen" information */
- fm->last_index=chunk_index;
- fm->last_chunk_info=chunk_info;
- } /* end else */
-
- /* Get coordinates of selection iterator for memory */
- if(H5S_SELECT_ITER_COORDS(&fm->mem_iter,coords_in_mem) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get iterator coordinates")
-
- /* Add point to memory selection for chunk */
- if(fm->msel_type==H5S_SEL_POINTS) {
- if(H5S_select_elements(chunk_info->mspace, H5S_SELECT_APPEND, (size_t)1, (const hsize_t **)coords_in_mem) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "unable to select element")
- } /* end if */
- else {
- if(H5S_hyper_add_span_element(chunk_info->mspace, fm->m_ndims, coords_in_mem) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "unable to select element")
+ if(NULL == (type_info->tconv_buf = (uint8_t *)dxpl_cache->tconv_buf)) {
+ /* Allocate temporary buffer */
+ if(NULL == (type_info->tconv_buf = H5FL_BLK_MALLOC(type_conv, target_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion")
+ type_info->tconv_buf_allocated = TRUE;
+ } /* end if */
+ if(type_info->need_bkg && NULL == (type_info->bkg_buf = (uint8_t *)dxpl_cache->bkgr_buf)) {
+ size_t bkg_size; /* Desired background buffer size */
+
+ /* Compute the background buffer size */
+ /* (don't try to use buffers smaller than the default size) */
+ bkg_size = type_info->request_nelmts * type_info->dst_type_size;
+ if(bkg_size < dxpl_cache->max_temp_buf)
+ bkg_size = dxpl_cache->max_temp_buf;
+
+ /* Allocate background buffer */
+ /* (Need calloc()-like call since memory needs to be initialized) */
+ if(NULL == (type_info->bkg_buf = H5FL_BLK_CALLOC(type_conv, bkg_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for background conversion")
+ type_info->bkg_buf_allocated = TRUE;
+ } /* end if */
} /* end else */
- /* Move memory selection iterator to next element in selection */
- if(H5S_SELECT_ITER_NEXT(&fm->mem_iter, (size_t)1) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to move to next iterator location")
-
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_chunk_mem_cb() */
+} /* end H5D_typeinfo_init() */
+#ifdef H5_HAVE_PARALLEL
/*-------------------------------------------------------------------------
- * Function: H5D_ioinfo_init
+ * Function: H5D_ioinfo_adjust
*
- * Purpose: Routine for determining correct I/O operations for
- * each I/O action.
+ * Purpose: Adjust operation's I/O info for any parallel I/O
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
- * Thursday, September 30, 2004
+ * Thursday, March 27, 2008
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5D_ioinfo_init(H5D_t *dset, const H5D_dxpl_cache_t *dxpl_cache, hid_t dxpl_id,
- const H5S_t
-#if !(defined H5_HAVE_PARALLEL || defined H5S_DEBUG)
- UNUSED
-#endif /* H5_HAVE_PARALLEL */
- *mem_space, const H5S_t
-#if !(defined H5_HAVE_PARALLEL || defined H5S_DEBUG)
- UNUSED
-#endif /* H5_HAVE_PARALLEL */
- *file_space, H5T_path_t
-#ifndef H5_HAVE_PARALLEL
- UNUSED
-#endif /* H5_HAVE_PARALLEL */
- *tpath,
- H5D_io_info_t *io_info)
+H5D_ioinfo_adjust(H5D_io_info_t *io_info, const H5D_t *dset,
+ const H5D_dxpl_cache_t *dxpl_cache, hid_t dxpl_id,
+ const H5S_t *file_space, const H5S_t *mem_space,
+ const H5D_type_info_t *type_info, const H5D_chunk_map_t *fm)
{
herr_t ret_value = SUCCEED; /* Return value */
-#if defined H5_HAVE_PARALLEL || defined H5S_DEBUG
- FUNC_ENTER_NOAPI_NOINIT(H5D_ioinfo_init)
-#else /* defined H5_HAVE_PARALLEL || defined H5S_DEBUG */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_ioinfo_init)
-#endif /* defined H5_HAVE_PARALLEL || defined H5S_DEBUG */
+ FUNC_ENTER_NOAPI_NOINIT(H5D_ioinfo_adjust)
/* check args */
HDassert(dset);
HDassert(dset->oloc.file);
HDassert(mem_space);
HDassert(file_space);
- HDassert(tpath);
+ HDassert(type_info);
+ HDassert(type_info->tpath);
HDassert(io_info);
- /* Set up "normal" I/O fields */
- io_info->dset=dset;
- io_info->dxpl_cache=dxpl_cache;
- io_info->dxpl_id=dxpl_id;
- io_info->store=NULL; /* Set later in I/O routine? */
-
- /* Set I/O operations to initial values */
- io_info->ops=dset->shared->io_ops;
-
-#ifdef H5_HAVE_PARALLEL
- /* Start in the "not modified" xfer_mode state */
- io_info->xfer_mode_changed = FALSE;
-
- if(IS_H5FD_MPI(dset->oloc.file)) {
+ /* Make any parallel I/O adjustments */
+ if(io_info->using_mpi_vfd) {
htri_t opt; /* Flag whether a selection is optimizable */
+ /* Record the original state of parallel I/O transfer options */
+ io_info->orig.xfer_mode = io_info->dxpl_cache->xfer_mode;
+ io_info->orig.coll_opt_mode = io_info->dxpl_cache->coll_opt_mode;
+ io_info->orig.io_ops.single_read = io_info->io_ops.single_read;
+ io_info->orig.io_ops.single_write = io_info->io_ops.single_write;
+
/* Get MPI communicator */
- if((io_info->comm = H5F_mpi_get_comm(dset->oloc.file)) == MPI_COMM_NULL)
+ if(MPI_COMM_NULL == (io_info->comm = H5F_mpi_get_comm(dset->oloc.file)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't retrieve MPI communicator")
- /*
- * Check if we can set direct MPI-IO read/write functions
- */
- opt=H5D_mpio_opt_possible(io_info, mem_space, file_space, tpath);
- if(opt==FAIL)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "invalid check for direct IO dataspace ");
+ /* Check if we can set direct MPI-IO read/write functions */
+ if((opt = H5D_mpio_opt_possible(io_info, file_space, mem_space, type_info, fm)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "invalid check for direct IO dataspace ")
/* Check if we can use the optimized parallel I/O routines */
- if(opt==TRUE) {
- /* Set the pointers to the MPI-specific routines */
- io_info->ops.read = H5D_mpio_select_read;
- io_info->ops.write = H5D_mpio_select_write;
+ if(opt == TRUE) {
+ /* Override the I/O op pointers to the MPI-specific routines */
+ io_info->io_ops.multi_read = dset->shared->layout.ops->par_read;
+ io_info->io_ops.multi_write = dset->shared->layout.ops->par_write;
+ io_info->io_ops.single_read = H5D_mpio_select_read;
+ io_info->io_ops.single_write = H5D_mpio_select_write;
} /* end if */
else {
- /* Set the pointers to the non-MPI-specific routines */
- io_info->ops.read = H5D_select_read;
- io_info->ops.write = H5D_select_write;
-
/* If we won't be doing collective I/O, but the user asked for
* collective I/O, change the request to use independent I/O, but
* mark it so that we remember to revert the change.
*/
- if(io_info->dxpl_cache->xfer_mode==H5FD_MPIO_COLLECTIVE) {
+ if(io_info->dxpl_cache->xfer_mode == H5FD_MPIO_COLLECTIVE) {
H5P_genplist_t *dx_plist; /* Data transer property list */
/* Get the dataset transfer property list */
- if (NULL == (dx_plist = H5I_object(dxpl_id)))
+ if(NULL == (dx_plist = (H5P_genplist_t *)H5I_object(dxpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list")
/* Change the xfer_mode to independent for handling the I/O */
io_info->dxpl_cache->xfer_mode = H5FD_MPIO_INDEPENDENT;
- if(H5P_set (dx_plist, H5D_XFER_IO_XFER_MODE_NAME, &io_info->dxpl_cache->xfer_mode) < 0)
+ if(H5P_set(dx_plist, H5D_XFER_IO_XFER_MODE_NAME, &io_info->dxpl_cache->xfer_mode) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set transfer mode")
-
- /* Indicate that the transfer mode should be restored before returning
- * to user.
- */
- io_info->xfer_mode_changed = TRUE;
} /* end if */
} /* end else */
} /* end if */
- else {
- /* Set the pointers to the non-MPI-specific routines */
- io_info->ops.read = H5D_select_read;
- io_info->ops.write = H5D_select_write;
- } /* end else */
-#else /* H5_HAVE_PARALLEL */
- io_info->ops.read = H5D_select_read;
- io_info->ops.write = H5D_select_write;
-#endif /* H5_HAVE_PARALLEL */
-#ifdef H5S_DEBUG
- /* Get the information for the I/O statistics */
- if((io_info->stats=H5S_find(mem_space,file_space))==NULL)
- HGOTO_ERROR(H5E_DATASET, H5E_BADSELECT, FAIL, "can't set up selection statistics");
-#endif /* H5S_DEBUG */
-
-#if defined H5_HAVE_PARALLEL || defined H5S_DEBUG
done:
-#endif /* H5_HAVE_PARALLEL || H5S_DEBUG */
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_ioinfo_init() */
+} /* end H5D_ioinfo_adjust() */
-#ifdef H5_HAVE_PARALLEL
/*-------------------------------------------------------------------------
* Function: H5D_ioinfo_term
@@ -3304,22 +937,69 @@ H5D_ioinfo_term(H5D_io_info_t *io_info)
FUNC_ENTER_NOAPI_NOINIT(H5D_ioinfo_term)
- /* Check if we need to revert the change to the xfer mode */
- if (io_info->xfer_mode_changed) {
- H5P_genplist_t *dx_plist; /* Data transer property list */
+ /* Check if we used the MPI VFD for the I/O */
+ if(io_info->using_mpi_vfd) {
+ /* Check if we need to revert the change to the xfer mode */
+ if(io_info->orig.xfer_mode != io_info->dxpl_cache->xfer_mode) {
+ H5P_genplist_t *dx_plist; /* Data transer property list */
+
+ /* Get the dataset transfer property list */
+ if(NULL == (dx_plist = (H5P_genplist_t *)H5I_object(io_info->dxpl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list")
+
+ /* Restore the original parallel I/O mode */
+ if(H5P_set(dx_plist, H5D_XFER_IO_XFER_MODE_NAME, &io_info->orig.xfer_mode) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set transfer mode")
+ } /* end if */
+
+ /* Check if we need to revert the change to the collective opt mode */
+ if(io_info->orig.coll_opt_mode != io_info->dxpl_cache->coll_opt_mode) {
+ H5P_genplist_t *dx_plist; /* Data transer property list */
- /* Get the dataset transfer property list */
- if (NULL == (dx_plist = H5I_object(io_info->dxpl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list")
+ /* Get the dataset transfer property list */
+ if(NULL == (dx_plist = (H5P_genplist_t *)H5I_object(io_info->dxpl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list")
- /* Restore the original parallel I/O mode */
- io_info->dxpl_cache->xfer_mode = H5FD_MPIO_COLLECTIVE;
- if(H5P_set (dx_plist, H5D_XFER_IO_XFER_MODE_NAME, &io_info->dxpl_cache->xfer_mode) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set transfer mode")
+ /* Restore the original parallel I/O mode */
+ if(H5P_set(dx_plist, H5D_XFER_MPIO_COLLECTIVE_OPT_NAME, &io_info->orig.coll_opt_mode) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set collective option mode")
+ } /* end if */
} /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_ioinfo_term() */
-#endif
+#endif /* H5_HAVE_PARALLEL */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_typeinfo_term
+ *
+ * Purpose: Common logic for terminating a type info object
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, March 6, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_typeinfo_term(const H5D_type_info_t *type_info)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_typeinfo_term)
+
+ /* Check for releasing datatype conversion & background buffers */
+ if(type_info->tconv_buf_allocated) {
+ HDassert(type_info->tconv_buf);
+ (void)H5FL_BLK_FREE(type_conv, type_info->tconv_buf);
+ } /* end if */
+ if(type_info->bkg_buf_allocated) {
+ HDassert(type_info->bkg_buf);
+ (void)H5FL_BLK_FREE(type_conv, type_info->bkg_buf);
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5D_typeinfo_term() */
+
diff --git a/src/H5Distore.c b/src/H5Distore.c
deleted file mode 100644
index 399f9f9..0000000
--- a/src/H5Distore.c
+++ /dev/null
@@ -1,4039 +0,0 @@
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Copyright by The HDF Group. *
- * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
- * access to either file, you may request a copy from help@hdfgroup.org. *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-/* Programmer: Robb Matzke <matzke@llnl.gov>
- * Wednesday, October 8, 1997
- *
- * Purpose: Indexed (chunked) I/O functions. The logical
- * multi-dimensional data space is regularly partitioned into
- * same-sized "chunks", the first of which is aligned with the
- * logical origin. The chunks are given a multi-dimensional
- * index which is used as a lookup key in a B-tree that maps
- * chunk index to disk address. Each chunk can be compressed
- * independently and the chunks may move around in the file as
- * their storage requirements change.
- *
- * Cache: Disk I/O is performed in units of chunks and H5MF_alloc()
- * contains code to optionally align chunks on disk block
- * boundaries for performance.
- *
- * The chunk cache is an extendible hash indexed by a function
- * of storage B-tree address and chunk N-dimensional offset
- * within the dataset. Collisions are not resolved -- one of
- * the two chunks competing for the hash slot must be preempted
- * from the cache. All entries in the hash also participate in
- * a doubly-linked list and entries are penalized by moving them
- * toward the front of the list. When a new chunk is about to
- * be added to the cache the heap is pruned by preempting
- * entries near the front of the list to make room for the new
- * entry which is added to the end of the list.
- */
-
-/****************/
-/* Module Setup */
-/****************/
-
-#define H5B_PACKAGE /*suppress error about including H5Bpkg */
-#define H5D_PACKAGE /*suppress error about including H5Dpkg */
-
-
-/***********/
-/* Headers */
-/***********/
-#include "H5private.h" /* Generic Functions */
-#include "H5Bpkg.h" /* B-link trees */
-#include "H5Dpkg.h" /* Datasets */
-#include "H5Eprivate.h" /* Error handling */
-#include "H5Fprivate.h" /* Files */
-#include "H5FDprivate.h" /* File drivers */
-#include "H5FLprivate.h" /* Free Lists */
-#include "H5Iprivate.h" /* IDs */
-#include "H5MFprivate.h" /* File space management */
-#include "H5MMprivate.h" /* Memory management */
-#include "H5Oprivate.h" /* Object headers */
-#include "H5Pprivate.h" /* Property lists */
-#include "H5Sprivate.h" /* Dataspaces */
-#include "H5SLprivate.h" /* Skip lists */
-#include "H5Vprivate.h" /* Vector and array functions */
-
-/****************/
-/* Local Macros */
-/****************/
-
-/*
- * Feature: If this constant is defined then every cache preemption and load
- * causes a character to be printed on the standard error stream:
- *
- * `.': Entry was preempted because it has been completely read or
- * completely written but not partially read and not partially
- * written. This is often a good reason for preemption because such
- * a chunk will be unlikely to be referenced in the near future.
- *
- * `:': Entry was preempted because it hasn't been used recently.
- *
- * `#': Entry was preempted because another chunk collided with it. This
- * is usually a relatively bad thing. If there are too many of
- * these then the number of entries in the cache can be increased.
- *
- * c: Entry was preempted because the file is closing.
- *
- * w: A chunk read operation was eliminated because the library is
- * about to write new values to the entire chunk. This is a good
- * thing, especially on files where the chunk size is the same as
- * the disk block size, chunks are aligned on disk block boundaries,
- * and the operating system can also eliminate a read operation.
- */
-
-/*#define H5D_ISTORE_DEBUG */
-
-/*
- * Given a B-tree node return the dimensionality of the chunks pointed to by
- * that node.
- */
-#define H5D_ISTORE_NDIMS(X) (((X)->sizeof_rkey-8)/8)
-
-#define H5D_HASH(D,ADDR) H5F_addr_hash(ADDR,(D)->cache.chunk.nslots)
-
-#define H5D_ISTORE_DEFAULT_SKIPLIST_HEIGHT 8
-
-/******************/
-/* Local Typedefs */
-/******************/
-
-/* Raw data chunks are cached. Each entry in the cache is: */
-typedef struct H5D_rdcc_ent_t {
- hbool_t locked; /*entry is locked in cache */
- hbool_t dirty; /*needs to be written to disk? */
- hsize_t offset[H5O_LAYOUT_NDIMS]; /*chunk name */
- size_t rd_count; /*bytes remaining to be read */
- size_t wr_count; /*bytes remaining to be written */
- size_t chunk_size; /*size of a chunk */
- size_t alloc_size; /*amount allocated for the chunk */
- uint8_t *chunk; /*the unfiltered chunk data */
- unsigned idx; /*index in hash table */
- struct H5D_rdcc_ent_t *next;/*next item in doubly-linked list */
- struct H5D_rdcc_ent_t *prev;/*previous item in doubly-linked list */
-} H5D_rdcc_ent_t;
-typedef H5D_rdcc_ent_t *H5D_rdcc_ent_ptr_t; /* For free lists */
-
-/*
- * Data exchange structure for indexed storage nodes. This structure is
- * passed through the B-link tree layer to the methods for the objects
- * to which the B-link tree points for operations which require no
- * additional information.
- *
- * (Just an alias for the "common" info).
- */
-typedef H5D_istore_bt_ud_common_t H5D_istore_ud0_t;
-
-/* B-tree callback info for iteration to total allocated space */
-typedef struct H5D_istore_it_ud1_t {
- H5D_istore_bt_ud_common_t common; /* Common info for B-tree user data (must be first) */
- hsize_t total_storage; /*output from iterator */
-} H5D_istore_it_ud1_t;
-
-/* B-tree callback info for iteration to dump node's info */
-typedef struct H5D_istore_it_ud2_t {
- H5D_istore_bt_ud_common_t common; /* Common info for B-tree user data (must be first) */
- FILE *stream; /*debug output stream */
- hbool_t header_displayed; /* Node's header is displayed? */
-} H5D_istore_it_ud2_t;
-
-/* B-tree callback info for iteration to prune chunks */
-typedef struct H5D_istore_it_ud3_t {
- H5D_istore_bt_ud_common_t common; /* Common info for B-tree user data (must be first) */
- const hsize_t *dims; /* New dataset dimensions */
- const hsize_t *down_chunks; /* "down" size of number of chunks in each dimension */
- H5SL_t *outside; /* Skip list to hold chunks outside the new dimensions */
-} H5D_istore_it_ud3_t;
-
-/* B-tree callback info for iteration to copy data */
-typedef struct H5D_istore_it_ud4_t {
- H5D_istore_bt_ud_common_t common; /* Common info for B-tree user data (must be first) */
- H5F_t *file_src; /* Source file for copy */
- haddr_t addr_dst; /* Address of dest. B-tree */
- void *buf; /* Buffer to hold chunk data for read/write */
- void *bkg; /* Buffer for background information during type conversion */
- size_t buf_size; /* Buffer size */
- hbool_t do_convert; /* Whether to perform type conversions */
-
- /* needed for converting variable-length data */
- hid_t tid_src; /* Datatype ID for source datatype */
- hid_t tid_dst; /* Datatype ID for destination datatype */
- hid_t tid_mem; /* Datatype ID for memory datatype */
- H5T_t *dt_src; /* Source datatype */
- H5T_path_t *tpath_src_mem; /* Datatype conversion path from source file to memory */
- H5T_path_t *tpath_mem_dst; /* Datatype conversion path from memory to dest. file */
- void *reclaim_buf; /* Buffer for reclaiming data */
- size_t reclaim_buf_size; /* Reclaim buffer size */
- size_t nelmts; /* Number of elements in buffer */
- H5S_t *buf_space; /* Dataspace describing buffer */
-
- /* needed for compressed variable-length data */
- H5O_pline_t *pline; /* Filter pipeline */
-
- /* needed for copy object pointed by refs */
- H5F_t *file_dst; /* Destination file for copy */
- H5O_copy_t *cpy_info; /* Copy options */
-} H5D_istore_it_ud4_t;
-
-/* B-tree callback info for iteration to obtain chunk address and the index of the chunk for all chunks in the B-tree. */
-typedef struct H5D_istore_it_ud5_t {
- H5D_istore_bt_ud_common_t common; /* Common info for B-tree user data (must be first) */
- hsize_t *down_chunks;
- haddr_t *chunk_addr;
-} H5D_istore_it_ud5_t;
-
-/* Skip list node for storing chunks to remove during an iteration */
-typedef struct H5D_istore_sl_ck_t {
- hsize_t index; /* Index of chunk to remove (must be first) */
- H5D_istore_key_t key; /* Chunk key */
-} H5D_istore_sl_ck_t;
-
-/* Skip list callback info when destroying list & removing chunks */
-typedef struct H5D_istore_sl_rm_t {
- H5F_t *f; /* Pointer to file for B-tree */
- hid_t dxpl_id; /* DXPL to use */
- const H5O_layout_t *mesg; /* Layout message */
-} H5D_istore_sl_rm_t;
-
-/********************/
-/* Local Prototypes */
-/********************/
-
-static void *H5D_istore_chunk_alloc(size_t size, const H5O_pline_t *pline);
-static void *H5D_istore_chunk_xfree(void *chk, const H5O_pline_t *pline);
-static herr_t H5D_istore_shared_create (const H5F_t *f, H5O_layout_t *layout);
-static herr_t H5D_istore_shared_free (void *page);
-
-/* B-tree iterator callbacks */
-static int H5D_istore_iter_chunkmap(H5F_t *f, hid_t dxpl_id, const void *left_key, haddr_t addr,
- const void *right_key, void *_udata);
-static int H5D_istore_iter_allocated(H5F_t *f, hid_t dxpl_id, const void *left_key, haddr_t addr,
- const void *right_key, void *_udata);
-static int H5D_istore_iter_dump(H5F_t *f, hid_t dxpl_id, const void *left_key, haddr_t addr,
- const void *right_key, void *_udata);
-static int H5D_istore_prune_check(H5F_t *f, hid_t dxpl_id, const void *_lt_key, haddr_t addr,
- const void *_rt_key, void *_udata);
-static int H5D_istore_iter_copy(H5F_t *f, hid_t dxpl_id, const void *_lt_key, haddr_t addr,
- const void *_rt_key, void *_udata);
-
-/* B-tree callbacks */
-static H5RC_t *H5D_istore_get_shared(const H5F_t *f, const void *_udata);
-static herr_t H5D_istore_new_node(H5F_t *f, hid_t dxpl_id, H5B_ins_t, void *_lt_key,
- void *_udata, void *_rt_key,
- haddr_t *addr_p /*out*/);
-static int H5D_istore_cmp2(H5F_t *f, hid_t dxpl_id, void *_lt_key, void *_udata,
- void *_rt_key);
-static int H5D_istore_cmp3(H5F_t *f, hid_t dxpl_id, void *_lt_key, void *_udata,
- void *_rt_key);
-static herr_t H5D_istore_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_lt_key,
- void *_udata);
-static H5B_ins_t H5D_istore_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key,
- hbool_t *lt_key_changed, void *_md_key,
- void *_udata, void *_rt_key,
- hbool_t *rt_key_changed,
- haddr_t *new_node/*out*/);
-static H5B_ins_t H5D_istore_remove( H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key,
- hbool_t *lt_key_changed, void *_udata, void *_rt_key,
- hbool_t *rt_key_changed);
-static herr_t H5D_istore_decode_key(const H5F_t *f, const H5B_t *bt, const uint8_t *raw,
- void *_key);
-static herr_t H5D_istore_encode_key(const H5F_t *f, const H5B_t *bt, uint8_t *raw,
- void *_key);
-static herr_t H5D_istore_debug_key(FILE *stream, H5F_t *f, hid_t dxpl_id,
- int indent, int fwidth, const void *key,
- const void *udata);
-
-/* inherits B-tree like properties from H5B */
-H5B_class_t H5B_ISTORE[1] = {{
- H5B_ISTORE_ID, /*id */
- sizeof(H5D_istore_key_t), /*sizeof_nkey */
- H5D_istore_get_shared, /*get_shared */
- H5D_istore_new_node, /*new */
- H5D_istore_cmp2, /*cmp2 */
- H5D_istore_cmp3, /*cmp3 */
- H5D_istore_found, /*found */
- H5D_istore_insert, /*insert */
- FALSE, /*follow min branch? */
- FALSE, /*follow max branch? */
- H5D_istore_remove, /*remove */
- H5D_istore_decode_key, /*decode */
- H5D_istore_encode_key, /*encode */
- H5D_istore_debug_key, /*debug */
-}};
-
-/*********************/
-/* Package Variables */
-/*********************/
-
-/*****************************/
-/* Library Private Variables */
-/*****************************/
-
-/*******************/
-/* Local Variables */
-/*******************/
-
-/* Declare a free list to manage H5F_rdcc_ent_t objects */
-H5FL_DEFINE_STATIC(H5D_rdcc_ent_t);
-
-/* Declare a free list to manage the H5F_rdcc_ent_ptr_t sequence information */
-H5FL_SEQ_DEFINE_STATIC(H5D_rdcc_ent_ptr_t);
-
-/* Declare a free list to manage the chunk sequence information */
-H5FL_BLK_DEFINE_STATIC(chunk);
-
-/* Declare a free list to manage the native key offset sequence information */
-H5FL_SEQ_DEFINE_STATIC(size_t);
-
-/* Declare a free list to manage the raw page information */
-H5FL_BLK_DEFINE_STATIC(chunk_page);
-
-/* Declare a free list to manage H5D_istore_sl_ck_t objects */
-H5FL_DEFINE_STATIC(H5D_istore_sl_ck_t);
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_get_shared
- *
- * Purpose: Returns the shared B-tree info for the specified UDATA.
- *
- * Return: Success: Pointer to the raw B-tree page for this dataset
- *
- * Failure: Can't fail
- *
- * Programmer: Quincey Koziol
- * Monday, July 5, 2004
- *
- *-------------------------------------------------------------------------
- */
-/* ARGSUSED */
-static H5RC_t *
-H5D_istore_get_shared(const H5F_t UNUSED *f, const void *_udata)
-{
- const H5D_istore_ud0_t *udata = (const H5D_istore_ud0_t *) _udata;
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_get_shared)
-
- HDassert(udata);
- HDassert(udata->mesg);
- HDassert(udata->mesg->u.chunk.btree_shared);
-
- /* Increment reference count on B-tree info */
- H5RC_INC(udata->mesg->u.chunk.btree_shared);
-
- /* Return the pointer to the ref-count object */
- FUNC_LEAVE_NOAPI(udata->mesg->u.chunk.btree_shared)
-} /* end H5D_istore_get_shared() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_decode_key
- *
- * Purpose: Decodes a raw key into a native key for the B-tree
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Robb Matzke
- * Friday, October 10, 1997
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D_istore_decode_key(const H5F_t UNUSED *f, const H5B_t *bt, const uint8_t *raw, void *_key)
-{
- H5D_istore_key_t *key = (H5D_istore_key_t *) _key;
- H5B_shared_t *shared; /* Pointer to shared B-tree info */
- size_t ndims;
- unsigned u;
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_decode_key)
-
- /* check args */
- assert(f);
- assert(bt);
- shared=H5RC_GET_OBJ(bt->rc_shared);
- HDassert(shared);
- assert(raw);
- assert(key);
- ndims = H5D_ISTORE_NDIMS(shared);
- assert(ndims<=H5O_LAYOUT_NDIMS);
-
- /* decode */
- UINT32DECODE(raw, key->nbytes);
- UINT32DECODE(raw, key->filter_mask);
- for (u=0; u<ndims; u++)
- UINT64DECODE(raw, key->offset[u]);
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5D_istore_decode_key() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_encode_key
- *
- * Purpose: Encode a key from native format to raw format.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Robb Matzke
- * Friday, October 10, 1997
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D_istore_encode_key(const H5F_t UNUSED *f, const H5B_t *bt, uint8_t *raw, void *_key)
-{
- H5D_istore_key_t *key = (H5D_istore_key_t *) _key;
- H5B_shared_t *shared; /* Pointer to shared B-tree info */
- size_t ndims;
- unsigned u;
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_encode_key)
-
- /* check args */
- assert(f);
- assert(bt);
- shared=H5RC_GET_OBJ(bt->rc_shared);
- HDassert(shared);
- assert(raw);
- assert(key);
- ndims = H5D_ISTORE_NDIMS(shared);
- assert(ndims<=H5O_LAYOUT_NDIMS);
-
- /* encode */
- UINT32ENCODE(raw, key->nbytes);
- UINT32ENCODE(raw, key->filter_mask);
- for (u=0; u<ndims; u++)
- UINT64ENCODE(raw, key->offset[u]);
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5D_istore_encode_key() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_debug_key
- *
- * Purpose: Prints a key.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Robb Matzke
- * Thursday, April 16, 1998
- *
- *-------------------------------------------------------------------------
- */
-/* ARGSUSED */
-static herr_t
-H5D_istore_debug_key(FILE *stream, H5F_t UNUSED *f, hid_t UNUSED dxpl_id, int indent, int fwidth,
- const void *_key, const void *_udata)
-{
- const H5D_istore_key_t *key = (const H5D_istore_key_t *)_key;
- const H5D_istore_ud0_t *udata = (const H5D_istore_ud0_t *)_udata;
- unsigned u;
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_debug_key)
-
- HDassert(key);
-
- HDfprintf(stream, "%*s%-*s %Zd bytes\n", indent, "", fwidth, "Chunk size:", key->nbytes);
- HDfprintf(stream, "%*s%-*s 0x%08x\n", indent, "", fwidth, "Filter mask:", key->filter_mask);
- HDfprintf(stream, "%*s%-*s {", indent, "", fwidth, "Logical offset:");
- for(u = 0; u < udata->mesg->u.chunk.ndims; u++)
- HDfprintf(stream, "%s%Hd", u?", ":"", key->offset[u]);
- HDfputs("}\n", stream);
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5D_istore_debug_key() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_cmp2
- *
- * Purpose: Compares two keys sort of like strcmp(). The UDATA pointer
- * is only to supply extra information not carried in the keys
- * (in this case, the dimensionality) and is not compared
- * against the keys.
- *
- * Return: Success: -1 if LT_KEY is less than RT_KEY;
- * 1 if LT_KEY is greater than RT_KEY;
- * 0 if LT_KEY and RT_KEY are equal.
- *
- * Failure: FAIL (same as LT_KEY<RT_KEY)
- *
- * Programmer: Robb Matzke
- * Thursday, November 6, 1997
- *
- *-------------------------------------------------------------------------
- */
-/* ARGSUSED */
-static int
-H5D_istore_cmp2(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, void *_lt_key, void *_udata,
- void *_rt_key)
-{
- H5D_istore_key_t *lt_key = (H5D_istore_key_t *) _lt_key;
- H5D_istore_key_t *rt_key = (H5D_istore_key_t *) _rt_key;
- H5D_istore_ud0_t *udata = (H5D_istore_ud0_t *) _udata;
- int ret_value;
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_cmp2)
-
- HDassert(lt_key);
- HDassert(rt_key);
- HDassert(udata);
- HDassert(udata->mesg->u.chunk.ndims > 0 && udata->mesg->u.chunk.ndims <= H5O_LAYOUT_NDIMS);
-
- /* Compare the offsets but ignore the other fields */
- ret_value = H5V_vector_cmp_u(udata->mesg->u.chunk.ndims, lt_key->offset, rt_key->offset);
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_istore_cmp2() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_cmp3
- *
- * Purpose: Compare the requested datum UDATA with the left and right
- * keys of the B-tree.
- *
- * Return: Success: negative if the min_corner of UDATA is less
- * than the min_corner of LT_KEY.
- *
- * positive if the min_corner of UDATA is
- * greater than or equal the min_corner of
- * RT_KEY.
- *
- * zero otherwise. The min_corner of UDATA is
- * not necessarily contained within the address
- * space represented by LT_KEY, but a key that
- * would describe the UDATA min_corner address
- * would fall lexicographically between LT_KEY
- * and RT_KEY.
- *
- * Failure: FAIL (same as UDATA < LT_KEY)
- *
- * Programmer: Robb Matzke
- * Wednesday, October 8, 1997
- *
- *-------------------------------------------------------------------------
- */
-/* ARGSUSED */
-static int
-H5D_istore_cmp3(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, void *_lt_key, void *_udata,
- void *_rt_key)
-{
- H5D_istore_key_t *lt_key = (H5D_istore_key_t *) _lt_key;
- H5D_istore_key_t *rt_key = (H5D_istore_key_t *) _rt_key;
- H5D_istore_ud0_t *udata = (H5D_istore_ud0_t *) _udata;
- int ret_value = 0;
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_cmp3)
-
- HDassert(lt_key);
- HDassert(rt_key);
- HDassert(udata);
- HDassert(udata->mesg->u.chunk.ndims > 0 && udata->mesg->u.chunk.ndims <= H5O_LAYOUT_NDIMS);
-
- /* Special case for faster checks on 1-D chunks */
- /* (Checking for ndims==2 because last dimension is the datatype size) */
- /* The additional checking for the right key is necessary due to the */
- /* slightly odd way the library initializes the right-most node in the */
- /* indexed storage B-tree... */
- /* (Dump the B-tree with h5debug to look at it) -QAK */
- if(udata->mesg->u.chunk.ndims==2) {
- if(udata->key.offset[0]>rt_key->offset[0])
- ret_value=1;
- else if(udata->key.offset[0]==rt_key->offset[0] &&
- udata->key.offset[1]>=rt_key->offset[1])
- ret_value=1;
- else if(udata->key.offset[0]<lt_key->offset[0])
- ret_value=(-1);
- } /* end if */
- else {
- if (H5V_vector_ge_u(udata->mesg->u.chunk.ndims, udata->key.offset,
- rt_key->offset))
- ret_value = 1;
- else if (H5V_vector_lt_u(udata->mesg->u.chunk.ndims, udata->key.offset,
- lt_key->offset))
- ret_value = -1;
- } /* end else */
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_istore_cmp3() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_new_node
- *
- * Purpose: Adds a new entry to an i-storage B-tree. We can assume that
- * the domain represented by UDATA doesn't intersect the domain
- * already represented by the B-tree.
- *
- * Return: Success: Non-negative. The address of leaf is returned
- * through the ADDR argument. It is also added
- * to the UDATA.
- *
- * Failure: Negative
- *
- * Programmer: Robb Matzke
- * Tuesday, October 14, 1997
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D_istore_new_node(H5F_t *f, hid_t dxpl_id, H5B_ins_t op,
- void *_lt_key, void *_udata, void *_rt_key,
- haddr_t *addr_p/*out*/)
-{
- H5D_istore_key_t *lt_key = (H5D_istore_key_t *) _lt_key;
- H5D_istore_key_t *rt_key = (H5D_istore_key_t *) _rt_key;
- H5D_istore_ud1_t *udata = (H5D_istore_ud1_t *) _udata;
- unsigned u;
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_istore_new_node)
-
- /* check args */
- HDassert(f);
- HDassert(lt_key);
- HDassert(rt_key);
- HDassert(udata);
- HDassert(udata->common.mesg->u.chunk.ndims > 0 && udata->common.mesg->u.chunk.ndims < H5O_LAYOUT_NDIMS);
- HDassert(addr_p);
-
- /* Allocate new storage */
- HDassert(udata->common.key.nbytes > 0);
- H5_CHECK_OVERFLOW(udata->common.key.nbytes ,size_t, hsize_t);
- if(HADDR_UNDEF == (*addr_p = H5MF_alloc(f, H5FD_MEM_DRAW, dxpl_id, (hsize_t)udata->common.key.nbytes)))
- HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "couldn't allocate new file storage")
- udata->addr = *addr_p;
-
- /*
- * The left key describes the storage of the UDATA chunk being
- * inserted into the tree.
- */
- lt_key->nbytes = udata->common.key.nbytes;
- lt_key->filter_mask = udata->common.key.filter_mask;
- for (u=0; u<udata->common.mesg->u.chunk.ndims; u++)
- lt_key->offset[u] = udata->common.key.offset[u];
-
- /*
- * The right key might already be present. If not, then add a zero-width
- * chunk.
- */
- if (H5B_INS_LEFT != op) {
- rt_key->nbytes = 0;
- rt_key->filter_mask = 0;
- for (u=0; u<udata->common.mesg->u.chunk.ndims; u++) {
- HDassert(udata->common.key.offset[u]+udata->common.mesg->u.chunk.dim[u] >
- udata->common.key.offset[u]);
- rt_key->offset[u] = udata->common.key.offset[u] + udata->common.mesg->u.chunk.dim[u];
- }
- }
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_istore_new_node() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_found
- *
- * Purpose: This function is called when the B-tree search engine has
- * found the leaf entry that points to a chunk of storage that
- * contains the beginning of the logical address space
- * represented by UDATA. The LT_KEY is the left key (the one
- * that describes the chunk) and RT_KEY is the right key (the
- * one that describes the next or last chunk).
- *
- * Note: It's possible that the chunk isn't really found. For
- * instance, in a sparse dataset the requested chunk might fall
- * between two stored chunks in which case this function is
- * called with the maximum stored chunk indices less than the
- * requested chunk indices.
- *
- * Return: Non-negative on success with information about the chunk
- * returned through the UDATA argument. Negative on failure.
- *
- * Programmer: Robb Matzke
- * Thursday, October 9, 1997
- *
- *-------------------------------------------------------------------------
- */
-/* ARGSUSED */
-static herr_t
-H5D_istore_found(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, haddr_t addr, const void *_lt_key,
- void *_udata)
-{
- H5D_istore_ud1_t *udata = (H5D_istore_ud1_t *) _udata;
- const H5D_istore_key_t *lt_key = (const H5D_istore_key_t *) _lt_key;
- unsigned u;
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_found)
-
- /* Check arguments */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
- HDassert(udata);
- HDassert(lt_key);
-
- /* Is this *really* the requested chunk? */
- for(u = 0; u < udata->common.mesg->u.chunk.ndims; u++)
- if(udata->common.key.offset[u] >= lt_key->offset[u] + udata->common.mesg->u.chunk.dim[u])
- HGOTO_DONE(FAIL)
-
- /* Initialize return values */
- udata->addr = addr;
- udata->common.key.nbytes = lt_key->nbytes;
- udata->common.key.filter_mask = lt_key->filter_mask;
- HDassert(lt_key->nbytes>0);
- for(u = 0; u < udata->common.mesg->u.chunk.ndims; u++)
- udata->common.key.offset[u] = lt_key->offset[u];
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_istore_found() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_insert
- *
- * Purpose: This function is called when the B-tree insert engine finds
- * the node to use to insert new data. The UDATA argument
- * points to a struct that describes the logical addresses being
- * added to the file. This function allocates space for the
- * data and returns information through UDATA describing a
- * file chunk to receive (part of) the data.
- *
- * The LT_KEY is always the key describing the chunk of file
- * memory at address ADDR. On entry, UDATA describes the logical
- * addresses for which storage is being requested (through the
- * `offset' and `size' fields). On return, UDATA describes the
- * logical addresses contained in a chunk on disk.
- *
- * Return: Success: An insertion command for the caller, one of
- * the H5B_INS_* constants. The address of the
- * new chunk is returned through the NEW_NODE
- * argument.
- *
- * Failure: H5B_INS_ERROR
- *
- * Programmer: Robb Matzke
- * Thursday, October 9, 1997
- *
- *-------------------------------------------------------------------------
- */
-/* ARGSUSED */
-static H5B_ins_t
-H5D_istore_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key,
- hbool_t *lt_key_changed,
- void *_md_key, void *_udata, void *_rt_key,
- hbool_t UNUSED *rt_key_changed,
- haddr_t *new_node_p/*out*/)
-{
- H5D_istore_key_t *lt_key = (H5D_istore_key_t *) _lt_key;
- H5D_istore_key_t *md_key = (H5D_istore_key_t *) _md_key;
- H5D_istore_key_t *rt_key = (H5D_istore_key_t *) _rt_key;
- H5D_istore_ud1_t *udata = (H5D_istore_ud1_t *) _udata;
- int cmp;
- unsigned u;
- H5B_ins_t ret_value;
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_istore_insert)
-
- /* check args */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
- HDassert(lt_key);
- HDassert(lt_key_changed);
- HDassert(md_key);
- HDassert(udata);
- HDassert(rt_key);
- HDassert(new_node_p);
-
- cmp = H5D_istore_cmp3(f, dxpl_id, lt_key, udata, rt_key);
- HDassert(cmp <= 0);
-
- if (cmp < 0) {
- /* Negative indices not supported yet */
- HGOTO_ERROR(H5E_STORAGE, H5E_UNSUPPORTED, H5B_INS_ERROR, "internal error")
-
- } else if (H5V_vector_eq_u (udata->common.mesg->u.chunk.ndims,
- udata->common.key.offset, lt_key->offset) &&
- lt_key->nbytes>0) {
- /*
- * Already exists. If the new size is not the same as the old size
- * then we should reallocate storage.
- */
- if (lt_key->nbytes != udata->common.key.nbytes) {
-/* Currently, the old chunk data is "thrown away" after the space is reallocated,
- * so avoid data copy in H5MF_realloc() call by just free'ing the space and
- * allocating new space.
- *
- * This should keep the file smaller also, by freeing the space and then
- * allocating new space, instead of vice versa (in H5MF_realloc).
- *
- * QAK - 11/19/2002
- */
-#ifdef OLD_WAY
- if(HADDR_UNDEF == (*new_node_p = H5MF_realloc(f, H5FD_MEM_DRAW, addr,
- (hsize_t)lt_key->nbytes, (hsize_t)udata->common.key.nbytes)))
- HGOTO_ERROR(H5E_STORAGE, H5E_NOSPACE, H5B_INS_ERROR, "unable to reallocate chunk storage")
-#else /* OLD_WAY */
- H5_CHECK_OVERFLOW( lt_key->nbytes ,size_t, hsize_t);
- if(H5MF_xfree(f, H5FD_MEM_DRAW, dxpl_id, addr, (hsize_t)lt_key->nbytes)<0)
- HGOTO_ERROR(H5E_STORAGE, H5E_CANTFREE, H5B_INS_ERROR, "unable to free chunk")
- H5_CHECK_OVERFLOW(udata->common.key.nbytes ,size_t, hsize_t);
- if(HADDR_UNDEF == (*new_node_p = H5MF_alloc(f, H5FD_MEM_DRAW, dxpl_id, (hsize_t)udata->common.key.nbytes)))
- HGOTO_ERROR(H5E_STORAGE, H5E_NOSPACE, H5B_INS_ERROR, "unable to reallocate chunk")
-#endif /* OLD_WAY */
- lt_key->nbytes = udata->common.key.nbytes;
- lt_key->filter_mask = udata->common.key.filter_mask;
- *lt_key_changed = TRUE;
- udata->addr = *new_node_p;
- ret_value = H5B_INS_CHANGE;
- } else {
- udata->addr = addr;
- ret_value = H5B_INS_NOOP;
- }
-
- } else if (H5V_hyper_disjointp(udata->common.mesg->u.chunk.ndims,
- lt_key->offset, udata->common.mesg->u.chunk.dim,
- udata->common.key.offset, udata->common.mesg->u.chunk.dim)) {
- HDassert(H5V_hyper_disjointp(udata->common.mesg->u.chunk.ndims,
- rt_key->offset, udata->common.mesg->u.chunk.dim,
- udata->common.key.offset, udata->common.mesg->u.chunk.dim));
- /*
- * Split this node, inserting the new new node to the right of the
- * current node. The MD_KEY is where the split occurs.
- */
- md_key->nbytes = udata->common.key.nbytes;
- md_key->filter_mask = udata->common.key.filter_mask;
- for(u = 0; u < udata->common.mesg->u.chunk.ndims; u++) {
- HDassert(0 == udata->common.key.offset[u] % udata->common.mesg->u.chunk.dim[u]);
- md_key->offset[u] = udata->common.key.offset[u];
- }
-
- /*
- * Allocate storage for the new chunk
- */
- H5_CHECK_OVERFLOW(udata->common.key.nbytes ,size_t, hsize_t);
- if(HADDR_UNDEF == (*new_node_p = H5MF_alloc(f, H5FD_MEM_DRAW, dxpl_id, (hsize_t)udata->common.key.nbytes)))
- HGOTO_ERROR(H5E_STORAGE, H5E_NOSPACE, H5B_INS_ERROR, "file allocation failed")
- udata->addr = *new_node_p;
- ret_value = H5B_INS_RIGHT;
-
- } else {
- HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, H5B_INS_ERROR, "internal error")
- }
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_istore_insert() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_iter_allocated
- *
- * Purpose: Simply counts the number of chunks for a dataset.
- *
- * Return: Success: Non-negative
- *
- * Failure: Negative
- *
- * Programmer: Robb Matzke
- * Wednesday, April 21, 1999
- *
- *-------------------------------------------------------------------------
- */
-/* ARGSUSED */
-static int
-H5D_istore_iter_allocated (H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const void *_lt_key, haddr_t UNUSED addr,
- const void UNUSED *_rt_key, void *_udata)
-{
- H5D_istore_it_ud1_t *udata = (H5D_istore_it_ud1_t *)_udata;
- const H5D_istore_key_t *lt_key = (const H5D_istore_key_t *)_lt_key;
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_iter_allocated)
-
- udata->total_storage += lt_key->nbytes;
-
- FUNC_LEAVE_NOAPI(H5_ITER_CONT)
-} /* H5D_istore_iter_allocated() */
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_iter_chunkmap
- *
- * Purpose: obtain chunk address and the corresponding index
- *
- * Return: Success: Non-negative
- *
- * Failure: Negative
- *
- * Programmer: Kent Yang
- * Tuesday, November 15, 2005
- *
- *-------------------------------------------------------------------------
- */
-/* ARGSUSED */
-static int
-H5D_istore_iter_chunkmap (H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const void *_lt_key, haddr_t addr,
- const void UNUSED *_rt_key, void *_udata)
-{
- H5D_istore_it_ud5_t *udata = (H5D_istore_it_ud5_t *)_udata;
- const H5D_istore_key_t *lt_key = (const H5D_istore_key_t *)_lt_key;
- unsigned rank;
- hsize_t chunk_index;
- int ret_value = H5_ITER_CONT; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_istore_iter_chunkmap)
-
- rank = udata->common.mesg->u.chunk.ndims - 1;
-
- if(H5V_chunk_index(rank, lt_key->offset, udata->common.mesg->u.chunk.dim, udata->down_chunks, &chunk_index) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index")
-
- udata->chunk_addr[chunk_index] = addr;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5D_istore_iter_allocated() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_iter_dump
- *
- * Purpose: If the UDATA.STREAM member is non-null then debugging
- * information is written to that stream.
- *
- * Return: Success: Non-negative
- *
- * Failure: Negative
- *
- * Programmer: Robb Matzke
- * Wednesday, April 21, 1999
- *
- *-------------------------------------------------------------------------
- */
-/* ARGSUSED */
-static int
-H5D_istore_iter_dump (H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const void *_lt_key, haddr_t UNUSED addr,
- const void UNUSED *_rt_key, void *_udata)
-{
- H5D_istore_it_ud2_t *udata = (H5D_istore_it_ud2_t *)_udata;
- const H5D_istore_key_t *lt_key = (const H5D_istore_key_t *)_lt_key;
- unsigned u;
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_iter_dump)
-
- if(udata->stream) {
- if(!udata->header_displayed) {
- HDfprintf(udata->stream, " Flags Bytes Address Logical Offset\n");
- HDfprintf(udata->stream, " ========== ======== ========== ==============================\n");
-
- /* Set flag that the headers has been printed */
- udata->header_displayed = TRUE;
- } /* end if */
- HDfprintf(udata->stream, " 0x%08x %8Zu %10a [", lt_key->filter_mask, lt_key->nbytes, addr);
- for(u = 0; u < udata->common.mesg->u.chunk.ndims; u++)
- HDfprintf(udata->stream, "%s%Hd", (u ? ", " : ""), lt_key->offset[u]);
- HDfputs("]\n", udata->stream);
- } /* end if */
-
- FUNC_LEAVE_NOAPI(H5_ITER_CONT)
-} /* H5D_istore_iter_dump() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_iter_copy
- *
- * Purpose: copy chunked raw data from source file and insert to the
- * B-tree node in the destination file
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Peter Cao
- * August 20, 2005
- *
- *-------------------------------------------------------------------------
- */
-static int
-H5D_istore_iter_copy(H5F_t *f_src, hid_t dxpl_id, const void *_lt_key,
- haddr_t addr_src, const void UNUSED *_rt_key, void *_udata)
-{
- H5D_istore_it_ud4_t *udata = (H5D_istore_it_ud4_t *)_udata;
- const H5D_istore_key_t *lt_key = (const H5D_istore_key_t *)_lt_key;
- H5D_istore_ud1_t udata_dst; /* User data about new destination chunk */
- hbool_t is_vlen = FALSE;
- hbool_t fix_ref = FALSE;
-
- /* General information about chunk copy */
- void *bkg = udata->bkg;
- void *buf = udata->buf;
- size_t buf_size = udata->buf_size;
- H5O_pline_t *pline = udata->pline;
-
- /* needed for commpressed variable length data */
- hbool_t is_compressed = FALSE;
- H5Z_EDC_t edc_read = H5Z_NO_EDC;
- size_t nbytes = lt_key->nbytes;
- H5Z_cb_t cb_struct;
-
- int ret_value = H5_ITER_CONT; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_istore_iter_copy)
-
- /* Check parameter for type conversion */
- if(udata->do_convert) {
- if(H5T_detect_class(udata->dt_src, H5T_VLEN) > 0)
- is_vlen = TRUE;
- else if((H5T_get_class(udata->dt_src, FALSE) == H5T_REFERENCE) && (udata->file_src != udata->file_dst))
- fix_ref = TRUE;
- else
- HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "unable to copy dataset elements")
- } /* end if */
-
- /* Check for filtered chunks */
- if(pline && pline->nused) {
- is_compressed = TRUE;
- cb_struct.func = NULL; /* no callback function when failed */
- } /* end if */
-
- /* Resize the buf if it is too small to hold the data */
- if(nbytes > buf_size) {
- void *new_buf; /* New buffer for data */
-
- /* Re-allocate memory for copying the chunk */
- if(NULL == (new_buf = H5MM_realloc(udata->buf, nbytes)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5_ITER_ERROR, "memory allocation failed for raw data chunk")
- udata->buf = new_buf;
- if(udata->bkg) {
- if(NULL == (new_buf = H5MM_realloc(udata->bkg, nbytes)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5_ITER_ERROR, "memory allocation failed for raw data chunk")
- udata->bkg = new_buf;
- if(!udata->cpy_info->expand_ref)
- HDmemset((uint8_t *)udata->bkg + buf_size, 0, (size_t)(nbytes - buf_size));
-
- bkg = udata->bkg;
- } /* end if */
-
- buf = udata->buf;
- udata->buf_size = buf_size = nbytes;
- } /* end if */
-
- /* read chunk data from the source file */
- if(H5F_block_read(f_src, H5FD_MEM_DRAW, addr_src, nbytes, dxpl_id, buf) < 0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, H5_ITER_ERROR, "unable to read raw data chunk")
-
- /* Need to uncompress variable-length & reference data elements */
- if(is_compressed && (is_vlen || fix_ref)) {
- unsigned filter_mask = lt_key->filter_mask;
-
- if(H5Z_pipeline(pline, H5Z_FLAG_REVERSE, &filter_mask, edc_read, cb_struct, &nbytes, &buf_size, &buf) < 0)
- HGOTO_ERROR(H5E_PLINE, H5E_CANTFILTER, H5_ITER_ERROR, "data pipeline read failed")
- } /* end if */
-
- /* Perform datatype conversion, if necessary */
- if(is_vlen) {
- H5T_path_t *tpath_src_mem = udata->tpath_src_mem;
- H5T_path_t *tpath_mem_dst = udata->tpath_mem_dst;
- H5S_t *buf_space = udata->buf_space;
- hid_t tid_src = udata->tid_src;
- hid_t tid_dst = udata->tid_dst;
- hid_t tid_mem = udata->tid_mem;
- size_t nelmts = udata->nelmts;
- void *reclaim_buf = udata->reclaim_buf;
- size_t reclaim_buf_size = udata->reclaim_buf_size;
-
- /* Convert from source file to memory */
- if(H5T_convert(tpath_src_mem, tid_src, tid_mem, nelmts, (size_t)0, (size_t)0, buf, NULL, dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5_ITER_ERROR, "datatype conversion failed")
-
- /* Copy into another buffer, to reclaim memory later */
- HDmemcpy(reclaim_buf, buf, reclaim_buf_size);
-
- /* Set background buffer to all zeros */
- HDmemset(bkg, 0, buf_size);
-
- /* Convert from memory to destination file */
- if(H5T_convert(tpath_mem_dst, tid_mem, tid_dst, nelmts, (size_t)0, (size_t)0, buf, bkg, dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5_ITER_ERROR, "datatype conversion failed")
-
- /* Reclaim space from variable length data */
- if(H5D_vlen_reclaim(tid_mem, buf_space, H5P_DATASET_XFER_DEFAULT, reclaim_buf) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_BADITER, H5_ITER_ERROR, "unable to reclaim variable-length data")
- } /* end if */
- else if(fix_ref) {
- /* Check for expanding references */
- /* (background buffer has already been zeroed out, if not expanding) */
- if(udata->cpy_info->expand_ref) {
- size_t ref_count;
-
- /* Determine # of reference elements to copy */
- ref_count = nbytes / H5T_get_size(udata->dt_src);
-
- /* Copy the reference elements */
- if(H5O_copy_expand_ref(f_src, buf, dxpl_id, udata->file_dst, bkg, ref_count, H5T_get_ref_type(udata->dt_src), udata->cpy_info) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "unable to copy reference attribute")
- } /* end if */
-
- /* After fix ref, copy the new reference elements to the buffer to write out */
- HDmemcpy(buf, bkg, buf_size);
- } /* end if */
-
- /* Copy source chunk callback information for insertion */
- HDmemset(&udata_dst, 0, sizeof(udata_dst));
- HDmemcpy(&(udata_dst.common.key), lt_key, sizeof(H5D_istore_key_t));
- udata_dst.common.mesg = udata->common.mesg; /* Share this pointer for a short while */
-
- /* Need to compress variable-length & reference data elements before writing to file */
- if(is_compressed && (is_vlen || fix_ref) ) {
- if(H5Z_pipeline(pline, 0, &(udata_dst.common.key.filter_mask), edc_read,
- cb_struct, &nbytes, &buf_size, &buf) < 0)
- HGOTO_ERROR(H5E_PLINE, H5E_CANTFILTER, H5_ITER_ERROR, "output pipeline failed")
- udata_dst.common.key.nbytes = nbytes;
- udata->buf = buf;
- udata->buf_size = buf_size;
- } /* end if */
-
- /* Insert chunk into the destination Btree */
- if(H5B_insert(udata->file_dst, dxpl_id, H5B_ISTORE, udata->addr_dst, &udata_dst) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, H5_ITER_ERROR, "unable to allocate chunk")
-
- /* Write chunk data to destination file */
- HDassert(H5F_addr_defined(udata_dst.addr));
- if(H5F_block_write(udata->file_dst, H5FD_MEM_DRAW, udata_dst.addr, nbytes, dxpl_id, buf) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, H5_ITER_ERROR, "unable to write raw data to file")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_istore_iter_copy() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_init
- *
- * Purpose: Initialize the raw data chunk cache for a dataset. This is
- * called when the dataset is initialized.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Robb Matzke
- * Monday, May 18, 1998
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5D_istore_init (const H5F_t *f, const H5D_t *dset)
-{
- H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk);
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5D_istore_init, FAIL)
-
- if (H5F_RDCC_NBYTES(f)>0 && H5F_RDCC_NELMTS(f)>0) {
- rdcc->nbytes=H5F_RDCC_NBYTES(f);
- rdcc->nslots = H5F_RDCC_NELMTS(f);
- rdcc->slot = H5FL_SEQ_CALLOC (H5D_rdcc_ent_ptr_t,rdcc->nslots);
- if (NULL==rdcc->slot)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
- } /* end if */
-
- /* Allocate the shared structure */
- if(H5D_istore_shared_create(f, &dset->shared->layout)<0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create wrapper for shared B-tree info")
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_istore_init() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_flush_entry
- *
- * Purpose: Writes a chunk to disk. If RESET is non-zero then the
- * entry is cleared -- it's slightly faster to flush a chunk if
- * the RESET flag is turned on because it results in one fewer
- * memory copy.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Robb Matzke
- * Thursday, May 21, 1998
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D_istore_flush_entry(const H5D_io_info_t *io_info, H5D_rdcc_ent_t *ent, hbool_t reset)
-{
- herr_t ret_value=SUCCEED; /*return value */
- unsigned u; /*counters */
- void *buf=NULL; /*temporary buffer */
- size_t alloc; /*bytes allocated for BUF */
- hbool_t point_of_no_return = FALSE;
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_istore_flush_entry)
-
- assert(io_info);
- assert(io_info->dset);
- assert(ent);
- assert(!ent->locked);
-
- buf = ent->chunk;
- if (ent->dirty) {
- H5D_istore_ud1_t udata; /*pass through B-tree */
-
- udata.common.mesg = &io_info->dset->shared->layout;
- udata.common.key.filter_mask = 0;
- udata.addr = HADDR_UNDEF;
- udata.common.key.nbytes = ent->chunk_size;
- for (u=0; u<io_info->dset->shared->layout.u.chunk.ndims; u++)
- udata.common.key.offset[u] = ent->offset[u];
- alloc = ent->alloc_size;
-
- /* Should the chunk be filtered before writing it to disk? */
- if (io_info->dset->shared->dcpl_cache.pline.nused) {
- if (!reset) {
- /*
- * Copy the chunk to a new buffer before running it through
- * the pipeline because we'll want to save the original buffer
- * for later.
- */
- alloc = ent->chunk_size;
- if (NULL==(buf = H5MM_malloc(alloc)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for pipeline")
- HDmemcpy(buf, ent->chunk, ent->chunk_size);
- } else {
- /*
- * If we are reseting and something goes wrong after this
- * point then it's too late to recover because we may have
- * destroyed the original data by calling H5Z_pipeline().
- * The only safe option is to continue with the reset
- * even if we can't write the data to disk.
- */
- point_of_no_return = TRUE;
- ent->chunk = NULL;
- }
- if (H5Z_pipeline(&(io_info->dset->shared->dcpl_cache.pline), 0, &(udata.common.key.filter_mask), io_info->dxpl_cache->err_detect,
- io_info->dxpl_cache->filter_cb, &(udata.common.key.nbytes), &alloc, &buf)<0)
- HGOTO_ERROR(H5E_PLINE, H5E_CANTFILTER, FAIL, "output pipeline failed")
- }
-
- /*
- * Create the chunk it if it doesn't exist, or reallocate the chunk if
- * its size changed. Then write the data into the file.
- */
- if(H5B_insert(io_info->dset->oloc.file, io_info->dxpl_id, H5B_ISTORE, io_info->dset->shared->layout.u.chunk.addr, &udata)<0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to allocate chunk")
- if(H5F_block_write(io_info->dset->oloc.file, H5FD_MEM_DRAW, udata.addr, udata.common.key.nbytes, io_info->dxpl_id, buf) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write raw data to file")
-
- /* Mark cache entry as clean */
- ent->dirty = FALSE;
-#ifdef H5D_ISTORE_DEBUG
- io_info->dset->shared->cache.chunk.nflushes++;
-#endif /* H5D_ISTORE_DEBUG */
- } /* end if */
-
- /* Reset, but do not free or removed from list */
- if (reset) {
- point_of_no_return = FALSE;
- if(buf==ent->chunk)
- buf = NULL;
- if(ent->chunk!=NULL)
- ent->chunk = H5D_istore_chunk_xfree(ent->chunk,&(io_info->dset->shared->dcpl_cache.pline));
- } /* end if */
-
-done:
- /* Free the temp buffer only if it's different than the entry chunk */
- if (buf!=ent->chunk)
- H5MM_xfree(buf);
-
- /*
- * If we reached the point of no return then we have no choice but to
- * reset the entry. This can only happen if RESET is true but the
- * output pipeline failed. Do not free the entry or remove it from the
- * list.
- */
- if (ret_value<0 && point_of_no_return) {
- if(ent->chunk)
- ent->chunk = H5D_istore_chunk_xfree(ent->chunk,&(io_info->dset->shared->dcpl_cache.pline));
- } /* end if */
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_istore_flush_entry() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_preempt
- *
- * Purpose: Preempts the specified entry from the cache, flushing it to
- * disk if necessary.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Robb Matzke
- * Thursday, May 21, 1998
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D_istore_preempt(const H5D_io_info_t *io_info, H5D_rdcc_ent_t * ent, hbool_t flush)
-{
- H5D_rdcc_t *rdcc = &(io_info->dset->shared->cache.chunk);
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_istore_preempt)
-
- assert(io_info);
- assert(ent);
- assert(!ent->locked);
- assert(ent->idx < rdcc->nslots);
-
- if(flush) {
- /* Flush */
- if(H5D_istore_flush_entry(io_info, ent, TRUE) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "cannot flush indexed storage buffer")
- }
- else {
- /* Don't flush, just free chunk */
- if(ent->chunk != NULL)
- ent->chunk = H5D_istore_chunk_xfree(ent->chunk,&(io_info->dset->shared->dcpl_cache.pline));
- }
-
- /* Unlink from list */
- if(ent->prev)
- ent->prev->next = ent->next;
- else
- rdcc->head = ent->next;
- if(ent->next)
- ent->next->prev = ent->prev;
- else
- rdcc->tail = ent->prev;
- ent->prev = ent->next = NULL;
-
- /* Remove from cache */
- rdcc->slot[ent->idx] = NULL;
- ent->idx = UINT_MAX;
- rdcc->nbytes -= ent->chunk_size;
- --rdcc->nused;
-
- /* Free */
- H5FL_FREE(H5D_rdcc_ent_t, ent);
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_istore_preempt() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_flush
- *
- * Purpose: Writes all dirty chunks to disk and optionally preempts them
- * from the cache.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Robb Matzke
- * Thursday, May 21, 1998
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5D_istore_flush(H5D_t *dset, hid_t dxpl_id, unsigned flags)
-{
- H5D_io_info_t io_info; /* Temporary I/O info object */
- H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */
- H5D_dxpl_cache_t *dxpl_cache = &_dxpl_cache; /* Data transfer property cache */
- H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk);
- unsigned nerrors = 0;
- H5D_rdcc_ent_t *ent, *next;
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5D_istore_flush, FAIL)
-
- /* Fill the DXPL cache values for later use */
- if(H5D_get_dxpl_cache(dxpl_id, &dxpl_cache) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache")
-
- /* Construct dataset I/O info */
- H5D_BUILD_IO_INFO(&io_info, dset, dxpl_cache, dxpl_id, NULL);
-
- /* Loop over all entries in the chunk cache */
- for(ent = rdcc->head; ent; ent = next) {
- next = ent->next;
- if((flags & H5F_FLUSH_INVALIDATE)) {
- if(H5D_istore_preempt(&io_info, ent, TRUE) < 0)
- nerrors++;
- } else {
- if(H5D_istore_flush_entry(&io_info, ent, FALSE) < 0)
- nerrors++;
- }
- } /* end for */
- if(nerrors)
- HGOTO_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "unable to flush one or more raw data chunks")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_istore_flush() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_dest
- *
- * Purpose: Destroy the entire chunk cache by flushing dirty entries,
- * preempting all entries, and freeing the cache itself.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Robb Matzke
- * Thursday, May 21, 1998
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5D_istore_dest (H5D_t *dset, hid_t dxpl_id)
-{
- H5D_io_info_t io_info; /* Temporary I/O info object */
- H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */
- H5D_dxpl_cache_t *dxpl_cache=&_dxpl_cache; /* Data transfer property cache */
- H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk);
- int nerrors=0;
- H5D_rdcc_ent_t *ent=NULL, *next=NULL;
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5D_istore_dest, FAIL)
-
- assert(dset);
-
- /* Fill the DXPL cache values for later use */
- if (H5D_get_dxpl_cache(dxpl_id,&dxpl_cache)<0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache")
-
- /* Construct dataset I/O info */
- H5D_BUILD_IO_INFO(&io_info,dset,dxpl_cache,dxpl_id,NULL);
-
- /* Flush all the cached chunks */
- for (ent=rdcc->head; ent; ent=next) {
-#ifdef H5D_ISTORE_DEBUG
- HDfputc('c', stderr);
- HDfflush(stderr);
-#endif
- next = ent->next;
- if (H5D_istore_preempt(&io_info, ent, TRUE )<0)
- nerrors++;
- }
- if (nerrors)
- HGOTO_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "unable to flush one or more raw data chunks")
-
- if(rdcc->slot)
- H5FL_SEQ_FREE (H5D_rdcc_ent_ptr_t,rdcc->slot);
- HDmemset (rdcc, 0, sizeof(H5D_rdcc_t));
-
- /* Free the raw B-tree node buffer */
- if(dset->shared->layout.u.chunk.btree_shared==NULL)
- HGOTO_ERROR(H5E_IO, H5E_CANTFREE, FAIL, "ref-counted page nil")
- if(H5RC_DEC(dset->shared->layout.u.chunk.btree_shared)<0)
- HGOTO_ERROR(H5E_IO, H5E_CANTFREE, FAIL, "unable to decrement ref-counted page")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_istore_dest() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_shared_create
- *
- * Purpose: Create & initialize B-tree shared info
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Monday, September 27, 2004
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D_istore_shared_create (const H5F_t *f, H5O_layout_t *layout)
-{
- H5B_shared_t *shared; /* Shared B-tree node info */
- size_t u; /* Local index variable */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_istore_shared_create)
-
- /* Allocate space for the shared structure */
- if(NULL==(shared=H5FL_MALLOC(H5B_shared_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for shared B-tree info")
-
- /* Set up the "global" information for this file's groups */
- shared->type= H5B_ISTORE;
- shared->two_k=2*H5F_KVALUE(f,H5B_ISTORE);
- shared->sizeof_rkey = 4 + /*storage size */
- 4 + /*filter mask */
- layout->u.chunk.ndims*8; /*dimension indices */
- assert(shared->sizeof_rkey);
- shared->sizeof_rnode = H5B_nodesize(f, shared, &shared->sizeof_keys);
- assert(shared->sizeof_rnode);
- if(NULL==(shared->page=H5FL_BLK_MALLOC(chunk_page,shared->sizeof_rnode)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree page")
-#ifdef H5_CLEAR_MEMORY
-HDmemset(shared->page, 0, shared->sizeof_rnode);
-#endif /* H5_CLEAR_MEMORY */
- if(NULL==(shared->nkey=H5FL_SEQ_MALLOC(size_t,(size_t)(2*H5F_KVALUE(f,H5B_ISTORE)+1))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree page")
-
- /* Initialize the offsets into the native key buffer */
- for(u=0; u<(2*H5F_KVALUE(f,H5B_ISTORE)+1); u++)
- shared->nkey[u]=u*H5B_ISTORE[0].sizeof_nkey;
-
- /* Make shared B-tree info reference counted */
- if(NULL==(layout->u.chunk.btree_shared=H5RC_create(shared,H5D_istore_shared_free)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create ref-count wrapper for shared B-tree info")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_istore_shared_create() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_shared_free
- *
- * Purpose: Free B-tree shared info
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Thursday, July 8, 2004
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D_istore_shared_free (void *_shared)
-{
- H5B_shared_t *shared = (H5B_shared_t *)_shared;
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_shared_free)
-
- /* Free the raw B-tree node buffer */
- H5FL_BLK_FREE(chunk_page,shared->page);
-
- /* Free the B-tree native key offsets buffer */
- H5FL_SEQ_FREE(size_t,shared->nkey);
-
- /* Free the shared B-tree info */
- H5FL_FREE(H5B_shared_t,shared);
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5D_istore_shared_free() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_prune
- *
- * Purpose: Prune the cache by preempting some things until the cache has
- * room for something which is SIZE bytes. Only unlocked
- * entries are considered for preemption.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Robb Matzke
- * Thursday, May 21, 1998
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D_istore_prune (const H5D_io_info_t *io_info, size_t size)
-{
- int i, j, nerrors=0;
- const H5D_rdcc_t *rdcc = &(io_info->dset->shared->cache.chunk);
- size_t total = rdcc->nbytes;
- const int nmeth=2; /*number of methods */
- int w[1]; /*weighting as an interval */
- H5D_rdcc_ent_t *p[2], *cur; /*list pointers */
- H5D_rdcc_ent_t *n[2]; /*list next pointers */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_istore_prune)
-
- /*
- * Preemption is accomplished by having multiple pointers (currently two)
- * slide down the list beginning at the head. Pointer p(N+1) will start
- * traversing the list when pointer pN reaches wN percent of the original
- * list. In other words, preemption method N gets to consider entries in
- * approximate least recently used order w0 percent before method N+1
- * where 100% means tha method N will run to completion before method N+1
- * begins. The pointers participating in the list traversal are each
- * given a chance at preemption before any of the pointers are advanced.
- */
- w[0] = (int)(rdcc->nused * H5F_RDCC_W0(io_info->dset->oloc.file));
- p[0] = rdcc->head;
- p[1] = NULL;
-
- while ((p[0] || p[1]) && rdcc->nbytes+size>total) {
-
- /* Introduce new pointers */
- for (i=0; i<nmeth-1; i++)
- if (0==w[i])
- p[i+1] = rdcc->head;
-
- /* Compute next value for each pointer */
- for (i=0; i<nmeth; i++)
- n[i] = p[i] ? p[i]->next : NULL;
-
- /* Give each method a chance */
- for (i=0; i<nmeth && rdcc->nbytes+size>total; i++) {
- if (0==i && p[0] && !p[0]->locked &&
- ((0==p[0]->rd_count && 0==p[0]->wr_count) ||
- (0==p[0]->rd_count && p[0]->chunk_size==p[0]->wr_count) ||
- (p[0]->chunk_size==p[0]->rd_count && 0==p[0]->wr_count))) {
- /*
- * Method 0: Preempt entries that have been completely written
- * and/or completely read but not entries that are partially
- * written or partially read.
- */
- cur = p[0];
-#ifdef H5D_ISTORE_DEBUG
- HDputc('.', stderr);
- HDfflush(stderr);
-#endif
-
- } else if (1==i && p[1] && !p[1]->locked) {
- /*
- * Method 1: Preempt the entry without regard to
- * considerations other than being locked. This is the last
- * resort preemption.
- */
- cur = p[1];
-#ifdef H5D_ISTORE_DEBUG
- HDputc(':', stderr);
- HDfflush(stderr);
-#endif
-
- } else {
- /* Nothing to preempt at this point */
- cur= NULL;
- }
-
- if (cur) {
- for (j=0; j<nmeth; j++) {
- if (p[j]==cur)
- p[j] = NULL;
- if (n[j]==cur)
- n[j] = cur->next;
- }
- if (H5D_istore_preempt(io_info, cur, TRUE)<0)
- nerrors++;
- }
- }
-
- /* Advance pointers */
- for (i=0; i<nmeth; i++)
- p[i] = n[i];
- for (i=0; i<nmeth-1; i++)
- w[i] -= 1;
- }
-
- if (nerrors)
- HGOTO_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "unable to preempt one or more raw data cache entry")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_istore_prune() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_lock
- *
- * Purpose: Return a pointer to a dataset chunk. The pointer points
- * directly into the chunk cache and should not be freed
- * by the caller but will be valid until it is unlocked. The
- * input value IDX_HINT is used to speed up cache lookups and
- * it's output value should be given to H5F_istore_unlock().
- * IDX_HINT is ignored if it is out of range, and if it points
- * to the wrong entry then we fall back to the normal search
- * method.
- *
- * If RELAX is non-zero and the chunk isn't in the cache then
- * don't try to read it from the file, but just allocate an
- * uninitialized buffer to hold the result. This is intended
- * for output functions that are about to overwrite the entire
- * chunk.
- *
- * Return: Success: Ptr to a file chunk.
- *
- * Failure: NULL
- *
- * Programmer: Robb Matzke
- * Thursday, May 21, 1998
- *
- *-------------------------------------------------------------------------
- */
-void *
-H5D_istore_lock(const H5D_io_info_t *io_info, H5D_istore_ud1_t *udata,
- hbool_t relax, unsigned *idx_hint/*in,out*/)
-{
- H5D_t *dset = io_info->dset; /* Local pointer to the dataset info */
- const H5O_pline_t *pline = &(dset->shared->dcpl_cache.pline); /* I/O pipeline info */
- const H5O_layout_t *layout = &(dset->shared->layout); /* Dataset layout */
- const H5O_fill_t *fill = &(dset->shared->dcpl_cache.fill); /* Fill value info */
- H5D_fill_buf_info_t fb_info; /* Dataset's fill buffer info */
- hbool_t fb_info_init = FALSE; /* Whether the fill value buffer has been initialized */
- H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk); /*raw data chunk cache*/
- H5D_rdcc_ent_t *ent = NULL; /*cache entry */
- unsigned idx = 0; /*hash index number */
- hbool_t found = FALSE; /*already in cache? */
- size_t chunk_size; /*size of a chunk */
- void *chunk = NULL; /*the file chunk */
- unsigned u; /*counters */
- void *ret_value; /*return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_istore_lock)
-
- HDassert(io_info);
- HDassert(dset);
- HDassert(io_info->dxpl_cache);
- HDassert(io_info->store);
- HDassert(TRUE == H5P_isa_class(io_info->dxpl_id, H5P_DATASET_XFER));
-
- /* Get the chunk's size */
- HDassert(layout->u.chunk.size > 0);
- H5_ASSIGN_OVERFLOW(chunk_size, layout->u.chunk.size, hsize_t, size_t);
-
- /* Search for the chunk in the cache */
- if(rdcc->nslots > 0) {
- idx = H5D_HASH(dset->shared,io_info->store->chunk.index);
- ent = rdcc->slot[idx];
-
- if(ent)
- for(u = 0, found = TRUE; u < layout->u.chunk.ndims; u++)
- if(io_info->store->chunk.offset[u] != ent->offset[u]) {
- found = FALSE;
- break;
- } /* end if */
- } /* end if */
-
- if(found) {
- /*
- * Already in the cache. Count a hit.
- */
-#ifdef H5D_ISTORE_DEBUG
- rdcc->nhits++;
-#endif /* H5D_ISTORE_DEBUG */
- } /* end if */
- else if(relax) {
- /*
- * Not in the cache, but we're about to overwrite the whole thing
- * anyway, so just allocate a buffer for it but don't initialize that
- * buffer with the file contents. Count this as a hit instead of a
- * miss because we saved ourselves lots of work.
- */
-#ifdef H5D_ISTORE_DEBUG
- HDputc('w', stderr);
- HDfflush(stderr);
- rdcc->nhits++;
-#endif
- if(NULL == (chunk = H5D_istore_chunk_alloc(chunk_size, pline)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for raw data chunk")
-
- /* In the case that some dataset functions look through this data,
- * clear it to all 0s. */
- HDmemset(chunk, 0, chunk_size);
-
- } /* end if */
- else {
- H5D_istore_ud1_t tmp_udata; /*B-tree pass-through */
- haddr_t chunk_addr; /* Address of chunk on disk */
-
- if(udata!=NULL)
- chunk_addr = udata->addr;
- else {
- /* Point at temporary storage for B-tree pass through */
- udata = &tmp_udata;
-
- /*
- * Not in the cache. Read it from the file and count this as a miss
- * if it's in the file or an init if it isn't.
- */
- chunk_addr = H5D_istore_get_addr(io_info, udata);
- } /* end else */
-
- if (H5F_addr_defined(chunk_addr)) {
- size_t chunk_alloc = 0; /*allocated chunk size */
-
- /*
- * The chunk exists on disk.
- */
- /* Chunk size on disk isn't [likely] the same size as the final chunk
- * size in memory, so allocate memory big enough. */
- chunk_alloc = udata->common.key.nbytes;
- if(NULL == (chunk = H5D_istore_chunk_alloc (chunk_alloc, pline)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for raw data chunk")
- if(H5F_block_read(dset->oloc.file, H5FD_MEM_DRAW, chunk_addr, udata->common.key.nbytes, io_info->dxpl_id, chunk) < 0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, NULL, "unable to read raw data chunk")
-
- if(pline->nused)
- if(H5Z_pipeline(pline, H5Z_FLAG_REVERSE, &(udata->common.key.filter_mask), io_info->dxpl_cache->err_detect,
- io_info->dxpl_cache->filter_cb, &(udata->common.key.nbytes), &chunk_alloc, &chunk) < 0)
- HGOTO_ERROR(H5E_PLINE, H5E_CANTFILTER, NULL, "data pipeline read failed")
-#ifdef H5D_ISTORE_DEBUG
- rdcc->nmisses++;
-#endif /* H5D_ISTORE_DEBUG */
- } else {
- H5D_fill_value_t fill_status;
-
-#ifdef OLD_WAY
- /* Clear the error stack from not finding the chunk on disk */
- H5E_clear_stack(NULL);
-#endif /* OLD_WAY */
-
- /* Chunk size on disk isn't [likely] the same size as the final chunk
- * size in memory, so allocate memory big enough. */
- if(NULL == (chunk = H5D_istore_chunk_alloc (chunk_size, pline)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for raw data chunk")
-
- if(H5P_is_fill_value_defined(fill, &fill_status) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't tell if fill value defined")
-
- if(fill->fill_time == H5D_FILL_TIME_ALLOC ||
- (fill->fill_time == H5D_FILL_TIME_IFSET && fill_status == H5D_FILL_VALUE_USER_DEFINED)) {
- /*
- * The chunk doesn't exist in the file. Replicate the fill
- * value throughout the chunk, if the fill value is defined.
- */
-
- /* Initialize the fill value buffer */
- /* (use the compact dataset storage buffer as the fill value buffer) */
- if(H5D_fill_init(&fb_info, chunk, FALSE,
- NULL, NULL, NULL, NULL,
- &dset->shared->dcpl_cache.fill, dset->shared->type,
- dset->shared->type_id, (size_t)0, chunk_size, io_info->dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "can't initialize fill buffer info")
- fb_info_init = TRUE;
-
- /* Check for VL datatype & non-default fill value */
- if(fb_info.has_vlen_fill_type)
- /* Fill the buffer with VL datatype fill values */
- if(H5D_fill_refill_vl(&fb_info, fb_info.elmts_per_buf, io_info->dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, NULL, "can't refill fill value buffer")
- } /* end if */
-#ifdef H5_CLEAR_MEMORY
- else
- HDmemset(chunk, 0, chunk_size);
-#endif /* H5_CLEAR_MEMORY */
-#ifdef H5D_ISTORE_DEBUG
- rdcc->ninits++;
-#endif /* H5D_ISTORE_DEBUG */
- } /* end else */
- } /* end else */
- HDassert(found || chunk_size > 0);
-
- if(!found && rdcc->nslots > 0 && chunk_size <= rdcc->nbytes &&
- (!ent || !ent->locked)) {
- /*
- * Add the chunk to the cache only if the slot is not already locked.
- * Preempt enough things from the cache to make room.
- */
- if (ent) {
-#ifdef H5D_ISTORE_DEBUG
- HDputc('#', stderr);
- HDfflush(stderr);
-#endif
- if (H5D_istore_preempt(io_info, ent, TRUE)<0)
- HGOTO_ERROR(H5E_IO, H5E_CANTINIT, NULL, "unable to preempt chunk from cache")
- }
- if (H5D_istore_prune(io_info, chunk_size)<0)
- HGOTO_ERROR(H5E_IO, H5E_CANTINIT, NULL, "unable to preempt chunk(s) from cache")
-
- /* Create a new entry */
- ent = H5FL_MALLOC(H5D_rdcc_ent_t);
- ent->locked = 0;
- ent->dirty = FALSE;
- ent->chunk_size = chunk_size;
- ent->alloc_size = chunk_size;
- for (u=0; u<layout->u.chunk.ndims; u++)
- ent->offset[u] = io_info->store->chunk.offset[u];
- ent->rd_count = chunk_size;
- ent->wr_count = chunk_size;
- ent->chunk = (uint8_t*)chunk;
-
- /* Add it to the cache */
- assert(NULL==rdcc->slot[idx]);
- rdcc->slot[idx] = ent;
- ent->idx = idx;
- rdcc->nbytes += chunk_size;
- rdcc->nused++;
-
- /* Add it to the linked list */
- ent->next = NULL;
- if (rdcc->tail) {
- rdcc->tail->next = ent;
- ent->prev = rdcc->tail;
- rdcc->tail = ent;
- } else {
- rdcc->head = rdcc->tail = ent;
- ent->prev = NULL;
- }
- found = TRUE;
- } else if (!found) {
- /*
- * The chunk is larger than the entire cache so we don't cache it.
- * This is the reason all those arguments have to be repeated for the
- * unlock function.
- */
- ent = NULL;
- idx = UINT_MAX;
-
- } else {
- /*
- * The chunk is not at the beginning of the cache; move it backward
- * by one slot. This is how we implement the LRU preemption
- * algorithm.
- */
- assert(ent);
- if (ent->next) {
- if (ent->next->next)
- ent->next->next->prev = ent;
- else
- rdcc->tail = ent;
- ent->next->prev = ent->prev;
- if (ent->prev)
- ent->prev->next = ent->next;
- else
- rdcc->head = ent->next;
- ent->prev = ent->next;
- ent->next = ent->next->next;
- ent->prev->next = ent;
- }
- }
-
- /* Lock the chunk into the cache */
- if (ent) {
- assert (!ent->locked);
- ent->locked = TRUE;
- chunk = ent->chunk;
- }
-
- if (idx_hint)
- *idx_hint = idx;
-
- /* Set return value */
- ret_value = chunk;
-
-done:
- /* Release the fill buffer info, if it's been initialized */
- if(fb_info_init && H5D_fill_term(&fb_info) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, NULL, "Can't release fill buffer info")
-
- /* Release the chunk allocated, on error */
- if(!ret_value)
- if(chunk)
- chunk = H5D_istore_chunk_xfree(chunk, pline);
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_istore_lock() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_unlock
- *
- * Purpose: Unlocks a previously locked chunk. The LAYOUT, COMP, and
- * OFFSET arguments should be the same as for H5F_rdcc_lock().
- * The DIRTY argument should be set to non-zero if the chunk has
- * been modified since it was locked. The IDX_HINT argument is
- * the returned index hint from the lock operation and BUF is
- * the return value from the lock.
- *
- * The NACCESSED argument should be the number of bytes accessed
- * for reading or writing (depending on the value of DIRTY).
- * It's only purpose is to provide additional information to the
- * preemption policy.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Robb Matzke
- * Thursday, May 21, 1998
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5D_istore_unlock(const H5D_io_info_t *io_info,
- hbool_t dirty, unsigned idx_hint, void *chunk, size_t naccessed)
-{
- const H5O_layout_t *layout=&(io_info->dset->shared->layout); /* Dataset layout */
- const H5D_rdcc_t *rdcc = &(io_info->dset->shared->cache.chunk);
- H5D_rdcc_ent_t *ent = NULL;
- unsigned u;
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_istore_unlock)
-
- assert(io_info);
-
- if (UINT_MAX==idx_hint) {
- /*
- * It's not in the cache, probably because it's too big. If it's
- * dirty then flush it to disk. In any case, free the chunk.
- * Note: we have to copy the layout and filter messages so we
- * don't discard the `const' qualifier.
- */
- if (dirty) {
- H5D_rdcc_ent_t x;
-
- HDmemset (&x, 0, sizeof x);
- x.dirty = TRUE;
- for (u=0; u<layout->u.chunk.ndims; u++)
- x.offset[u] = io_info->store->chunk.offset[u];
- assert(layout->u.chunk.size>0);
- H5_ASSIGN_OVERFLOW(x.chunk_size,layout->u.chunk.size,hsize_t,size_t);
- x.alloc_size = x.chunk_size;
- x.chunk = (uint8_t*)chunk;
-
- if (H5D_istore_flush_entry(io_info, &x, TRUE)<0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "cannot flush indexed storage buffer")
- } else {
- if(chunk)
- chunk=H5D_istore_chunk_xfree (chunk,&(io_info->dset->shared->dcpl_cache.pline));
- }
- } else {
- /* Sanity check */
- assert(idx_hint<rdcc->nslots);
- assert(rdcc->slot[idx_hint]);
- assert(rdcc->slot[idx_hint]->chunk==chunk);
-
- /*
- * It's in the cache so unlock it.
- */
- ent = rdcc->slot[idx_hint];
- assert (ent->locked);
- if (dirty) {
- ent->dirty = TRUE;
- ent->wr_count -= MIN (ent->wr_count, naccessed);
- } else {
- ent->rd_count -= MIN (ent->rd_count, naccessed);
- }
- ent->locked = FALSE;
- }
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_istore_unlock() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_if_load
- *
- * Purpose: A small internal function to if it's necessary to load the
- * chunk into cache. If the chunk is too large to load into
- * the cache and it has no filters in the pipeline (i.e. not
- * compressed) and if the address for the chunk has been
- * defined, then don't load the chunk into the cache, just
- * read the data from it directly. If MPI based VFD is used,
- * must bypass the chunk-cache scheme because other MPI
- * processes could be writing to other elements in the same
- * chunk. Do a direct read-through of only the elements
- * requested.
- *
- * Return: TRUE or FALSE
- *
- * Programmer: Raymond Lu
- * 17 July 2007
- *
- *-------------------------------------------------------------------------
- */
-hbool_t
-H5D_istore_if_load(H5D_t *dataset, haddr_t caddr)
-{
- hbool_t ret_value;
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_istore_if_load)
-
- assert(dataset);
-
- if (dataset->shared->dcpl_cache.pline.nused==0 && ((dataset->shared->layout.u.chunk.size >
- dataset->shared->cache.chunk.nbytes && caddr!=HADDR_UNDEF)
- || (IS_H5FD_MPI(dataset->oloc.file) && (H5F_ACC_RDWR &
- H5F_get_intent(dataset->oloc.file))))) {
- ret_value = FALSE;
- } else
- ret_value = TRUE;
-
- FUNC_LEAVE_NOAPI(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_readvv
- *
- * Purpose: Reads a multi-dimensional buffer from (part of) an indexed raw
- * storage array.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Wednesday, May 7, 2003
- *
- * Modification:
- * Raymond Lu
- * 20 July 2007
- * Moved H5D_istore_lock and H5D_istore_unlock to H5D_chunk_read
- * from this function to avoid frequent lock and unlock.
- *
- *-------------------------------------------------------------------------
- */
-ssize_t
-H5D_istore_readvv(const H5D_io_info_t *io_info,
- size_t chunk_max_nseq, size_t *chunk_curr_seq, size_t chunk_len_arr[], hsize_t chunk_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[],
- haddr_t chunk_addr, void *chunk, void *buf)
-{
- H5D_t *dset=io_info->dset; /* Local pointer to the dataset info */
- size_t u; /* Local index variables */
- ssize_t ret_value; /* Return value */
-
- FUNC_ENTER_NOAPI(H5D_istore_readvv, FAIL)
-
- /* Check args */
- HDassert(io_info);
- HDassert(dset && H5D_CHUNKED==dset->shared->layout.type);
- HDassert(dset->shared->layout.u.chunk.ndims>0 && dset->shared->layout.u.chunk.ndims<=H5O_LAYOUT_NDIMS);
- HDassert(io_info->dxpl_cache);
- HDassert(io_info->store);
- HDassert(chunk_len_arr);
- HDassert(chunk_offset_arr);
- HDassert(mem_len_arr);
- HDassert(mem_offset_arr);
- HDassert(buf);
-
- /* Get the address of this chunk on disk */
-#ifdef QAK
-HDfprintf(stderr,"%s: io_info->store->chunk.offset={",FUNC);
-for(u=0; u<dset->shared->layout.u.chunk.ndims; u++)
- HDfprintf(stderr,"%Hd%s",io_info->store->chunk.offset[u],(u<(dset->shared->layout.u.chunk.ndims-1) ? ", " : "}\n"));
-
-HDfprintf(stderr,"%s: chunk_addr=%a, chunk_size=%Zu\n",FUNC,chunk_addr,dset->shared->layout.u.chunk.size);
-HDfprintf(stderr,"%s: chunk_len_arr[%Zu]=%Zu\n",FUNC,*chunk_curr_seq,chunk_len_arr[*chunk_curr_seq]);
-HDfprintf(stderr,"%s: chunk_offset_arr[%Zu]=%Hu\n",FUNC,*chunk_curr_seq,chunk_offset_arr[*chunk_curr_seq]);
-HDfprintf(stderr,"%s: mem_len_arr[%Zu]=%Zu\n",FUNC,*mem_curr_seq,mem_len_arr[*mem_curr_seq]);
-HDfprintf(stderr,"%s: mem_offset_arr[%Zu]=%Hu\n",FUNC,*mem_curr_seq,mem_offset_arr[*mem_curr_seq]);
-HDfprintf(stderr,"%s: buf=%p\n",FUNC,buf);
-#endif /* QAK */
-
- /*
- * If the chunk is too large to load into the cache and it has no
- * filters in the pipeline (i.e. not compressed) and if the address
- * for the chunk has been defined, then don't load the chunk into the
- * cache, just read the data from it directly.
- *
- * If MPI based VFD is used, must bypass the
- * chunk-cache scheme because other MPI processes could be
- * writing to other elements in the same chunk. Do a direct
- * read-through of only the elements requested.
- */
- if (!H5D_istore_if_load(dset, chunk_addr)) {
- H5D_io_info_t chk_io_info; /* Temporary I/O info object */
- H5D_storage_t chk_store; /* Chunk storage information */
-
- /* Set up the storage information for the chunk */
- chk_store.contig.dset_addr=chunk_addr;
- chk_store.contig.dset_size=(hsize_t)dset->shared->layout.u.chunk.size;
-
- /* Set up new dataset I/O info */
- H5D_BUILD_IO_INFO(&chk_io_info,dset,io_info->dxpl_cache,io_info->dxpl_id,&chk_store);
-
- /* Do I/O directly on chunk without reading it into the cache */
- if ((ret_value=H5D_contig_readvv(&chk_io_info, chunk_max_nseq, chunk_curr_seq, chunk_len_arr,
- chunk_offset_arr, mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, (haddr_t)0, NULL, buf))<0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data to file")
- } /* end if */
- else {
- ssize_t naccessed; /* Number of bytes accessed in chunk */
-
- /* If the chunk address is not defined, check if the fill value is
- * undefined also. If both situations hold, don't bother copying
- * values to the destination buffer, since they will just be
- * garbage.
- *
- * Ideally, this will eventually be checked at a higher level and
- * the entire I/O operation on the chunk will be skipped. -QAK
- */
- if(!H5F_addr_defined(chunk_addr)) {
- H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk);/*raw data chunk cache*/
- hbool_t found = FALSE; /*already in cache? */
-
- /* Check if the chunk is in the cache (but hasn't been written to disk yet) */
- if(rdcc->nslots>0) {
- unsigned idx = H5D_HASH(dset->shared, io_info->store->chunk.index); /* Cache entry index */
- H5D_rdcc_ent_t *ent = rdcc->slot[idx]; /* Cache entry */
-
- /* Potential match... */
- if(ent) {
- for(u = 0, found = TRUE; u < dset->shared->layout.u.chunk.ndims; u++) {
- if(io_info->store->chunk.offset[u] != ent->offset[u]) {
- found = FALSE;
- break;
- } /* end if */
- } /* end for */
- } /* end if */
- } /* end if */
-
- /* If the chunk is in the cache, then it must have valid data */
- if(!found) {
- const H5O_fill_t *fill = &(dset->shared->dcpl_cache.fill); /* Fill value info */
- H5D_fill_value_t fill_status;
-
- /* Check if the fill value is defined */
- if(H5P_is_fill_value_defined(fill, &fill_status) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't tell if fill value defined")
-
- /* If we are never to return fill values, or if we would return them
- * but they aren't set, process the entire set of I/O vectors and
- * get out now.
- */
- if(fill->fill_time == H5D_FILL_TIME_NEVER ||
- (fill->fill_time == H5D_FILL_TIME_IFSET && fill_status!=H5D_FILL_VALUE_USER_DEFINED)) {
- size_t size; /* Size of sequence in bytes */
- size_t v; /* Local index variable */
- ssize_t bytes_processed = 0; /* Eventual return value */
-
- /* Work through all the sequences */
- for(u = *mem_curr_seq, v = *chunk_curr_seq; u < mem_max_nseq && v < chunk_max_nseq; ) {
- /* Choose smallest buffer to write */
- if(chunk_len_arr[v] < mem_len_arr[u])
- size = chunk_len_arr[v];
- else
- size = mem_len_arr[u];
-
- /* Update source information */
- chunk_len_arr[v] -= size;
- chunk_offset_arr[v] += size;
- if(chunk_len_arr[v] == 0)
- v++;
-
- /* Update destination information */
- mem_len_arr[u] -= size;
- mem_offset_arr[u] += size;
- if(mem_len_arr[u] == 0)
- u++;
-
- /* Increment number of bytes copied */
- bytes_processed += (ssize_t)size;
- } /* end for */
-
- /* Update current sequence vectors */
- *mem_curr_seq = u;
- *chunk_curr_seq = v;
-
- HGOTO_DONE(bytes_processed)
- } /* end if */
- } /* end if */
- } /* end if */
-
- /* Use the vectorized memory copy routine to do actual work */
- if((naccessed = H5V_memcpyvv(buf, mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, chunk, chunk_max_nseq, chunk_curr_seq, chunk_len_arr, chunk_offset_arr)) < 0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "vectorized memcpy failed")
-
- H5_CHECK_OVERFLOW(naccessed, ssize_t, size_t);
-
- /* Set return value */
- ret_value = naccessed;
- } /* end else */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5D_istore_readvv() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_writevv
- *
- * Purpose: Writes a multi-dimensional buffer to (part of) an indexed raw
- * storage array.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Friday, May 2, 2003
- *
- * Modification:
- * Raymond Lu
- * 20 July 2007
- * Moved H5D_istore_lock and H5D_istore_unlock to H5D_chunk_write
- * from this function to avoid frequent lock and unlock.
- *
- *-------------------------------------------------------------------------
- */
-ssize_t
-H5D_istore_writevv(const H5D_io_info_t *io_info,
- size_t chunk_max_nseq, size_t *chunk_curr_seq, size_t chunk_len_arr[], hsize_t chunk_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[],
- haddr_t chunk_addr, void *chunk, const void *buf)
-{
- H5D_t *dset = io_info->dset; /* Local pointer to the dataset info */
- ssize_t ret_value; /* Return value */
-
- FUNC_ENTER_NOAPI(H5D_istore_writevv, FAIL)
-
- /* Check args */
- HDassert(io_info);
- HDassert(dset && H5D_CHUNKED==dset->shared->layout.type);
- HDassert(dset->shared->layout.u.chunk.ndims>0 && dset->shared->layout.u.chunk.ndims<=H5O_LAYOUT_NDIMS);
- HDassert(io_info->dxpl_cache);
- HDassert(io_info->store);
- HDassert(chunk_len_arr);
- HDassert(chunk_offset_arr);
- HDassert(mem_len_arr);
- HDassert(mem_offset_arr);
- HDassert(buf);
-
-#ifdef QAK
-{
-size_t u; /* Local index variables */
-
-HDfprintf(stderr,"%s: io_info->store->chunk.offset={",FUNC);
-for(u=0; u<dset->shared->layout.u.chunk.ndims; u++)
- HDfprintf(stderr,"%Hd%s",io_info->store->chunk.offset[u],(u<(dset->shared->layout.u.chunk.ndims-1) ? ", " : "}\n"));
-
-HDfprintf(stderr,"%s: chunk_addr=%a, chunk_size=%Zu\n",FUNC,chunk_addr,dset->shared->layout.u.chunk.size);
-HDfprintf(stderr,"%s: chunk_len_arr[%Zu]=%Zu\n",FUNC,*chunk_curr_seq,chunk_len_arr[*chunk_curr_seq]);
-HDfprintf(stderr,"%s: chunk_offset_arr[%Zu]=%Hu\n",FUNC,*chunk_curr_seq,chunk_offset_arr[*chunk_curr_seq]);
-HDfprintf(stderr,"%s: mem_len_arr[%Zu]=%Zu\n",FUNC,*mem_curr_seq,mem_len_arr[*mem_curr_seq]);
-HDfprintf(stderr,"%s: mem_offset_arr[%Zu]=%Hu\n",FUNC,*mem_curr_seq,mem_offset_arr[*mem_curr_seq]);
-}
-#endif /* QAK */
-
- /*
- * If the chunk is too large to load into the cache and it has no
- * filters in the pipeline (i.e. not compressed) and if the address
- * for the chunk has been defined, then don't load the chunk into the
- * cache, just write the data to it directly.
- *
- * If MPI based VFD is used, must bypass the
- * chunk-cache scheme because other MPI processes could be
- * writing to other elements in the same chunk. Do a direct
- * write-through of only the elements requested.
- */
- if (!H5D_istore_if_load(dset, chunk_addr)) {
- H5D_io_info_t chk_io_info; /* Temporary I/O info object */
- H5D_storage_t chk_store; /* Chunk storage information */
-
- /* Set up the storage information for the chunk */
- chk_store.contig.dset_addr=chunk_addr;
- chk_store.contig.dset_size=(hsize_t)dset->shared->layout.u.chunk.size;
-
- /* Set up new dataset I/O info */
- H5D_BUILD_IO_INFO(&chk_io_info,dset,io_info->dxpl_cache,io_info->dxpl_id,&chk_store);
-
- /* Do I/O directly on chunk without reading it into the cache */
- if ((ret_value=H5D_contig_writevv(&chk_io_info, chunk_max_nseq, chunk_curr_seq, chunk_len_arr, chunk_offset_arr, mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, (haddr_t)0, NULL, buf))<0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write raw data to file")
- } /* end if */
- else {
- ssize_t naccessed; /* Number of bytes accessed in chunk */
-
- /* Use the vectorized memory copy routine to do actual work */
- if((naccessed=H5V_memcpyvv(chunk,chunk_max_nseq,chunk_curr_seq,chunk_len_arr,chunk_offset_arr,buf,mem_max_nseq,mem_curr_seq,mem_len_arr,mem_offset_arr))<0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed")
-
- H5_CHECK_OVERFLOW(naccessed,ssize_t,size_t);
-
- /* Set return value */
- ret_value=naccessed;
- } /* end else */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5D_istore_writevv() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_create
- *
- * Purpose: Creates a new indexed-storage B-tree and initializes the
- * istore struct with information about the storage. The
- * struct should be immediately written to the object header.
- *
- * This function must be called before passing ISTORE to any of
- * the other indexed storage functions!
- *
- * Return: Non-negative on success (with the ISTORE argument initialized
- * and ready to write to an object header). Negative on failure.
- *
- * Programmer: Robb Matzke
- * Tuesday, October 21, 1997
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5D_istore_create(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout /*out */)
-{
- H5D_istore_ud0_t udata;
-#ifndef NDEBUG
- unsigned u;
-#endif
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5D_istore_create, FAIL)
-
- /* Check args */
- HDassert(f);
- HDassert(layout && H5D_CHUNKED == layout->type);
- HDassert(layout->u.chunk.ndims > 0 && layout->u.chunk.ndims <= H5O_LAYOUT_NDIMS);
-#ifndef NDEBUG
- for(u = 0; u < layout->u.chunk.ndims; u++)
- HDassert(layout->u.chunk.dim[u] > 0);
-#endif
-
- /* Initialize "user" data for B-tree callbacks, etc. */
- udata.mesg = layout;
-
- if(H5B_create(f, dxpl_id, H5B_ISTORE, &udata, &(layout->u.chunk.addr)/*out*/) < 0)
- HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "can't create B-tree")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_istore_create() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_allocated
- *
- * Purpose: Return the number of bytes allocated in the file for storage
- * of raw data under the specified B-tree (ADDR is the address
- * of the B-tree).
- *
- * Return: Success: Number of bytes stored in all chunks.
- *
- * Failure: 0
- *
- * Programmer: Robb Matzke
- * Wednesday, April 21, 1999
- *
- *-------------------------------------------------------------------------
- */
-hsize_t
-H5D_istore_allocated(H5D_t *dset, hid_t dxpl_id)
-{
- H5D_io_info_t io_info; /* Temporary I/O info object */
- const H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk); /*raw data chunk cache */
- H5D_rdcc_ent_t *ent; /*cache entry */
- H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */
- H5D_dxpl_cache_t *dxpl_cache=&_dxpl_cache; /* Data transfer property cache */
- H5D_istore_it_ud1_t udata;
- hsize_t ret_value; /* Return value */
-
- FUNC_ENTER_NOAPI(H5D_istore_allocated, 0)
-
- HDassert(dset);
-
- /* Fill the DXPL cache values for later use */
- if (H5D_get_dxpl_cache(dxpl_id,&dxpl_cache)<0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, 0, "can't fill dxpl cache")
-
- /* Construct dataset I/O info */
- H5D_BUILD_IO_INFO(&io_info,dset,dxpl_cache,dxpl_id,NULL);
-
- /* Search for cached chunks that haven't been written out */
- for(ent = rdcc->head; ent; ent = ent->next) {
- /* Flush the chunk out to disk, to make certain the size is correct later */
- if (H5D_istore_flush_entry(&io_info, ent, FALSE)<0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, 0, "cannot flush indexed storage buffer")
- } /* end for */
-
- HDmemset(&udata, 0, sizeof udata);
- udata.common.mesg = &dset->shared->layout;
- if(H5B_iterate(dset->oloc.file, dxpl_id, H5B_ISTORE, H5D_istore_iter_allocated, dset->shared->layout.u.chunk.addr, &udata) < 0)
- HGOTO_ERROR(H5E_IO, H5E_CANTINIT, 0, "unable to iterate over chunk B-tree")
-
- /* Set return value */
- ret_value = udata.total_storage;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_istore_allocated() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_chunkmap
- *
- * Purpose: obtain the chunk address and corresponding chunk index
- *
- * Return: Success: Non-negative on succeed.
- *
- * Failure: negative value
- *
- * Programmer: Kent Yang
- * November 15, 2005
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5D_istore_chunkmap(const H5D_io_info_t *io_info, haddr_t chunk_addr[],
- hsize_t down_chunks[])
-{
- H5D_t *dset = io_info->dset; /* Local pointer to dataset info */
- H5D_istore_it_ud5_t udata;
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5D_istore_chunkmap, FAIL)
-
- HDassert(dset);
-
- /* Set up user data for B-tree callback */
- HDmemset(&udata, 0, sizeof(udata));
- udata.common.mesg = &dset->shared->layout;
- udata.down_chunks = down_chunks;
- udata.chunk_addr = chunk_addr;
-
- /* Build mapping of chunk addresses and indices */
- if(H5B_iterate(dset->oloc.file, io_info->dxpl_id, H5B_ISTORE, H5D_istore_iter_chunkmap, dset->shared->layout.u.chunk.addr, &udata) < 0)
- HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to iterate over chunk B-tree")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_istore_chunkmap() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_get_addr
- *
- * Purpose: Get the file address of a chunk if file space has been
- * assigned. Save the retrieved information in the udata
- * supplied.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Albert Cheng
- * June 27, 1998
- *
- *-------------------------------------------------------------------------
- */
-haddr_t
-H5D_istore_get_addr(const H5D_io_info_t *io_info, H5D_istore_ud1_t *_udata)
-{
- H5D_istore_ud1_t tmp_udata; /* Information about a chunk */
- H5D_istore_ud1_t *udata; /* Pointer to information about a chunk */
- unsigned u;
- haddr_t ret_value; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_get_addr)
-
- HDassert(io_info);
- HDassert(io_info->dset);
- HDassert(io_info->dset->shared->layout.u.chunk.ndims > 0);
- HDassert(io_info->store->chunk.offset);
-
- /* Check for udata struct to return */
- udata = (_udata != NULL ? _udata : &tmp_udata);
-
- /* Initialize the information about the chunk we are looking for */
- for(u = 0; u < io_info->dset->shared->layout.u.chunk.ndims; u++)
- udata->common.key.offset[u] = io_info->store->chunk.offset[u];
- udata->common.mesg = &(io_info->dset->shared->layout);
- udata->addr = HADDR_UNDEF;
-
- /* Go get the chunk information */
- if (H5B_find (io_info->dset->oloc.file, io_info->dxpl_id, H5B_ISTORE, io_info->dset->shared->layout.u.chunk.addr, udata)<0) {
- /* Note: don't push error on stack, leave that to next higher level,
- * since many times the B-tree is searched in order to determine
- * if a chunk exists in the B-tree or not. -QAK
- */
-#ifdef OLD_WAY
- H5E_clear_stack(NULL);
-
- HGOTO_ERROR(H5E_BTREE,H5E_NOTFOUND,HADDR_UNDEF,"Can't locate chunk info")
-#else /* OLD_WAY */
- HGOTO_DONE(HADDR_UNDEF)
-#endif /* OLD_WAY */
- } /* end if */
-
- /* Success! Set the return value */
- ret_value=udata->addr;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5D_istore_get_addr() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_chunk_alloc
- *
- * Purpose: Allocate space for a chunk in memory. This routine allocates
- * memory space for non-filtered chunks from a block free list
- * and uses malloc()/free() for filtered chunks.
- *
- * Return: Pointer to memory for chunk on success/NULL on failure
- *
- * Programmer: Quincey Koziol
- * April 22, 2004
- *
- *-------------------------------------------------------------------------
- */
-static void *
-H5D_istore_chunk_alloc(size_t size, const H5O_pline_t *pline)
-{
- void *ret_value = NULL; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_istore_chunk_alloc)
-
- HDassert(size);
- HDassert(pline);
-
- if(pline->nused > 0)
- ret_value = H5MM_malloc(size);
- else
- ret_value = H5FL_BLK_MALLOC(chunk, size);
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5D_istore_chunk_alloc() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_chunk_xfree
- *
- * Purpose: Free space for a chunk in memory. This routine allocates
- * memory space for non-filtered chunks from a block free list
- * and uses malloc()/free() for filtered chunks.
- *
- * Return: NULL (never fails)
- *
- * Programmer: Quincey Koziol
- * April 22, 2004
- *
- *-------------------------------------------------------------------------
- */
-static void *
-H5D_istore_chunk_xfree(void *chk, const H5O_pline_t *pline)
-{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_chunk_xfree)
-
- HDassert(pline);
-
- if(chk) {
- if(pline->nused > 0)
- H5MM_xfree(chk);
- else
- H5FL_BLK_FREE(chunk, chk);
- } /* end if */
-
- FUNC_LEAVE_NOAPI(NULL)
-} /* H5D_istore_chunk_xfree() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_allocate
- *
- * Purpose: Allocate file space for all chunks that are not allocated yet.
- * Return SUCCEED if all needed allocation succeed, otherwise
- * FAIL.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Note: Current implementation relies on cache_size being 0,
- * thus no chunk is cached and written to disk immediately
- * when a chunk is unlocked (via H5F_istore_unlock)
- * This should be changed to do a direct flush independent
- * of the cache value.
- *
- * Programmer: Albert Cheng
- * June 26, 1998
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5D_istore_allocate(H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite)
-{
- H5D_io_info_t io_info; /* Dataset I/O info */
- H5D_storage_t store; /* Dataset storage information */
- hsize_t chunk_offset[H5O_LAYOUT_NDIMS]; /* Offset of current chunk */
- size_t orig_chunk_size; /* Original size of chunk in bytes */
- unsigned filter_mask = 0; /* Filter mask for chunks that have them */
- const H5O_layout_t *layout = &(dset->shared->layout); /* Dataset layout */
- const H5O_pline_t *pline = &(dset->shared->dcpl_cache.pline); /* I/O pipeline info */
- const H5O_fill_t *fill = &(dset->shared->dcpl_cache.fill); /* Fill value info */
- H5D_fill_value_t fill_status; /* The fill value status */
- hbool_t should_fill = FALSE; /* Whether fill values should be written */
- H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */
- H5D_dxpl_cache_t *dxpl_cache = &_dxpl_cache; /* Data transfer property cache */
-#ifdef H5_HAVE_PARALLEL
- MPI_Comm mpi_comm = MPI_COMM_NULL; /* MPI communicator for file */
- int mpi_rank = (-1); /* This process's rank */
- int mpi_code; /* MPI return code */
- hbool_t blocks_written = FALSE; /* Flag to indicate that chunk was actually written */
- hbool_t using_mpi = FALSE; /* Flag to indicate that the file is being accessed with an MPI-capable file driver */
-#endif /* H5_HAVE_PARALLEL */
- hbool_t carry; /* Flag to indicate that chunk increment carrys to higher dimension (sorta) */
- int space_ndims; /* Dataset's space rank */
- hsize_t space_dim[H5O_LAYOUT_NDIMS]; /* Dataset's dataspace dimensions */
- H5D_fill_buf_info_t fb_info; /* Dataset's fill buffer info */
- hbool_t fb_info_init = FALSE; /* Whether the fill value buffer has been initialized */
- hid_t data_dxpl_id; /* DXPL ID to use for raw data I/O operations */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5D_istore_allocate, FAIL)
-
- /* Check args */
- HDassert(dset && H5D_CHUNKED == layout->type);
- HDassert(layout->u.chunk.ndims > 0 && layout->u.chunk.ndims <= H5O_LAYOUT_NDIMS);
- HDassert(H5F_addr_defined(layout->u.chunk.addr));
- HDassert(TRUE == H5P_isa_class(dxpl_id, H5P_DATASET_XFER));
-
- /* Retrieve the dataset dimensions */
- if((space_ndims = H5S_get_simple_extent_dims(dset->shared->space, space_dim, NULL)) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to get simple dataspace info")
- space_dim[space_ndims] = layout->u.chunk.dim[space_ndims];
-
-#ifdef H5_HAVE_PARALLEL
- /* Retrieve MPI parameters */
- if(IS_H5FD_MPI(dset->oloc.file)) {
- /* Get the MPI communicator */
- if(MPI_COMM_NULL == (mpi_comm = H5F_mpi_get_comm(dset->oloc.file)))
- HGOTO_ERROR(H5E_INTERNAL, H5E_MPI, FAIL, "Can't retrieve MPI communicator")
-
- /* Get the MPI rank */
- if((mpi_rank = H5F_mpi_get_rank(dset->oloc.file)) < 0)
- HGOTO_ERROR(H5E_INTERNAL, H5E_MPI, FAIL, "Can't retrieve MPI rank")
-
- /* Set the MPI-capable file driver flag */
- using_mpi = TRUE;
-
- /* Use the internal "independent" DXPL */
- data_dxpl_id = H5AC_ind_dxpl_id;
- } /* end if */
- else {
-#endif /* H5_HAVE_PARALLEL */
- /* Use the DXPL we were given */
- data_dxpl_id = dxpl_id;
-#ifdef H5_HAVE_PARALLEL
- } /* end else */
-#endif /* H5_HAVE_PARALLEL */
-
- /* Fill the DXPL cache values for later use */
- if(H5D_get_dxpl_cache(data_dxpl_id, &dxpl_cache) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache")
-
- /* Get original chunk size */
- H5_CHECK_OVERFLOW(layout->u.chunk.size, hsize_t, size_t);
- orig_chunk_size = (size_t)layout->u.chunk.size;
-
- /* Check the dataset's fill-value status */
- if(H5P_is_fill_value_defined(fill, &fill_status) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't tell if fill value defined")
-
- /* If we are filling the dataset on allocation or "if set" and
- * the fill value _is_ set, _and_ we are not overwriting the new blocks,
- * or if there are any pipeline filters defined,
- * set the "should fill" flag
- */
- if((!full_overwrite && (fill->fill_time == H5D_FILL_TIME_ALLOC ||
- (fill->fill_time == H5D_FILL_TIME_IFSET && fill_status == H5D_FILL_VALUE_USER_DEFINED)))
- || pline->nused > 0)
- should_fill = TRUE;
-
- /* Check if fill values should be written to chunks */
- if(should_fill) {
- /* Initialize the fill value buffer */
- /* (delay allocating fill buffer for VL datatypes until refilling) */
- /* (casting away const OK - QAK) */
- if(H5D_fill_init(&fb_info, NULL, (hbool_t)(pline->nused > 0),
- (H5MM_allocate_t)H5D_istore_chunk_alloc, (void *)pline,
- (H5MM_free_t)H5D_istore_chunk_xfree, (void *)pline,
- &dset->shared->dcpl_cache.fill, dset->shared->type,
- dset->shared->type_id, (size_t)0, orig_chunk_size, data_dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize fill buffer info")
- fb_info_init = TRUE;
-
- /* Check if there are filters which need to be applied to the chunk */
- /* (only do this in advance when the chunk info can be re-used (i.e.
- * it doesn't contain any non-default VL datatype fill values)
- */
- if(!fb_info.has_vlen_fill_type && pline->nused > 0) {
- size_t buf_size = orig_chunk_size;
-
- /* Push the chunk through the filters */
- if(H5Z_pipeline(pline, 0, &filter_mask, dxpl_cache->err_detect, dxpl_cache->filter_cb, &orig_chunk_size, &buf_size, &fb_info.fill_buf) < 0)
- HGOTO_ERROR(H5E_PLINE, H5E_WRITEERROR, FAIL, "output pipeline failed")
- } /* end if */
- } /* end if */
-
- /* Set up dataset I/O info */
- store.chunk.offset = chunk_offset;
- H5D_BUILD_IO_INFO(&io_info, dset, dxpl_cache, data_dxpl_id, &store);
-
- /* Reset the chunk offset indices */
- HDmemset(chunk_offset, 0, (layout->u.chunk.ndims * sizeof(chunk_offset[0])));
-
- /* Loop over all chunks */
- carry = FALSE;
- while(!carry) {
- int i; /* Local index variable */
-
- /* Check if the chunk exists yet on disk */
- if(!H5F_addr_defined(H5D_istore_get_addr(&io_info, NULL))) {
- const H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk); /* Raw data chunk cache */
- H5D_rdcc_ent_t *ent; /* Cache entry */
- hbool_t chunk_exists; /* Flag to indicate whether a chunk exists already */
- unsigned u; /* Local index variable */
-
- /* Didn't find the chunk on disk */
- chunk_exists = FALSE;
-
- /* Look for chunk in cache */
- for(ent = rdcc->head; ent && !chunk_exists; ent = ent->next) {
- /* Assume a match */
- chunk_exists = TRUE;
- for(u = 0; u < layout->u.chunk.ndims; u++)
- if(ent->offset[u] != chunk_offset[u]) {
- chunk_exists = FALSE; /* Reset if no match */
- break;
- } /* end if */
- } /* end for */
-
- /* Chunk wasn't in cache either, create it now */
- if(!chunk_exists) {
- H5D_istore_ud1_t udata; /* B-tree pass-through for creating chunk */
- size_t chunk_size; /* Size of chunk in bytes, possibly filtered */
-
- /* Check for VL datatype & non-default fill value */
- if(fb_info_init && fb_info.has_vlen_fill_type) {
- /* Sanity check */
- HDassert(should_fill);
-
- /* Fill the buffer with VL datatype fill values */
- if(H5D_fill_refill_vl(&fb_info, fb_info.elmts_per_buf, data_dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "can't refill fill value buffer")
-
- /* Check if there are filters which need to be applied to the chunk */
- if(pline->nused > 0) {
- size_t buf_size = orig_chunk_size;
- size_t nbytes = fb_info.fill_buf_size;
-
- /* Push the chunk through the filters */
- if(H5Z_pipeline(pline, 0, &filter_mask, dxpl_cache->err_detect, dxpl_cache->filter_cb, &nbytes, &buf_size, &fb_info.fill_buf) < 0)
- HGOTO_ERROR(H5E_PLINE, H5E_WRITEERROR, FAIL, "output pipeline failed")
-
- /* Keep the number of bytes the chunk turned in to */
- chunk_size = nbytes;
- } /* end if */
- else
- chunk_size = (size_t)layout->u.chunk.size;
- } /* end if */
- else
- chunk_size = orig_chunk_size;
-
- /* Initialize the chunk information */
- udata.common.mesg = layout;
- udata.common.key.filter_mask = filter_mask;
- udata.addr = HADDR_UNDEF;
- udata.common.key.nbytes = chunk_size;
- for(u = 0; u < layout->u.chunk.ndims; u++)
- udata.common.key.offset[u] = chunk_offset[u];
-
- /* Allocate the chunk with all processes */
- if(H5B_insert(dset->oloc.file, dxpl_id, H5B_ISTORE, layout->u.chunk.addr, &udata) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to allocate chunk")
-
- /* Check if fill values should be written to chunks */
- if(should_fill) {
- /* Sanity check */
- HDassert(fb_info_init);
-
-#ifdef H5_HAVE_PARALLEL
- /* Check if this file is accessed with an MPI-capable file driver */
- if(using_mpi) {
- /* Write the chunks out from only one process */
- /* !! Use the internal "independent" DXPL!! -QAK */
- if(H5_PAR_META_WRITE == mpi_rank)
- if(H5F_block_write(dset->oloc.file, H5FD_MEM_DRAW, udata.addr, udata.common.key.nbytes, data_dxpl_id, fb_info.fill_buf) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write raw data to file")
-
- /* Indicate that blocks are being written */
- blocks_written = TRUE;
- } /* end if */
- else {
-#endif /* H5_HAVE_PARALLEL */
- if(H5F_block_write(dset->oloc.file, H5FD_MEM_DRAW, udata.addr, udata.common.key.nbytes, data_dxpl_id, fb_info.fill_buf) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write raw data to file")
-#ifdef H5_HAVE_PARALLEL
- } /* end else */
-#endif /* H5_HAVE_PARALLEL */
- } /* end if */
-
- /* Release the fill buffer if we need to re-allocate it each time */
- if(fb_info_init && fb_info.has_vlen_fill_type && pline->nused > 0)
- H5D_fill_release(&fb_info);
- } /* end if */
- } /* end if */
-
- /* Increment indices */
- carry = TRUE;
- for(i = (int)(space_ndims - 1); i >= 0; --i) {
- chunk_offset[i] += layout->u.chunk.dim[i];
- if(chunk_offset[i] >= space_dim[i])
- chunk_offset[i] = 0;
- else {
- carry = FALSE;
- break;
- } /* end else */
- } /* end for */
- } /* end while */
-
-#ifdef H5_HAVE_PARALLEL
- /* Only need to block at the barrier if we actually initialized a chunk */
- /* using an MPI-capable file driver */
- if(using_mpi && blocks_written) {
- /* Wait at barrier to avoid race conditions where some processes are
- * still writing out chunks and other processes race ahead to read
- * them in, getting bogus data.
- */
- if(MPI_SUCCESS != (mpi_code = MPI_Barrier(mpi_comm)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Barrier failed", mpi_code)
- } /* end if */
-#endif /* H5_HAVE_PARALLEL */
-
-done:
- /* Release the fill buffer info, if it's been initialized */
- if(fb_info_init && H5D_fill_term(&fb_info) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release fill buffer info")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_istore_allocate() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_prune_check
- *
- * Purpose: Search for chunks that are no longer necessary in the B-tree.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
- * March 26, 2002
- *
- *-------------------------------------------------------------------------
- */
-/* ARGSUSED */
-static int
-H5D_istore_prune_check(H5F_t UNUSED *f, hid_t UNUSED dxpl_id,
- const void *_lt_key, haddr_t UNUSED addr, const void UNUSED *_rt_key,
- void *_udata)
-{
- H5D_istore_it_ud3_t *udata = (H5D_istore_it_ud3_t *)_udata;
- const H5D_istore_key_t *lt_key = (const H5D_istore_key_t *)_lt_key;
- unsigned rank; /*current # of dimensions */
- unsigned u;
- int ret_value = H5_ITER_CONT; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_istore_prune_check)
-
- /* Figure out what chunks are no longer in use for the specified extent and release them */
- rank = udata->common.mesg->u.chunk.ndims - 1;
- for(u = 0; u < rank; u++)
- /* The LT_KEY is the left key (the one that describes the chunk). It points to a chunk of
- * storage that contains the beginning of the logical address space represented by UDATA.
- */
- if((hsize_t)lt_key->offset[u] > udata->dims[u]) {
- H5D_istore_sl_ck_t *sl_node; /* Skip list node for chunk to remove */
-
- /* Allocate space for the shared structure */
- if(NULL == (sl_node = H5FL_MALLOC(H5D_istore_sl_ck_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5_ITER_ERROR, "memory allocation failed for shared B-tree info")
-
- /* Calculate the index of this chunk */
- if(H5V_chunk_index(rank, lt_key->offset, udata->common.mesg->u.chunk.dim, udata->down_chunks, &sl_node->index) < 0) {
- H5FL_FREE(H5D_istore_sl_ck_t, sl_node);
- HGOTO_ERROR(H5E_IO, H5E_BADRANGE, H5_ITER_ERROR, "can't get chunk index")
- } /* end if */
-
- /* Store the key for the chunk */
- sl_node->key = *lt_key;
-
- /* Insert the chunk description in the skip list */
- if(H5SL_insert(udata->outside, sl_node, &sl_node->index) < 0) {
- H5FL_FREE(H5D_istore_sl_ck_t, sl_node);
- HGOTO_ERROR(H5E_IO, H5E_CANTINSERT, H5_ITER_ERROR, "can't insert chunk into skip list")
- } /* end if */
-
- /* Break out of loop, we know the chunk is outside the current dimensions */
- break;
- } /* end if */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_istore_prune_check() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_prune_remove
- *
- * Purpose: Destroy a skip list node for "pruning" chunks, also removes
- * the chunk from the B-tree.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol, koziol@hdfgroup.org
- * May 3, 2007
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D_istore_prune_remove(void *item, void UNUSED *key, void *op_data)
-{
- H5D_istore_sl_ck_t *sl_node = (H5D_istore_sl_ck_t *)item; /* Temporary pointer to chunk to remove */
- H5D_istore_sl_rm_t *rm_info = (H5D_istore_sl_rm_t *)op_data; /* Information needed for removing chunk from B-tree */
- H5D_istore_ud0_t bt_udata; /* User data for B-tree removal routine */
- herr_t ret_value = H5_ITER_CONT; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_istore_prune_remove)
-
- /* Sanity checks */
- HDassert(sl_node);
- HDassert(rm_info);
-
- /* Initialize the user data for the B-tree callback */
- HDmemset(&bt_udata, 0, sizeof bt_udata);
- bt_udata.key = sl_node->key;
- bt_udata.mesg = rm_info->mesg;
-
- /* Remove */
- if(H5B_remove(rm_info->f, rm_info->dxpl_id, H5B_ISTORE, rm_info->mesg->u.chunk.addr, &bt_udata) < 0)
- HGOTO_ERROR(H5E_IO, H5E_CANTINIT, H5_ITER_ERROR, "unable to remove entry")
-
- /* Free the chunk checking node */
- H5FL_FREE(H5D_istore_sl_ck_t, sl_node);
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5D_istore_prune_remove() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_prune_by_extent
- *
- * Purpose: This function searches for chunks that are no longer necessary both in the
- * raw data cache and in the B-tree.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
- * Algorithm: Robb Matzke
- * March 27, 2002
- *
- * The algorithm is:
- *
- * For chunks that are no longer necessary:
- *
- * 1. Search in the raw data cache for each chunk
- * 2. If found then preempt it from the cache
- * 3. Search in the B-tree for each chunk
- * 4. If found then remove it from the B-tree and deallocate file storage for the chunk
- *
- * This example shows a 2d dataset of 90x90 with a chunk size of 20x20.
- *
- *
- * 0 20 40 60 80 90 100
- * 0 +---------+---------+---------+---------+-----+...+
- * |:::::X:::::::::::::: : : | :
- * |:::::::X:::::::::::: : : | : Key
- * |::::::::::X::::::::: : : | : --------
- * |::::::::::::X::::::: : : | : +-+ Dataset
- * 20+::::::::::::::::::::.........:.........:.....+...: | | Extent
- * | :::::X::::: : : | : +-+
- * | ::::::::::: : : | :
- * | ::::::::::: : : | : ... Chunk
- * | :::::::X::: : : | : : : Boundary
- * 40+.........:::::::::::.........:.........:.....+...: :.:
- * | : : : : | :
- * | : : : : | : ... Allocated
- * | : : : : | : ::: & Filled
- * | : : : : | : ::: Chunk
- * 60+.........:.........:.........:.........:.....+...:
- * | : :::::::X::: : | : X Element
- * | : ::::::::::: : | : Written
- * | : ::::::::::: : | :
- * | : ::::::::::: : | :
- * 80+.........:.........:::::::::::.........:.....+...: O Fill Val
- * | : : ::::::::::: | : Explicitly
- * | : : ::::::X:::: | : Written
- * 90+---------+---------+---------+---------+-----+ :
- * : : : ::::::::::: :
- * 100:.........:.........:.........:::::::::::.........:
- *
- *
- * We have 25 total chunks for this dataset, 5 of which have space
- * allocated in the file because they were written to one or more
- * elements. These five chunks (and only these five) also have entries in
- * the storage B-tree for this dataset.
- *
- * Now lets say we want to shrink the dataset down to 70x70:
- *
- *
- * 0 20 40 60 70 80 90 100
- * 0 +---------+---------+---------+----+----+-----+...+
- * |:::::X:::::::::::::: : | : | :
- * |:::::::X:::::::::::: : | : | : Key
- * |::::::::::X::::::::: : | : | : --------
- * |::::::::::::X::::::: : | : | : +-+ Dataset
- * 20+::::::::::::::::::::.........:....+....:.....|...: | | Extent
- * | :::::X::::: : | : | : +-+
- * | ::::::::::: : | : | :
- * | ::::::::::: : | : | : ... Chunk
- * | :::::::X::: : | : | : : : Boundary
- * 40+.........:::::::::::.........:....+....:.....|...: :.:
- * | : : : | : | :
- * | : : : | : | : ... Allocated
- * | : : : | : | : ::: & Filled
- * | : : : | : | : ::: Chunk
- * 60+.........:.........:.........:....+....:.....|...:
- * | : :::::::X::: | : | : X Element
- * | : ::::::::::: | : | : Written
- * +---------+---------+---------+----+ : | :
- * | : ::::::::::: : | :
- * 80+.........:.........:::::::::X:.........:.....|...: O Fill Val
- * | : : ::::::::::: | : Explicitly
- * | : : ::::::X:::: | : Written
- * 90+---------+---------+---------+---------+-----+ :
- * : : : ::::::::::: :
- * 100:.........:.........:.........:::::::::::.........:
- *
- *
- * That means that the nine chunks along the bottom and right side should
- * no longer exist. Of those nine chunks, (0,80), (20,80), (40,80),
- * (60,80), (80,80), (80,60), (80,40), (80,20), and (80,0), one is actually allocated
- * that needs to be released.
- * To release the chunks, we traverse the B-tree to obtain a list of unused
- * allocated chunks, and then call H5B_remove() for each chunk.
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5D_istore_prune_by_extent(const H5D_io_info_t *io_info, const hsize_t *old_dims)
-{
- H5D_t *dset = io_info->dset; /* Local pointer to the dataset info */
- const H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk); /*raw data chunk cache */
- H5D_rdcc_ent_t *ent = NULL, *next = NULL; /*cache entry */
- H5D_istore_it_ud3_t udata; /*B-tree pass-through */
- H5D_istore_sl_rm_t rm_info; /* User data for skip list destroy callback */
- hsize_t curr_dims[H5O_LAYOUT_NDIMS]; /*current dataspace dimensions */
- hsize_t chunks[H5O_LAYOUT_NDIMS]; /*current number of chunks in each dimension */
- hsize_t down_chunks[H5O_LAYOUT_NDIMS]; /* "down" size of number of elements in each dimension */
- unsigned rank; /* Current # of dimensions */
- unsigned u; /* Local index variable */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5D_istore_prune_by_extent, FAIL)
-
- /* Check args */
- HDassert(io_info);
- HDassert(dset && H5D_CHUNKED == dset->shared->layout.type);
- HDassert(dset->shared->layout.u.chunk.ndims > 0 && dset->shared->layout.u.chunk.ndims <= H5O_LAYOUT_NDIMS);
- HDassert(H5F_addr_defined(dset->shared->layout.u.chunk.addr));
-
- /* Go get the rank & dimensions */
- rank = dset->shared->layout.u.chunk.ndims - 1;
- if(H5S_get_simple_extent_dims(dset->shared->space, curr_dims, NULL) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get dataset dimensions")
-
- /*-------------------------------------------------------------------------
- * Figure out what chunks are no longer in use for the specified extent
- * and release them from the linked list raw data cache
- *-------------------------------------------------------------------------
- */
- for(ent = rdcc->head; ent; ent = next) {
- /* Get pointer to next extry in cache, in case this one is evicted */
- next = ent->next;
-
- /* Check for chunk offset outside of new dimensions */
- for(u = 0; u < rank; u++)
- if((hsize_t)ent->offset[u] > curr_dims[u]) {
-#ifdef H5D_ISTORE_DEBUG
- HDfputs("cache:remove:[", stderr);
- for(u = 0; u < rank; u++)
- HDfprintf(stderr, "%s%Hd", (u ? ", " : ""), ent->offset[u]);
- HDfputs("]\n", stderr);
-#endif
-
- /* Preempt the entry from the cache, but do not flush it to disk */
- if(H5D_istore_preempt(io_info, ent, FALSE) < 0)
- HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to preempt chunk")
-
- /* Break out of loop, chunk is evicted */
- break;
- } /* end if */
- } /* end for */
-
- /* Round up to the next integer # of chunks, to accomodate partial chunks */
- for(u = 0; u < rank; u++)
- chunks[u] = ((old_dims[u] + dset->shared->layout.u.chunk.dim[u]) - 1) / dset->shared->layout.u.chunk.dim[u];
-
- /* Get the "down" sizes for each dimension */
- if(H5V_array_down(rank, chunks, down_chunks) < 0)
- HGOTO_ERROR(H5E_IO, H5E_BADVALUE, FAIL, "can't compute 'down' sizes")
-
- /* Initialize the user data for the iteration */
- HDmemset(&udata, 0, sizeof udata);
- udata.common.mesg = &dset->shared->layout;
- udata.dims = curr_dims;
- udata.down_chunks = down_chunks;
-
- /* Initialize the skip list that will hold the chunks outside the dimensions */
- if(NULL == (udata.outside = H5SL_create(H5SL_TYPE_HSIZE, 0.5, (size_t)H5D_ISTORE_DEFAULT_SKIPLIST_HEIGHT)))
- HGOTO_ERROR(H5E_IO, H5E_CANTCREATE, FAIL, "can't create skip list for chunks outside new dimensions")
-
- /* Iterate over chunks in dataset, creating a list of chunks which are
- * now completely outside the dataset's dimensions.
- *
- * Note: It would be more efficient to create a new B-tree routine that
- * performed a "remove if" operation on the B-tree and remove all
- * the chunks that were outside the dataset's dimensions through
- * that routine. However, that's a fair amount of work and it's
- * unlikely that shrinking a dataset is a performance critical
- * operation. - QAK
- */
- if(H5B_iterate(dset->oloc.file, io_info->dxpl_id, H5B_ISTORE, H5D_istore_prune_check, dset->shared->layout.u.chunk.addr, &udata) < 0)
- HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to iterate over B-tree")
-
- /* Set up user data for skip list callback */
- rm_info.f = dset->oloc.file;
- rm_info.dxpl_id = io_info->dxpl_id;
- rm_info.mesg = &dset->shared->layout;
-
- /* Destroy the skip list, deleting the chunks in the callback */
- H5SL_destroy(udata.outside, H5D_istore_prune_remove, &rm_info);
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_istore_prune_by_extent() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_remove
- *
- * Purpose: Removes chunks that are no longer necessary in the B-tree.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Robb Matzke
- * Pedro Vicente, pvn@ncsa.uiuc.edu
- * March 28, 2002
- *
- *-------------------------------------------------------------------------
- */
-/* ARGSUSED */
-static H5B_ins_t
-H5D_istore_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key /*in,out */ ,
- hbool_t *lt_key_changed /*out */ ,
- void UNUSED * _udata /*in,out */ ,
- void UNUSED * _rt_key /*in,out */ ,
- hbool_t *rt_key_changed /*out */ )
-{
- H5D_istore_key_t *lt_key = (H5D_istore_key_t *)_lt_key;
- H5B_ins_t ret_value=H5B_INS_REMOVE; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_istore_remove)
-
- /* Remove raw data chunk from file */
- if(H5MF_xfree(f, H5FD_MEM_DRAW, dxpl_id, addr, (hsize_t)lt_key->nbytes)<0)
- HGOTO_ERROR(H5E_STORAGE, H5E_CANTFREE, H5B_INS_ERROR, "unable to free chunk")
-
- /* Mark keys as unchanged */
- *lt_key_changed = FALSE;
- *rt_key_changed = FALSE;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_istore_remove() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_initialize_by_extent
- *
- * Purpose: This function searches for chunks that have to be initialized with the fill
- * value both in the raw data cache and in the B-tree.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
- * April 4, 2002
- *
- * Comments:
- *
- * (See the example of H5D_istore_prune_by_extent)
- * Next, there are seven chunks where the database extent boundary is
- * within the chunk. We find those seven just like we did with the previous nine.
- * Fot the ones that are allocated we initialize the part that lies outside the boundary
- * with the fill value.
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5D_istore_initialize_by_extent(H5D_io_info_t *io_info)
-{
- H5S_t *space_chunk = NULL; /* Dataspace for a chunk */
- H5D_t *dset = io_info->dset; /* Local pointer to the dataset info */
- const H5O_layout_t *layout = &(dset->shared->layout); /* Dataset's layout */
- H5D_storage_t store; /* Dataset storage information */
- H5D_fill_buf_info_t fb_info; /* Dataset's fill buffer info */
- hbool_t fb_info_init = FALSE; /* Whether the fill value buffer has been initialized */
- hsize_t dset_dims[H5O_LAYOUT_NDIMS]; /* Current dataspace dimensions */
- hsize_t chunk_dims[H5O_LAYOUT_NDIMS]; /* Current chunk dimensions */
- hsize_t chunk_offset[H5O_LAYOUT_NDIMS]; /* Logical location of the chunks */
- hsize_t hyper_start[H5O_LAYOUT_NDIMS]; /* Starting location of hyperslab */
- hsize_t nchunks[H5O_LAYOUT_NDIMS]; /* Current number of chunks in each dimension */
- hsize_t down_chunks[H5O_LAYOUT_NDIMS]; /* "down" size of number of elements in each dimension */
- hsize_t bytes_per_chunk; /* Bytes in chunk */
- int srank; /* # of chunk dimensions (signed) */
- unsigned rank; /* # of chunk dimensions */
- hbool_t carry; /* Flag to indicate that chunk increment carrys to higher dimension (sorta) */
- unsigned u; /* Local index variable */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5D_istore_initialize_by_extent, FAIL)
-
- /* Check args */
- HDassert(io_info);
- HDassert(io_info->dset && H5D_CHUNKED == layout->type);
- HDassert(layout->u.chunk.ndims > 0 && layout->u.chunk.ndims <= H5O_LAYOUT_NDIMS);
- HDassert(H5F_addr_defined(layout->u.chunk.addr));
-
- /* Go get the rank & dimensions */
- if((srank = H5S_get_simple_extent_dims(dset->shared->space, dset_dims, NULL)) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get dataset dimensions")
- H5_ASSIGN_OVERFLOW(rank, srank, int, unsigned);
-
- /* Set size of lowest chunk dimension (the dataset element size) */
- dset_dims[rank] = layout->u.chunk.dim[rank];
-
- /* Compute the number of chunks in dataset & the # of bytes in a chunk */
- /* (round up to the next integer # of chunks, to accomodate partial chunks) */
- for(u = 0, bytes_per_chunk = layout->u.chunk.dim[rank]; u < rank; u++) {
- nchunks[u] = ((dset_dims[u] - 1) / layout->u.chunk.dim[u]) + 1;
- bytes_per_chunk *= layout->u.chunk.dim[u];
- } /* end for */
-
- /* Get the "down" sizes for each dimension */
- if(H5V_array_down(rank, nchunks, down_chunks) < 0)
- HGOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "can't compute 'down' sizes")
-
- /* Create a data space for a chunk & set the extent */
- for(u = 0; u < rank; u++)
- chunk_dims[u] = layout->u.chunk.dim[u];
- if(NULL == (space_chunk = H5S_create_simple(rank, chunk_dims, NULL)))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create simple dataspace")
-
- /* Point to local dataset storage info */
- HDassert(io_info->store == NULL); /* Make certain we aren't blowing anything away */
- io_info->store = &store;
-
- /* Reset hyperslab start array */
- HDmemset(hyper_start, 0, sizeof(hyper_start));
-
- /* Initialize current chunk offset to the origin (0, 0, 0, ...) */
- HDmemset(chunk_offset, 0, sizeof(chunk_offset));
-
- /* Loop over all chunks */
- carry = FALSE;
- while(!carry) {
- hbool_t found; /* Initialize this entry */
- int i; /* Local index variable */
-
- /*
- * Figure out what chunks have to be initialized. These are the chunks where the dataspace
- * extent boundary is within the chunk
- */
- found = FALSE;
- for(u = 0; u < rank; u++)
- if((chunk_offset[u] + layout->u.chunk.dim[u]) > dset_dims[u]) {
- found = TRUE;
- break;
- } /* end if */
-
- if(found) {
- H5S_sel_iter_t chunk_iter; /* Memory selection iteration info */
- hssize_t nelmts; /* Number of data elements */
- hsize_t count[H5O_LAYOUT_NDIMS]; /* Element count of hyperslab */
- uint8_t *chunk; /* The file chunk */
- unsigned idx_hint; /* Which chunk we're dealing with */
- hsize_t bytes_accessed; /* Bytes accessed in chunk */
-
- /* Initialize the fill value buffer, if necessary */
- if(!fb_info_init) {
- if(H5D_fill_init(&fb_info, NULL, FALSE, NULL, NULL, NULL, NULL,
- &dset->shared->dcpl_cache.fill,
- dset->shared->type, dset->shared->type_id, (size_t)(bytes_per_chunk / layout->u.chunk.dim[rank]),
- io_info->dxpl_cache->max_temp_buf, io_info->dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize fill buffer info")
- fb_info_init = TRUE;
- } /* end if */
-
- /* Compute the # of elements to leave with existing value, in each dimension */
- for(u = 0; u < rank; u++)
- count[u] = MIN(layout->u.chunk.dim[u], (dset_dims[u] - chunk_offset[u]));
-
-#ifdef H5D_ISTORE_DEBUG
- HDfputs("cache:initialize:offset:[", stdout);
- for(u = 0; u < rank; u++)
- HDfprintf(stdout, "%s%Hd", u ? ", " : "", chunk_offset[u]);
- HDfputs("]", stdout);
- HDfputs(":count:[", stdout);
- for(u = 0; u < rank; u++)
- HDfprintf(stdout, "%s%Hd", u ? ", " : "", count[u]);
- HDfputs("]\n", stdout);
-#endif
-
- /* Select all elements in chunk, to begin with */
- if(H5S_select_all(space_chunk, TRUE) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to select space")
-
- /* "Subtract out" the elements to keep */
- if(H5S_select_hyperslab(space_chunk, H5S_SELECT_NOTB, hyper_start, NULL, count, NULL) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to select hyperslab")
-
- /* Calculate the index of this chunk */
- if(H5V_chunk_index(rank, chunk_offset, layout->u.chunk.dim, down_chunks, &store.chunk.index) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index")
-
- /* Lock the chunk into the cache, to get a pointer to the chunk buffer */
- store.chunk.offset = chunk_offset;
- if(NULL == (chunk = H5D_istore_lock(io_info, NULL, FALSE, &idx_hint)))
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to read raw data chunk")
-
-
- /* Fill the selection in the memory buffer */
- /* Use the size of the elements in the chunk directly instead of */
- /* relying on the fill.size, which might be set to 0 if there is */
- /* no fill-value defined for the dataset -QAK */
-
- /* Get the number of elements in the selection */
- nelmts = H5S_GET_SELECT_NPOINTS(space_chunk);
- HDassert(nelmts >= 0);
- H5_CHECK_OVERFLOW(nelmts, hssize_t, size_t);
-
- /* Check for VL datatype & non-default fill value */
- if(fb_info.has_vlen_fill_type)
- /* Re-fill the buffer to use for this I/O operation */
- if(H5D_fill_refill_vl(&fb_info, (size_t)nelmts, io_info->dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "can't refill fill value buffer")
-
- /* Create a selection iterator for scattering the elements to memory buffer */
- if(H5S_select_iter_init(&chunk_iter, space_chunk, layout->u.chunk.dim[rank]) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize chunk selection information")
-
- /* Scatter the data into memory */
- if(H5D_select_mscat(fb_info.fill_buf, space_chunk, &chunk_iter, (size_t)nelmts, io_info->dxpl_cache, chunk/*out*/) < 0) {
- H5S_SELECT_ITER_RELEASE(&chunk_iter);
- HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "scatter failed")
- } /* end if */
-
- /* Release the selection iterator */
- if(H5S_SELECT_ITER_RELEASE(&chunk_iter) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
-
-
- /* The number of bytes accessed in the chunk */
- /* (i.e. the bytes replaced with fill values) */
- bytes_accessed = nelmts * layout->u.chunk.dim[rank];
-
- /* Release lock on chunk */
- H5_CHECK_OVERFLOW(bytes_accessed, hsize_t, size_t);
- if(H5D_istore_unlock(io_info, TRUE, idx_hint, chunk, (size_t)bytes_accessed) < 0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to unlock raw data chunk")
- } /* end if */
-
- /* Increment indices */
- carry = TRUE;
- for(i = (int)(rank - 1); i >= 0; --i) {
- chunk_offset[i] += layout->u.chunk.dim[i];
- if(chunk_offset[i] >= dset_dims[i])
- chunk_offset[i] = 0;
- else {
- carry = FALSE;
- break;
- } /* end else */
- } /* end for */
- } /* end while */
-
-done:
- /* Release resources */
- if(space_chunk && H5S_close(space_chunk) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataspace")
- if(fb_info_init && H5D_fill_term(&fb_info) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release fill buffer info")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_istore_initialize_by_extent() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_delete
- *
- * Purpose: Delete raw data storage for entire dataset (i.e. all chunks)
- *
- * Return: Success: Non-negative
- * Failure: negative
- *
- * Programmer: Quincey Koziol
- * Thursday, March 20, 2003
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5D_istore_delete(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout)
-{
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5D_istore_delete, FAIL)
-
- /* Check if the B-tree has been created in the file */
- if(H5F_addr_defined(layout->u.chunk.addr)) {
- H5O_layout_t tmp_layout=*layout;/* Local copy of layout info */
- H5D_istore_ud0_t udata; /* User data for B-tree iterator call */
-
- /* Set up user data for B-tree deletion */
- HDmemset(&udata, 0, sizeof udata);
- udata.mesg = &tmp_layout;
-
- /* Allocate the shared structure */
- if(H5D_istore_shared_create(f, &tmp_layout)<0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create wrapper for shared B-tree info")
-
- /* Delete entire B-tree */
- if(H5B_delete(f, dxpl_id, H5B_ISTORE, tmp_layout.u.chunk.addr, &udata)<0)
- HGOTO_ERROR(H5E_IO, H5E_CANTDELETE, 0, "unable to delete chunk B-tree")
-
- /* Free the raw B-tree node buffer */
- if(tmp_layout.u.chunk.btree_shared==NULL)
- HGOTO_ERROR(H5E_IO, H5E_CANTFREE, FAIL, "ref-counted page nil")
- if(H5RC_DEC(tmp_layout.u.chunk.btree_shared)<0)
- HGOTO_ERROR(H5E_IO, H5E_CANTFREE, FAIL, "unable to decrement ref-counted page")
- } /* end if */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_istore_delete() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_update_cache
- *
- * Purpose: Update any cached chunks index values after the dataspace
- * size has changed
- *
- * Return: Success: Non-negative
- * Failure: negative
- *
- * Programmer: Quincey Koziol
- * Saturday, May 29, 2004
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5D_istore_update_cache(H5D_t *dset, hid_t dxpl_id)
-{
- H5D_io_info_t io_info; /* Temporary I/O info object */
- H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk); /*raw data chunk cache */
- H5D_rdcc_ent_t *ent, *next; /*cache entry */
- H5D_rdcc_ent_t *old_ent; /* Old cache entry */
- H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */
- H5D_dxpl_cache_t *dxpl_cache=&_dxpl_cache; /* Data transfer property cache */
- unsigned rank; /*current # of dimensions */
- hsize_t curr_dims[H5O_LAYOUT_NDIMS]; /*current dataspace dimensions */
- hsize_t chunks[H5O_LAYOUT_NDIMS]; /*current number of chunks in each dimension */
- hsize_t down_chunks[H5O_LAYOUT_NDIMS]; /* "down" size of number of elements in each dimension */
- unsigned u; /*counters */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5D_istore_update_cache, FAIL)
-
- /* Check args */
- assert(dset && H5D_CHUNKED == dset->shared->layout.type);
- assert(dset->shared->layout.u.chunk.ndims > 0 && dset->shared->layout.u.chunk.ndims <= H5O_LAYOUT_NDIMS);
-
- /* Go get the rank & dimensions */
- rank = dset->shared->layout.u.chunk.ndims-1;
- if(H5S_get_simple_extent_dims(dset->shared->space, curr_dims, NULL) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get dataset dimensions")
-
- /* Round up to the next integer # of chunks, to accomodate partial chunks */
- for(u = 0; u < rank; u++)
- chunks[u] = ((curr_dims[u]+dset->shared->layout.u.chunk.dim[u])-1) / dset->shared->layout.u.chunk.dim[u];
-
- /* Get the "down" sizes for each dimension */
- if(H5V_array_down(rank,chunks,down_chunks) < 0)
- HGOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, FAIL, "can't compute 'down' sizes")
-
- /* Fill the DXPL cache values for later use */
- if (H5D_get_dxpl_cache(dxpl_id,&dxpl_cache) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache")
-
- /* Construct dataset I/O info */
- H5D_BUILD_IO_INFO(&io_info,dset,dxpl_cache,dxpl_id,NULL);
-
- /* Recompute the index for each cached chunk that is in a dataset */
- for(ent = rdcc->head; ent; ent = next) {
- hsize_t idx; /* Chunk index */
- unsigned old_idx; /* Previous index number */
-
- /* Get the pointer to the next cache entry */
- next = ent->next;
-
- /* Calculate the index of this chunk */
- if(H5V_chunk_index(rank,ent->offset,dset->shared->layout.u.chunk.dim,down_chunks,&idx)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index")
-
- /* Compute the index for the chunk entry */
- old_idx=ent->idx; /* Save for later */
- ent->idx=H5D_HASH(dset->shared,idx);
-
- if(old_idx!=ent->idx) {
- /* Check if there is already a chunk at this chunk's new location */
- old_ent = rdcc->slot[ent->idx];
- if(old_ent!=NULL) {
- assert(old_ent->locked==0);
-
- /* Check if we are removing the entry we would walk to next */
- if(old_ent==next)
- next=old_ent->next;
-
- /* Remove the old entry from the cache */
- if (H5D_istore_preempt(&io_info, old_ent, TRUE )<0)
- HGOTO_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "unable to flush one or more raw data chunks")
- } /* end if */
-
- /* Insert this chunk into correct location in hash table */
- rdcc->slot[ent->idx]=ent;
-
- /* Null out previous location */
- rdcc->slot[old_idx]=NULL;
- } /* end if */
- } /* end for */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_istore_update_cache() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_copy
- *
- * Purpose: copy an indexed storage B-tree from SRC file to DST file.
- *
- * Return: Non-negative on success (with the ISTORE argument initialized
- * and ready to write to an object header). Negative on failure.
- *
- * Programmer: Peter Cao
- * August 20, 2005
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5D_istore_copy(H5F_t *f_src, H5O_layout_t *layout_src, H5F_t *f_dst,
- H5O_layout_t *layout_dst, H5T_t *dt_src, H5O_copy_t *cpy_info, H5O_pline_t *pline, hid_t dxpl_id)
-{
- H5D_istore_it_ud4_t udata;
- H5T_path_t *tpath_src_mem = NULL, *tpath_mem_dst = NULL; /* Datatype conversion paths */
- hid_t tid_src = -1; /* Datatype ID for source datatype */
- hid_t tid_dst = -1; /* Datatype ID for destination datatype */
- hid_t tid_mem = -1; /* Datatype ID for memory datatype */
- size_t buf_size; /* Size of copy buffer */
- size_t reclaim_buf_size; /* Size of reclaim buffer */
- void *buf = NULL; /* Buffer for copying data */
- void *bkg = NULL; /* Buffer for background during type conversion */
- void *reclaim_buf = NULL; /* Buffer for reclaiming data */
- H5S_t *buf_space = NULL; /* Dataspace describing buffer */
- hid_t sid_buf = -1; /* ID for buffer dataspace */
- size_t nelmts = 0; /* Number of elements in buffer */
- hbool_t do_convert = FALSE; /* Indicate that type conversions should be performed */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5D_istore_copy, FAIL)
-
- /* Check args */
- HDassert(f_src);
- HDassert(f_dst);
- HDassert(layout_src && H5D_CHUNKED == layout_src->type);
- HDassert(layout_dst && H5D_CHUNKED == layout_dst->type);
- HDassert(dt_src);
-
- /* Create datatype ID for src datatype */
- if((tid_src = H5I_register(H5I_DATATYPE, dt_src)) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register source file datatype")
-
- /* Create shared B-tree info for each file */
- if(H5D_istore_shared_create(f_src, layout_src) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create wrapper for shared B-tree info")
- if(H5D_istore_shared_create(f_dst, layout_dst) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create wrapper for shared B-tree info")
-
- /* Check if we need to create the B-tree in the dest. file */
- if(layout_dst->u.chunk.addr == HADDR_UNDEF) {
- /* Create the root of the B-tree that describes chunked storage */
- if(H5D_istore_create(f_dst, dxpl_id, layout_dst) < 0)
- HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to initialize chunked storage")
- } /* end if */
-
- /* If there's a VLEN source datatype, set up type conversion information */
- if(H5T_detect_class(dt_src, H5T_VLEN) > 0) {
- H5T_t *dt_dst; /* Destination datatype */
- H5T_t *dt_mem; /* Memory datatype */
- size_t mem_dt_size; /* Memory datatype size */
- size_t tmp_dt_size; /* Temp. datatype size */
- size_t max_dt_size; /* Max atatype size */
- hsize_t buf_dim; /* Dimension for buffer */
- unsigned u;
-
- /* create a memory copy of the variable-length datatype */
- if(NULL == (dt_mem = H5T_copy(dt_src, H5T_COPY_TRANSIENT)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy")
- if((tid_mem = H5I_register(H5I_DATATYPE, dt_mem)) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register memory datatype")
-
- /* create variable-length datatype at the destinaton file */
- if(NULL == (dt_dst = H5T_copy(dt_src, H5T_COPY_TRANSIENT)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy")
- if(H5T_set_loc(dt_dst, f_dst, H5T_LOC_DISK) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "cannot mark datatype on disk")
- if((tid_dst = H5I_register(H5I_DATATYPE, dt_dst)) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register destination file datatype")
-
- /* Set up the conversion functions */
- if(NULL == (tpath_src_mem = H5T_path_find(dt_src, dt_mem, NULL, NULL, dxpl_id, FALSE)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert between src and mem datatypes")
- if(NULL == (tpath_mem_dst = H5T_path_find(dt_mem, dt_dst, NULL, NULL, dxpl_id, FALSE)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert between mem and dst datatypes")
-
- /* Determine largest datatype size */
- if(0 == (max_dt_size = H5T_get_size(dt_src)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to determine datatype size")
- if(0 == (mem_dt_size = H5T_get_size(dt_mem)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to determine datatype size")
- max_dt_size = MAX(max_dt_size, mem_dt_size);
- if(0 == (tmp_dt_size = H5T_get_size(dt_dst)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to determine datatype size")
- max_dt_size = MAX(max_dt_size, tmp_dt_size);
-
- /* Compute the number of elements per chunk */
- nelmts = 1;
- for(u = 0; u < (layout_src->u.chunk.ndims - 1); u++)
- nelmts *= layout_src->u.chunk.dim[u];
-
- /* Create the space and set the initial extent */
- buf_dim = nelmts;
- if(NULL == (buf_space = H5S_create_simple((unsigned)1, &buf_dim, NULL)))
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create simple dataspace")
-
- /* Atomize */
- if((sid_buf = H5I_register(H5I_DATASPACE, buf_space)) < 0) {
- H5S_close(buf_space);
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace ID")
- } /* end if */
-
- /* Set initial buffer sizes */
- buf_size = nelmts * max_dt_size;
- reclaim_buf_size = nelmts * mem_dt_size;
-
- /* Allocate memory for reclaim buf */
- if(NULL == (reclaim_buf = H5MM_malloc(reclaim_buf_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for raw data chunk")
-
- /* Indicate that type conversion should be performed */
- do_convert = TRUE;
- } /* end if */
- else {
- if(H5T_get_class(dt_src, FALSE) == H5T_REFERENCE) {
- /* Indicate that type conversion should be performed */
- do_convert = TRUE;
- } /* end if */
-
- buf_size = layout_src->u.chunk.size;
- reclaim_buf_size = 0;
- } /* end else */
-
- /* Set up conversion buffer, if appropriate */
- if(do_convert) {
- /* Allocate background memory for converting the chunk */
- if(NULL == (bkg = H5MM_malloc(buf_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for raw data chunk")
-
- /* Check for reference datatype and no expanding references & clear background buffer */
- if(!cpy_info->expand_ref &&
- ((H5T_get_class(dt_src, FALSE) == H5T_REFERENCE) && (f_src != f_dst)))
- /* Reset value to zero */
- HDmemset(bkg, 0, buf_size);
- } /* end if */
-
- /* Allocate memory for copying the chunk */
- if(NULL == (buf = H5MM_malloc(buf_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for raw data chunk")
-
- /* Initialize the callback structure for the source */
- HDmemset(&udata, 0, sizeof udata);
- udata.common.mesg = layout_src;
- udata.file_src = f_src;
- udata.addr_dst = layout_dst->u.chunk.addr;
- udata.buf = buf;
- udata.bkg = bkg;
- udata.buf_size = buf_size;
- udata.tid_src = tid_src;
- udata.tid_mem = tid_mem;
- udata.tid_dst = tid_dst;
- udata.dt_src = dt_src;
- udata.do_convert = do_convert;
- udata.tpath_src_mem = tpath_src_mem;
- udata.tpath_mem_dst = tpath_mem_dst;
- udata.reclaim_buf = reclaim_buf;
- udata.reclaim_buf_size = reclaim_buf_size;
- udata.buf_space = buf_space;
- udata.nelmts = nelmts;
- udata.pline = pline;
- udata.file_dst = f_dst;
- udata.cpy_info = cpy_info;
-
- /* copy the chunked data by iteration */
- if(H5B_iterate(f_src, dxpl_id, H5B_ISTORE, H5D_istore_iter_copy, layout_src->u.chunk.addr, &udata) < 0)
- HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to iterate over chunk B-tree")
-
- /* I/O buffers may have been re-allocated */
- buf = udata.buf;
- bkg = udata.bkg;
-
-done:
- if(sid_buf > 0)
- if(H5I_dec_ref(sid_buf) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary dataspace ID")
- if(tid_src > 0)
- if(H5I_dec_ref(tid_src) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
- if(tid_dst > 0)
- if(H5I_dec_ref(tid_dst) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
- if(tid_mem > 0)
- if(H5I_dec_ref(tid_mem) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
- if(buf)
- H5MM_xfree(buf);
- if(bkg)
- H5MM_xfree(bkg);
- if(reclaim_buf)
- H5MM_xfree(reclaim_buf);
-
- if(H5RC_DEC(layout_src->u.chunk.btree_shared) < 0)
- HDONE_ERROR(H5E_IO, H5E_CANTFREE, FAIL, "unable to decrement ref-counted page")
-
- if(H5RC_DEC(layout_dst->u.chunk.btree_shared) < 0)
- HDONE_ERROR(H5E_IO, H5E_CANTFREE, FAIL, "unable to decrement ref-counted page")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_istore_copy() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_bh_size
- *
- * Purpose: Retrieve the amount of B-tree storage for chunked dataset
- *
- * Return: Success: Non-negative
- * Failure: negative
- *
- * Programmer: Vailin Choi
- * June 8, 2007
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5D_istore_bh_info(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout, hsize_t *btree_size)
-{
- H5D_istore_it_ud1_t udata; /* User-data for loading istore nodes */
- H5B_info_ud_t bh_udata; /* User-data for B-tree size iteration */
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI(H5D_istore_bh_info, FAIL)
-
- /* Check args */
- HDassert(f);
- HDassert(layout);
- HDassert(btree_size);
-
- /* Initialize the shared info for the B-tree traversal */
- if(H5D_istore_shared_create(f, layout) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create wrapper for shared B-tree info")
-
- /* Initialize istore node user-data */
- HDmemset(&udata, 0, sizeof udata);
- udata.common.mesg = layout;
-
- /* Iterate over B-tree, accumulating metadata size */
- bh_udata.udata = &udata;
- bh_udata.btree_size = btree_size;
- if(H5B_iterate_size(f, dxpl_id, H5B_ISTORE, NULL, layout->u.chunk.addr, &bh_udata) < 0)
- HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "unable to iterate over chunk B-tree")
-
-done:
- if(layout->u.chunk.btree_shared == NULL)
- HDONE_ERROR(H5E_IO, H5E_CANTFREE, FAIL, "ref-counted page nil")
- if(H5RC_DEC(layout->u.chunk.btree_shared) < 0)
- HDONE_ERROR(H5E_IO, H5E_CANTFREE, FAIL, "unable to decrement ref-counted page")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_istore_bh_info() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_dump_btree
- *
- * Purpose: Prints information about the storage B-tree to the specified
- * stream.
- *
- * Return: Success: Non-negative
- *
- * Failure: negative
- *
- * Programmer: Robb Matzke
- * Wednesday, April 28, 1999
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5D_istore_dump_btree(H5F_t *f, hid_t dxpl_id, FILE *stream, unsigned ndims, haddr_t addr)
-{
- H5O_layout_t layout;
- H5D_istore_it_ud2_t udata;
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5D_istore_dump_btree, FAIL)
-
- HDmemset(&udata, 0, sizeof udata);
- layout.u.chunk.ndims = ndims;
- udata.common.mesg = &layout;
- udata.stream = stream;
- if(stream)
- HDfprintf(stream, " Address: %a\n", addr);
- if(H5B_iterate(f, dxpl_id, H5B_ISTORE, H5D_istore_iter_dump, addr, &udata)<0)
- HGOTO_ERROR(H5E_IO, H5E_CANTINIT, 0, "unable to iterate over chunk B-tree")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_istore_dump_btree() */
-
-#ifdef H5D_ISTORE_DEBUG
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_stats
- *
- * Purpose: Print raw data cache statistics to the debug stream. If
- * HEADERS is non-zero then print table column headers,
- * otherwise assume that the H5AC layer has already printed them.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Robb Matzke
- * Thursday, May 21, 1998
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5D_istore_stats (H5D_t *dset, hbool_t headers)
-{
- H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk);
- double miss_rate;
- char ascii[32];
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5D_istore_stats, FAIL)
-
- if (!H5DEBUG(AC))
- HGOTO_DONE(SUCCEED)
-
- if (headers) {
- fprintf(H5DEBUG(AC), "H5D: raw data cache statistics\n");
- fprintf(H5DEBUG(AC), " %-18s %8s %8s %8s %8s+%-8s\n",
- "Layer", "Hits", "Misses", "MissRate", "Inits", "Flushes");
- fprintf(H5DEBUG(AC), " %-18s %8s %8s %8s %8s-%-8s\n",
- "-----", "----", "------", "--------", "-----", "-------");
- }
-
-#ifdef H5AC_DEBUG
- if (H5DEBUG(AC)) headers = TRUE;
-#endif
-
- if (headers) {
- if (rdcc->nhits>0 || rdcc->nmisses>0) {
- miss_rate = 100.0 * rdcc->nmisses /
- (rdcc->nhits + rdcc->nmisses);
- } else {
- miss_rate = 0.0;
- }
- if (miss_rate > 100) {
- sprintf(ascii, "%7d%%", (int) (miss_rate + 0.5));
- } else {
- sprintf(ascii, "%7.2f%%", miss_rate);
- }
-
- fprintf(H5DEBUG(AC), " %-18s %8u %8u %7s %8d+%-9ld\n",
- "raw data chunks", rdcc->nhits, rdcc->nmisses, ascii,
- rdcc->ninits, (long)(rdcc->nflushes)-(long)(rdcc->ninits));
- }
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_istore_stats() */
-#endif /* H5D_ISTORE_DEBUG */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_istore_debug
- *
- * Purpose: Debugs a B-tree node for indexed raw data storage.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Robb Matzke
- * Thursday, April 16, 1998
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5D_istore_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent,
- int fwidth, unsigned ndims)
-{
- H5O_layout_t layout;
- H5D_istore_ud0_t udata; /* B-tree user data */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5D_istore_debug,FAIL)
-
- layout.u.chunk.ndims = ndims;
-
- /* Allocate the shared structure */
- if(H5D_istore_shared_create(f, &layout)<0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create wrapper for shared B-tree info")
-
- /* Set up B-tree user data */
- HDmemset(&udata, 0, sizeof udata);
- udata.mesg = &layout;
-
- (void)H5B_debug(f, dxpl_id, addr, stream, indent, fwidth, H5B_ISTORE, &udata);
-
- /* Free the raw B-tree node buffer */
- if(layout.u.chunk.btree_shared==NULL)
- HGOTO_ERROR(H5E_IO, H5E_CANTFREE, FAIL, "ref-counted page nil")
- if(H5RC_DEC(layout.u.chunk.btree_shared)<0)
- HGOTO_ERROR(H5E_IO, H5E_CANTFREE, FAIL, "unable to decrement ref-counted page")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_istore_debug() */
-
diff --git a/src/H5Dmpio.c b/src/H5Dmpio.c
index a6981ee..99ad001 100644
--- a/src/H5Dmpio.c
+++ b/src/H5Dmpio.c
@@ -15,7 +15,7 @@
/*
* Programmer: rky 980813
- * KY 2005 revised the code and made the change to support and optimize
+ * KY 2005 revised the code and made the change to support and optimize
* collective IO support.
* Purpose: Functions to read/write directly between app buffer and file.
*
@@ -34,12 +34,12 @@
/* Headers */
/***********/
#include "H5private.h" /* Generic Functions */
-#include "H5Iprivate.h"
#include "H5Dpkg.h" /* Datasets */
#include "H5Eprivate.h" /* Error handling */
#include "H5Fprivate.h" /* File access */
#include "H5FDprivate.h" /* File drivers */
-#include "H5MMprivate.h"
+#include "H5Iprivate.h" /* IDs */
+#include "H5MMprivate.h" /* Memory management */
#include "H5Oprivate.h" /* Object headers */
#include "H5Pprivate.h" /* Property lists */
#include "H5Sprivate.h" /* Dataspaces */
@@ -86,6 +86,7 @@
#define H5D_CHUNK_SELECT_IRREG 2
#define H5D_CHUNK_SELECT_NONE 0
+
/******************/
/* Local Typedefs */
/******************/
@@ -95,66 +96,47 @@ typedef struct H5D_chunk_addr_info_t {
H5D_chunk_info_t chunk_info;
} H5D_chunk_addr_info_t;
-/* Combine all information that needs to know for collective MPI-IO of this selection. */
-typedef struct H5D_common_coll_info_t {
- hbool_t mbt_is_derived;
- hbool_t mft_is_derived;
- size_t mpi_buf_count;
- haddr_t chunk_addr;
-} H5D_common_coll_info_t;
-
/********************/
/* Local Prototypes */
/********************/
-
-static herr_t
-H5D_multi_chunk_collective_io(H5D_io_info_t *io_info,fm_map *fm,const void *buf,
- hbool_t do_write);
-static herr_t
-H5D_multi_chunk_collective_io_no_opt(H5D_io_info_t *io_info,fm_map *fm,const void *buf,
- hbool_t do_write);
-
-static herr_t
-H5D_link_chunk_collective_io(H5D_io_info_t *io_info,fm_map *fm,const void *buf,
- hbool_t do_write,int sum_chunk);
-
-static herr_t
-H5D_inter_collective_io(H5D_io_info_t *io_info,const H5S_t *file_space,
- const H5S_t *mem_space,haddr_t addr,
- const void *buf, hbool_t do_write );
-
-static herr_t
-H5D_final_collective_io(H5D_io_info_t *io_info,MPI_Datatype*mpi_file_type,
- MPI_Datatype *mpi_buf_type,
- H5D_common_coll_info_t* coll_info,
- const void *buf, hbool_t do_write);
-static herr_t
-H5D_sort_chunk(H5D_io_info_t * io_info,
- fm_map *fm,
- H5D_chunk_addr_info_t chunk_addr_info_array[],
- int many_chunk_opt);
-
-static herr_t
-H5D_obtain_mpio_mode(H5D_io_info_t* io_info,
- fm_map *fm,
- uint8_t assign_io_mode[],
- haddr_t chunk_addr[]);
-
-static herr_t H5D_ioinfo_make_ind(H5D_io_info_t *io_info);
-static herr_t H5D_ioinfo_make_coll_opt(H5D_io_info_t *io_info);
-static herr_t H5D_ioinfo_make_coll(H5D_io_info_t *io_info);
+static herr_t H5D_chunk_collective_io(H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info, H5D_chunk_map_t *fm);
+static herr_t H5D_multi_chunk_collective_io(H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info, H5D_chunk_map_t *fm,
+ H5P_genplist_t *dx_plist);
+static herr_t H5D_multi_chunk_collective_io_no_opt(H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info, H5D_chunk_map_t *fm, H5P_genplist_t *dx_plist);
+#ifdef H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS
+static herr_t H5D_link_chunk_collective_io(H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info, H5D_chunk_map_t *fm, int sum_chunk);
+#endif /* H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS */
+static herr_t H5D_inter_collective_io(H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info, const H5S_t *file_space,
+ const H5S_t *mem_space);
+static herr_t H5D_final_collective_io(H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info, size_t nelmts, MPI_Datatype *mpi_file_type,
+ MPI_Datatype *mpi_buf_type);
+static herr_t H5D_sort_chunk(H5D_io_info_t *io_info, const H5D_chunk_map_t *fm,
+ H5D_chunk_addr_info_t chunk_addr_info_array[], int many_chunk_opt);
+static herr_t H5D_obtain_mpio_mode(H5D_io_info_t *io_info, H5D_chunk_map_t *fm,
+ H5P_genplist_t *dx_plist, uint8_t assign_io_mode[], haddr_t chunk_addr[]);
+static herr_t H5D_ioinfo_xfer_mode(H5D_io_info_t *io_info, H5P_genplist_t *dx_plist,
+ H5FD_mpio_xfer_t xfer_mode);
+static herr_t H5D_ioinfo_coll_opt_mode(H5D_io_info_t *io_info, H5P_genplist_t *dx_plist,
+ H5FD_mpio_collective_opt_t coll_opt_mode);
static herr_t H5D_mpio_get_min_chunk(const H5D_io_info_t *io_info,
- const fm_map *fm, int *min_chunkf);
+ const H5D_chunk_map_t *fm, int *min_chunkf);
static int H5D_cmp_chunk_addr(const void *addr1, const void *addr2);
static herr_t H5D_mpio_get_sum_chunk(const H5D_io_info_t *io_info,
- const fm_map *fm, int *sum_chunkf);
+ const H5D_chunk_map_t *fm, int *sum_chunkf);
/*********************/
/* Package Variables */
/*********************/
+
/*******************/
/* Local Variables */
/*******************/
@@ -175,64 +157,77 @@ static herr_t H5D_mpio_get_sum_chunk(const H5D_io_info_t *io_info,
*-------------------------------------------------------------------------
*/
htri_t
-H5D_mpio_opt_possible( const H5D_io_info_t *io_info,
- const H5S_t *mem_space, const H5S_t *file_space, const H5T_path_t *tpath)
+H5D_mpio_opt_possible(const H5D_io_info_t *io_info, const H5S_t *file_space,
+ const H5S_t *mem_space, const H5D_type_info_t *type_info,
+ const H5D_chunk_map_t *fm)
{
- int local_opinion = TRUE; /* This process's idea of whether to perform collective I/O or not */
- int consensus; /* Consensus opinion of all processes */
- int mpi_code; /* MPI error code */
- htri_t ret_value=TRUE;
+ int local_opinion = TRUE; /* This process's idea of whether to perform collective I/O or not */
+ int consensus; /* Consensus opinion of all processes */
+ int mpi_code; /* MPI error code */
+ htri_t ret_value = TRUE;
- FUNC_ENTER_NOAPI(H5D_mpio_opt_possible, FAIL);
+ FUNC_ENTER_NOAPI(H5D_mpio_opt_possible, FAIL)
/* Check args */
- assert(io_info);
- assert(mem_space);
- assert(file_space);
+ HDassert(io_info);
+ HDassert(mem_space);
+ HDassert(file_space);
+ HDassert(type_info);
/* For independent I/O, get out quickly and don't try to form consensus */
- if (io_info->dxpl_cache->xfer_mode==H5FD_MPIO_INDEPENDENT)
+ if(io_info->dxpl_cache->xfer_mode == H5FD_MPIO_INDEPENDENT)
HGOTO_DONE(FALSE);
+ /* Don't allow collective operations if datatype conversions need to happen */
+ if(!type_info->is_conv_noop) {
+ local_opinion = FALSE;
+ goto broadcast;
+ } /* end if */
+
+ /* Don't allow collective operations if data transform operations should occur */
+ if(!type_info->is_xform_noop) {
+ local_opinion = FALSE;
+ goto broadcast;
+ } /* end if */
+
/* Optimized MPI types flag must be set and it must be collective IO */
/* (Don't allow parallel I/O for the MPI-posix driver, since it doesn't do real collective I/O) */
- if (!(H5S_mpi_opt_types_g && io_info->dxpl_cache->xfer_mode==H5FD_MPIO_COLLECTIVE && !IS_H5FD_MPIPOSIX(io_info->dset->oloc.file))) {
+ if(!(H5S_mpi_opt_types_g && io_info->dxpl_cache->xfer_mode == H5FD_MPIO_COLLECTIVE
+ && !IS_H5FD_MPIPOSIX(io_info->dset->oloc.file))) {
local_opinion = FALSE;
goto broadcast;
} /* end if */
/* Check whether these are both simple or scalar dataspaces */
- if (!((H5S_SIMPLE==H5S_GET_EXTENT_TYPE(mem_space) || H5S_SCALAR==H5S_GET_EXTENT_TYPE(mem_space))
- && (H5S_SIMPLE==H5S_GET_EXTENT_TYPE(file_space) || H5S_SCALAR==H5S_GET_EXTENT_TYPE(file_space)))) {
+ if(!((H5S_SIMPLE == H5S_GET_EXTENT_TYPE(mem_space) || H5S_SCALAR == H5S_GET_EXTENT_TYPE(mem_space))
+ && (H5S_SIMPLE == H5S_GET_EXTENT_TYPE(file_space) || H5S_SCALAR == H5S_GET_EXTENT_TYPE(file_space)))) {
local_opinion = FALSE;
goto broadcast;
} /* end if */
/* Can't currently handle point selections */
- if (H5S_SEL_POINTS==H5S_GET_SELECT_TYPE(mem_space) || H5S_SEL_POINTS==H5S_GET_SELECT_TYPE(file_space)) {
+ if(H5S_SEL_POINTS == H5S_GET_SELECT_TYPE(mem_space)
+ || H5S_SEL_POINTS == H5S_GET_SELECT_TYPE(file_space)) {
local_opinion = FALSE;
goto broadcast;
} /* end if */
/* Dataset storage must be contiguous or chunked */
- if (!(io_info->dset->shared->layout.type == H5D_CONTIGUOUS ||
+ if(!(io_info->dset->shared->layout.type == H5D_CONTIGUOUS ||
io_info->dset->shared->layout.type == H5D_CHUNKED)) {
local_opinion = FALSE;
goto broadcast;
} /* end if */
- /* The handling of memory space is different for chunking
- and contiguous storage,
- For contigous storage, mem_space and file_space won't
- change when it it is doing disk IO.
- For chunking storage, mem_space will change for different
- chunks. So for chunking storage, whether we can use
- collective IO will defer until each chunk IO is reached.
- For contiguous storage, if we find MPI-IO cannot
- support complicated MPI derived data type and the shape
- of data space is not regular, we will
- set use_par_opt_io = FALSE.
- */
+ /* The handling of memory space is different for chunking and contiguous
+ * storage. For contiguous storage, mem_space and file_space won't change
+ * when it it is doing disk IO. For chunking storage, mem_space will
+ * change for different chunks. So for chunking storage, whether we can
+ * use collective IO will defer until each chunk IO is reached. For
+ * contiguous storage, if we find MPI-IO cannot support complicated MPI
+ * derived data type and the shape of data space is not regular, we will
+ * set use_par_opt_io = FALSE.
+ */
#ifndef H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS
if(io_info->dset->shared->layout.type == H5D_CONTIGUOUS)
if((H5S_SELECT_IS_REGULAR(file_space) != TRUE) ||
@@ -243,81 +238,43 @@ H5D_mpio_opt_possible( const H5D_io_info_t *io_info,
#endif
/* Don't allow collective operations if filters need to be applied */
- if(io_info->dset->shared->layout.type == H5D_CHUNKED)
- if(io_info->dset->shared->dcpl_cache.pline.nused>0) {
+ if(io_info->dset->shared->layout.type == H5D_CHUNKED) {
+ if(io_info->dset->shared->dcpl_cache.pline.nused > 0) {
local_opinion = FALSE;
goto broadcast;
} /* end if */
- /* Don't allow collective operations if datatype conversions need to happen */
- if(!H5T_path_noop(tpath)) {
- local_opinion = FALSE;
- goto broadcast;
- } /* end if */
-
- /* Don't allow collective operations if data transform operations should occur */
- if(!H5Z_xform_noop(io_info->dxpl_cache->data_xform_prop)) {
- local_opinion = FALSE;
- goto broadcast;
+/* If H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS and H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS
+ * are defined, the HDF5 library will do collective IO if the application
+ * asks for it.
+ *
+ * If H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS is not defined and one or more
+ * processes are not participating in the IO, then collective IO is not
+ * assured. The library will check each process for the number of chunks
+ * it involves. If any process involves zero chunks, the library will use
+ * independent IO mode instead.
+ */
+#ifndef H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS
+ /* Check the number of chunks to perform I/O on */
+ if(0 == H5SL_count(fm->sel_chunks)) {
+ local_opinion = FALSE;
+ goto broadcast;
+ } /* end if */
+#endif /* H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS */
} /* end if */
broadcast:
/* Form consensus opinion among all processes about whether to perform
- * collective I/O */
- if (MPI_SUCCESS != (mpi_code = MPI_Allreduce(&local_opinion, &consensus, 1, MPI_INT, MPI_LAND, io_info->comm)))
+ * collective I/O
+ */
+ if(MPI_SUCCESS != (mpi_code = MPI_Allreduce(&local_opinion, &consensus, 1, MPI_INT, MPI_LAND, io_info->comm)))
HMPI_GOTO_ERROR(FAIL, "MPI_Allreduce failed", mpi_code)
ret_value = consensus > 0 ? TRUE : FALSE;
done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* H5D_mpio_opt_possible() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_mpio_chunk_adjust_iomode
- *
- * Decription: If H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS and
- H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS are defined,
- the HDF5 library will do collective IO if the application asks for it.
-
- If H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS is not defined
- and one or more processes are not participating in the IO,
- then collective IO is not assured. The library will check
- each process for the
- number of chunks it involves. If any process involves zero chunks,
- the library will use independent IO mode instead.
- This function is only used for linked chunk IO.
- * Purpose: Checks if it is possible to do collective IO
- *
- * Return: Success: Non-negative: TRUE or FALSE
- * Failure: Negative
- *
- * Programmer: Muqun Yang
- * Monday, Feb. 13th, 2006
- *
- *-------------------------------------------------------------------------
- */
-#ifndef H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS
-herr_t
-H5D_mpio_chunk_adjust_iomode(H5D_io_info_t *io_info, const fm_map *fm)
-{
- int min_chunk;
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_mpio_chunk_adjust_iomode)
-
- if(H5D_mpio_get_min_chunk(io_info,fm,&min_chunk) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSWAP, FAIL, "unable to obtain the min chunk number of all processes");
- if(min_chunk == 0) {
- /* Switch to independent I/O */
- if(H5D_ioinfo_make_ind(io_info) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't switch to independent I/O")
- } /* end if */
-done:
FUNC_LEAVE_NOAPI(ret_value)
-}
-#endif
+} /* H5D_mpio_opt_possible() */
/*-------------------------------------------------------------------------
@@ -332,23 +289,20 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5D_mpio_select_read(H5D_io_info_t *io_info,
- size_t mpi_buf_count,
- const size_t UNUSED elmt_size,
- const H5S_t UNUSED *file_space,
- const H5S_t UNUSED *mem_space,
- haddr_t addr,
- void UNUSED *pointer,
- void *buf/*out*/)
+H5D_mpio_select_read(const H5D_io_info_t *io_info, const H5D_type_info_t UNUSED *type_info,
+ hsize_t mpi_buf_count, const H5S_t UNUSED *file_space, const H5S_t UNUSED *mem_space)
{
+ const H5D_contig_storage_t *store_contig = &(io_info->store->contig); /* Contiguous storage info for this I/O operation */
herr_t ret_value = SUCCEED;
- FUNC_ENTER_NOAPI(H5D_mpio_select_read,FAIL);
+ FUNC_ENTER_NOAPI(H5D_mpio_select_read, FAIL)
+
+ H5_CHECK_OVERFLOW(mpi_buf_count, hsize_t, size_t);
+ if(H5F_block_read(io_info->dset->oloc.file, H5FD_MEM_DRAW, store_contig->dset_addr, (size_t)mpi_buf_count, io_info->dxpl_id, io_info->u.rbuf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "can't finish collective parallel read")
- if(H5F_block_read (io_info->dset->oloc.file, H5FD_MEM_DRAW, addr, mpi_buf_count, io_info->dxpl_id, buf) < 0)
- HGOTO_ERROR(H5E_IO,H5E_READERROR,FAIL,"can't finish collective parallel read");
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_mpio_select_read() */
@@ -364,32 +318,28 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5D_mpio_select_write(H5D_io_info_t *io_info,
- size_t mpi_buf_count,
- const size_t UNUSED elmt_size,
- const H5S_t UNUSED *file_space,
- const H5S_t UNUSED *mem_space,
- haddr_t addr,
- void UNUSED *pointer,
- const void *buf)
+H5D_mpio_select_write(const H5D_io_info_t *io_info, const H5D_type_info_t UNUSED *type_info,
+ hsize_t mpi_buf_count, const H5S_t UNUSED *file_space, const H5S_t UNUSED *mem_space)
{
+ const H5D_contig_storage_t *store_contig = &(io_info->store->contig); /* Contiguous storage info for this I/O operation */
herr_t ret_value = SUCCEED;
- FUNC_ENTER_NOAPI(H5D_mpio_select_write,FAIL);
+ FUNC_ENTER_NOAPI(H5D_mpio_select_write, FAIL)
/*OKAY: CAST DISCARDS CONST QUALIFIER*/
- if(H5F_block_write (io_info->dset->oloc.file, H5FD_MEM_DRAW, addr, mpi_buf_count, io_info->dxpl_id, buf)<0)
- HGOTO_ERROR(H5E_IO,H5E_WRITEERROR,FAIL,"can't finish collective parallel write");
+ H5_CHECK_OVERFLOW(mpi_buf_count, hsize_t, size_t);
+ if(H5F_block_write(io_info->dset->oloc.file, H5FD_MEM_DRAW, store_contig->dset_addr, (size_t)mpi_buf_count, io_info->dxpl_id, io_info->u.wbuf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "can't finish collective parallel write")
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_mpio_select_write() */
/*-------------------------------------------------------------------------
- * Function: H5D_ioinfo_make_ind
+ * Function: H5D_ioinfo_xfer_mode
*
- * Purpose: Switch to MPI independent I/O
+ * Purpose: Switch to between collective & independent MPI I/O
*
* Return: Non-negative on success/Negative on failure
*
@@ -399,42 +349,42 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5D_ioinfo_make_ind(H5D_io_info_t *io_info)
+H5D_ioinfo_xfer_mode(H5D_io_info_t *io_info, H5P_genplist_t *dx_plist,
+ H5FD_mpio_xfer_t xfer_mode)
{
- H5P_genplist_t *dx_plist; /* Data transer property list */
herr_t ret_value = SUCCEED; /*return value */
- FUNC_ENTER_NOAPI_NOINIT(H5D_ioinfo_make_ind)
+ FUNC_ENTER_NOAPI_NOINIT(H5D_ioinfo_xfer_mode)
- /* Get the dataset transfer property list */
- if (NULL == (dx_plist = H5I_object(io_info->dxpl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list")
-
- /* Change the xfer_mode to independent, handle the request,
- * then set xfer_mode before return.
- */
- io_info->dxpl_cache->xfer_mode = H5FD_MPIO_INDEPENDENT;
- if(H5P_set (dx_plist, H5D_XFER_IO_XFER_MODE_NAME, &io_info->dxpl_cache->xfer_mode) < 0)
+ /* Change the xfer_mode */
+ io_info->dxpl_cache->xfer_mode = xfer_mode;
+ if(H5P_set(dx_plist, H5D_XFER_IO_XFER_MODE_NAME, &io_info->dxpl_cache->xfer_mode) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set transfer mode")
- /* Set the pointers to the non-MPI-specific routines */
- io_info->ops.read = H5D_select_read;
- io_info->ops.write = H5D_select_write;
+ /* Change the "single I/O" function pointers */
+ if(xfer_mode == H5FD_MPIO_INDEPENDENT) {
+ /* Set the pointers to the original, non-MPI-specific routines */
+ io_info->io_ops.single_read = io_info->orig.io_ops.single_read;
+ io_info->io_ops.single_write = io_info->orig.io_ops.single_write;
+ } /* end if */
+ else {
+ HDassert(xfer_mode == H5FD_MPIO_COLLECTIVE);
- /* Indicate that the transfer mode should be restored before returning
- * to user.
- */
- io_info->xfer_mode_changed=TRUE;
+ /* Set the pointers to the MPI-specific routines */
+ io_info->io_ops.single_read = H5D_mpio_select_read;
+ io_info->io_ops.single_write = H5D_mpio_select_write;
+ } /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_ioinfo_make_ind() */
+} /* end H5D_ioinfo_xfer_mode() */
/*-------------------------------------------------------------------------
- * Function: H5D_ioinfo_make_coll_opt
+ * Function: H5D_ioinfo_coll_opt_mode
*
- * Purpose: Switch to MPI independent I/O with file set view
+ * Purpose: Switch between using collective & independent MPI I/O w/file
+ * set view
*
* Return: Non-negative on success/Negative on failure
*
@@ -444,87 +394,21 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5D_ioinfo_make_coll_opt(H5D_io_info_t *io_info)
-{
- H5P_genplist_t *dx_plist; /* Data transer property list */
- herr_t ret_value = SUCCEED; /*return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_ioinfo_make_coll_opt)
-
- /* Get the dataset transfer property list */
- if (NULL == (dx_plist = H5I_object(io_info->dxpl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list")
-
- /* Change the optimial xfer_mode to independent, handle the request,
- * then set xfer_mode before return.
- */
- io_info->dxpl_cache->xfer_opt_mode = H5FD_MPIO_INDIVIDUAL_IO;
- if(H5P_set (dx_plist, H5D_XFER_IO_XFER_OPT_MODE_NAME, &io_info->dxpl_cache->xfer_opt_mode) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set transfer mode")
-
- /* Set the pointers to the non-MPI-specific routines */
- io_info->ops.read = H5D_mpio_select_read;
- io_info->ops.write = H5D_mpio_select_write;
-
- /* Indicate that the transfer mode should be restored before returning
- * to user.
- */
- io_info->xfer_opt_mode_changed = TRUE;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_ioinfo_make_coll_opt() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_ioinfo_make_coll
- *
- * Purpose: Switch to MPI collective I/O
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Friday, August 12, 2005
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5D_ioinfo_make_coll(H5D_io_info_t *io_info)
+H5D_ioinfo_coll_opt_mode(H5D_io_info_t *io_info, H5P_genplist_t *dx_plist,
+ H5FD_mpio_collective_opt_t coll_opt_mode)
{
- H5P_genplist_t *dx_plist; /* Data transer property list */
herr_t ret_value = SUCCEED; /*return value */
- FUNC_ENTER_NOAPI_NOINIT(H5D_ioinfo_make_coll)
-
- /* Get the dataset transfer property list */
- if (NULL == (dx_plist = H5I_object(io_info->dxpl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list")
-
- /* Change the xfer_mode to independent, handle the request,
- * then set xfer_mode before return.
- */
- io_info->dxpl_cache->xfer_mode = H5FD_MPIO_COLLECTIVE;
- if(H5P_set (dx_plist, H5D_XFER_IO_XFER_MODE_NAME, &io_info->dxpl_cache->xfer_mode) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set transfer mode")
+ FUNC_ENTER_NOAPI_NOINIT(H5D_ioinfo_coll_opt_mode)
- io_info->dxpl_cache->xfer_opt_mode = H5FD_MPIO_COLLECTIVE_IO;
- if(H5P_set (dx_plist, H5D_XFER_IO_XFER_OPT_MODE_NAME, &io_info->dxpl_cache->xfer_opt_mode) < 0)
+ /* Change the optimal xfer_mode */
+ io_info->dxpl_cache->coll_opt_mode = coll_opt_mode;
+ if(H5P_set(dx_plist, H5D_XFER_MPIO_COLLECTIVE_OPT_NAME, &io_info->dxpl_cache->coll_opt_mode) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set transfer mode")
-
- /* Set the pointers to the MPI-specific routines */
- io_info->ops.read = H5D_mpio_select_read;
- io_info->ops.write = H5D_mpio_select_write;
-
- /* Indicate that the transfer mode should _NOT_ be restored before returning
- * to user.
- */
- io_info->xfer_mode_changed=FALSE;
- io_info->xfer_opt_mode_changed=FALSE;
-
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_ioinfo_make_coll() */
+} /* end H5D_ioinfo_coll_opt_mode() */
/*-------------------------------------------------------------------------
@@ -535,29 +419,30 @@ done:
*
* Return: Non-negative on success/Negative on failure
*
- * Programmer:
+ * Programmer: Muqun Yang
+ * Monday, Feb. 13th, 2006
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5D_mpio_get_min_chunk(const H5D_io_info_t *io_info,
- const fm_map *fm, int *min_chunkf)
+H5D_mpio_get_min_chunk(const H5D_io_info_t *io_info, const H5D_chunk_map_t *fm,
+ int *min_chunkf)
{
int num_chunkf; /* Number of chunks to iterate over */
int mpi_code; /* MPI return code */
herr_t ret_value = SUCCEED;
- FUNC_ENTER_NOAPI_NOINIT(H5D_mpio_get_min_chunk);
+ FUNC_ENTER_NOAPI_NOINIT(H5D_mpio_get_min_chunk)
/* Get the number of chunks to perform I/O on */
- num_chunkf = H5SL_count(fm->fsel);
+ num_chunkf = H5SL_count(fm->sel_chunks);
/* Determine the minimum # of chunks for all processes */
- if (MPI_SUCCESS != (mpi_code = MPI_Allreduce(&num_chunkf, min_chunkf, 1, MPI_INT, MPI_MIN, io_info->comm)))
+ if(MPI_SUCCESS != (mpi_code = MPI_Allreduce(&num_chunkf, min_chunkf, 1, MPI_INT, MPI_MIN, io_info->comm)))
HMPI_GOTO_ERROR(FAIL, "MPI_Allreduce failed", mpi_code)
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_mpio_get_min_chunk() */
@@ -569,221 +454,278 @@ done:
*
* Return: Non-negative on success/Negative on failure
*
- * Programmer:
+ * Programmer: Muqun Yang
+ * Monday, Feb. 13th, 2006
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5D_mpio_get_sum_chunk(const H5D_io_info_t *io_info,
- const fm_map *fm, int *sum_chunkf)
+H5D_mpio_get_sum_chunk(const H5D_io_info_t *io_info, const H5D_chunk_map_t *fm,
+ int *sum_chunkf)
{
int num_chunkf; /* Number of chunks to iterate over */
size_t ori_num_chunkf;
int mpi_code; /* MPI return code */
herr_t ret_value = SUCCEED;
- FUNC_ENTER_NOAPI_NOINIT(H5D_mpio_get_sum_chunk);
+ FUNC_ENTER_NOAPI_NOINIT(H5D_mpio_get_sum_chunk)
/* Get the number of chunks to perform I/O on */
num_chunkf = 0;
- ori_num_chunkf = H5SL_count(fm->fsel);
- H5_ASSIGN_OVERFLOW(num_chunkf,ori_num_chunkf,size_t,int);
+ ori_num_chunkf = H5SL_count(fm->sel_chunks);
+ H5_ASSIGN_OVERFLOW(num_chunkf, ori_num_chunkf, size_t, int);
/* Determine the summation of number of chunks for all processes */
- if (MPI_SUCCESS != (mpi_code = MPI_Allreduce(&num_chunkf, sum_chunkf, 1, MPI_INT, MPI_SUM, io_info->comm)))
+ if(MPI_SUCCESS != (mpi_code = MPI_Allreduce(&num_chunkf, sum_chunkf, 1, MPI_INT, MPI_SUM, io_info->comm)))
HMPI_GOTO_ERROR(FAIL, "MPI_Allreduce failed", mpi_code)
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_mpio_get_sum_chunk() */
/*-------------------------------------------------------------------------
- * Function: H5D_contig_collective_io
+ * Function: H5D_contig_collective_read
*
- * Purpose: Wrapper Routine for H5D_inter_collective_io
- The starting file address of contiguous layout
- will be calculated and passed to H5D_inter_collective_io routine.
- *
+ * Purpose: Reads directly from contiguous data in file into application
+ * memory using collective I/O.
*
* Return: Non-negative on success/Negative on failure
*
- * Programmer:
- *
- * Modifications:
+ * Programmer: Quincey Koziol
+ * Tuesday, March 4, 2008
*
*-------------------------------------------------------------------------
*/
herr_t
-H5D_contig_collective_io(H5D_io_info_t *io_info,
- const H5S_t *file_space,
- const H5S_t *mem_space,
- const void *buf,
- hbool_t do_write)
+H5D_contig_collective_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t UNUSED nelmts, const H5S_t *file_space, const H5S_t *mem_space,
+ H5D_chunk_map_t UNUSED *fm)
{
+ herr_t ret_value = SUCCEED; /* Return value */
+ FUNC_ENTER_NOAPI(H5D_contig_collective_read, FAIL)
- haddr_t addr = HADDR_UNDEF; /* Address of dataset (or selection) within file */
- herr_t ret_value = SUCCEED; /* return value */
+ /* Sanity check */
+ HDassert(IS_H5FD_MPIO(io_info->dset->oloc.file));
+ HDassert(TRUE == H5P_isa_class(io_info->dxpl_id, H5P_DATASET_XFER));
- FUNC_ENTER_NOAPI_NOINIT(H5D_contig_collective_io)
- assert (IS_H5FD_MPIO(io_info->dset->oloc.file));
+ /* Call generic internal collective I/O routine */
+ if(H5D_inter_collective_io(io_info, type_info, file_space, mem_space) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "couldn't finish shared collective MPI-IO")
- /* Make certain we have the correct type of property list */
- assert(TRUE==H5P_isa_class(io_info->dxpl_id,H5P_DATASET_XFER));
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_contig_collective_read() */
- /* Get the base address of the contiguous dataset */
- if(io_info->dset->shared->layout.type == H5D_CONTIGUOUS)
- addr = H5D_contig_get_addr(io_info->dset);
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_contig_collective_write
+ *
+ * Purpose: Write directly to contiguous data in file from application
+ * memory using collective I/O.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, March 4, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_contig_collective_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t UNUSED nelmts, const H5S_t *file_space, const H5S_t *mem_space,
+ H5D_chunk_map_t UNUSED *fm)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
- if(H5D_inter_collective_io(io_info,file_space,mem_space,addr,buf,do_write)<0)
- HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,"couldn't finish shared collective MPI-IO");
-
- done:
+ FUNC_ENTER_NOAPI(H5D_contig_collective_write, FAIL)
+ /* Sanity check */
+ HDassert(IS_H5FD_MPIO(io_info->dset->oloc.file));
+ HDassert(TRUE == H5P_isa_class(io_info->dxpl_id, H5P_DATASET_XFER));
+
+ /* Call generic internal collective I/O routine */
+ if(H5D_inter_collective_io(io_info, type_info, file_space, mem_space) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "couldn't finish shared collective MPI-IO")
+
+done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_contig_collective_io */
+} /* end H5D_contig_collective_write() */
/*-------------------------------------------------------------------------
* Function: H5D_chunk_collective_io
*
- * Purpose: Routine for
- 1) choose an IO option:
- a) One collective IO defined by one MPI derived datatype to link through all chunks
- or b) multiple chunk IOs,to do MPI-IO for each chunk, the IO mode may be adjusted
- due to the selection pattern for each chunk.
+ * Purpose: Routine for
+ * 1) choose an IO option:
+ * a) One collective IO defined by one MPI derived datatype to link through all chunks
+ * or b) multiple chunk IOs,to do MPI-IO for each chunk, the IO mode may be adjusted
+ * due to the selection pattern for each chunk.
* For option a)
- 1. Sort the chunk address, obtain chunk info according to the sorted chunk address
- 2. Build up MPI derived datatype for each chunk
- 3. Build up the final MPI derived datatype
- 4. Set up collective IO property list
- 5. Do IO
+ * 1. Sort the chunk address, obtain chunk info according to the sorted chunk address
+ * 2. Build up MPI derived datatype for each chunk
+ * 3. Build up the final MPI derived datatype
+ * 4. Set up collective IO property list
+ * 5. Do IO
* For option b)
- 1. Use MPI_gather and MPI_Bcast to obtain information of *collective/independent/none*
- IO mode for each chunk of the selection
- 2. Depending on whether the IO mode is collective or independent or none,
- Create either MPI derived datatype for each chunk to do collective IO or
- just do independent IO or independent IO with file set view
- 3. Set up collective IO property list for collective mode
- 4. DO IO
+ * 1. Use MPI_gather and MPI_Bcast to obtain information of *collective/independent/none*
+ * IO mode for each chunk of the selection
+ * 2. Depending on whether the IO mode is collective or independent or none,
+ * Create either MPI derived datatype for each chunk to do collective IO or
+ * just do independent IO or independent IO with file set view
+ * 3. Set up collective IO property list for collective mode
+ * 4. DO IO
*
* Return: Non-negative on success/Negative on failure
*
- * Programmer:
- *
- * Modifications:
+ * Programmer: Muqun Yang
+ * Monday, Feb. 13th, 2006
*
*-------------------------------------------------------------------------
*/
-herr_t
-H5D_chunk_collective_io(H5D_io_info_t *io_info,fm_map *fm,const void *buf, hbool_t do_write)
+static herr_t
+H5D_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ H5D_chunk_map_t *fm)
{
-
- int io_option = H5D_MULTI_CHUNK_IO_MORE_OPT;
- int sum_chunk = 0,mpi_size;
- unsigned one_link_chunk_io_threshold;
- H5P_genplist_t *plist;
+ H5P_genplist_t *dx_plist; /* Pointer to DXPL */
H5FD_mpio_chunk_opt_t chunk_opt_mode;
-
+ int io_option = H5D_MULTI_CHUNK_IO_MORE_OPT;
+ int sum_chunk = -1;
#ifdef H5_HAVE_INSTRUMENTED_LIBRARY
- htri_t check_prop,temp_not_link_io = FALSE;
- int new_value;
+ htri_t temp_not_link_io = FALSE;
#endif
- herr_t ret_value = SUCCEED;
+ herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_collective_io)
- assert (IS_H5FD_MPIO(io_info->dset->oloc.file));
-
+ /* Sanity checks */
+ HDassert(io_info);
+ HDassert(io_info->using_mpi_vfd);
+ HDassert(type_info);
+ HDassert(fm);
+
/* Obtain the data transfer properties */
- if(NULL == (plist = H5I_object(io_info->dxpl_id)))
+ if(NULL == (dx_plist = H5I_object(io_info->dxpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")
-
+
/* Check the optional property list on what to do with collective chunk IO. */
- chunk_opt_mode=(H5FD_mpio_chunk_opt_t)H5P_peek_unsigned(plist,H5D_XFER_MPIO_CHUNK_OPT_HARD_NAME);
-
+ chunk_opt_mode = (H5FD_mpio_chunk_opt_t)H5P_peek_unsigned(dx_plist, H5D_XFER_MPIO_CHUNK_OPT_HARD_NAME);
if(chunk_opt_mode == H5FD_MPIO_CHUNK_ONE_IO)
- io_option = H5D_ONE_LINK_CHUNK_IO;/*no opt*/
+ io_option = H5D_ONE_LINK_CHUNK_IO; /*no opt*/
else if(chunk_opt_mode == H5FD_MPIO_CHUNK_MULTI_IO)
- io_option = H5D_MULTI_CHUNK_IO;/*no opt */
+ io_option = H5D_MULTI_CHUNK_IO; /*no opt */
else {
- if(H5D_mpio_get_sum_chunk(io_info,fm,&sum_chunk)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSWAP, FAIL, "unable to obtain the total chunk number of all processes");
- if((mpi_size = H5F_mpi_get_size(io_info->dset->oloc.file))<0)
- HGOTO_ERROR (H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi size");
-
- if(NULL == (plist = H5I_object(io_info->dxpl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")
-
- one_link_chunk_io_threshold =H5P_peek_unsigned(plist,H5D_XFER_MPIO_CHUNK_OPT_NUM_NAME);
-
- /* step 1: choose an IO option */
- /* If the average number of chunk per process is greater than a threshold, we will do one link chunked IO. */
- if((unsigned)sum_chunk/mpi_size >= one_link_chunk_io_threshold)
+ unsigned one_link_chunk_io_threshold; /* Threshhold to use single collective I/O for all chunks */
+ int mpi_size; /* Number of processes in MPI job */
+
+ if(H5D_mpio_get_sum_chunk(io_info, fm, &sum_chunk) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSWAP, FAIL, "unable to obtain the total chunk number of all processes");
+ if((mpi_size = H5F_mpi_get_size(io_info->dset->oloc.file)) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi size")
+
+ one_link_chunk_io_threshold = H5P_peek_unsigned(dx_plist, H5D_XFER_MPIO_CHUNK_OPT_NUM_NAME);
+
+ /* step 1: choose an IO option */
+ /* If the average number of chunk per process is greater than a threshold, we will do one link chunked IO. */
+ if((unsigned)sum_chunk / mpi_size >= one_link_chunk_io_threshold)
io_option = H5D_ONE_LINK_CHUNK_IO_MORE_OPT;
#ifdef H5_HAVE_INSTRUMENTED_LIBRARY
- else
- temp_not_link_io = TRUE;
+ else
+ temp_not_link_io = TRUE;
+#endif
+ } /* end else */
+
+#ifndef H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS
+ if(io_option == H5D_ONE_LINK_CHUNK_IO) {
+ io_option = H5D_MULTI_CHUNK_IO; /* We can not do this with one chunk IO. */
+#ifdef H5_HAVE_INSTRUMENTED_LIBRARY
+ { int new_value;
+ htri_t check_prop;
+ check_prop = H5Pexist(io_info->dxpl_id, H5D_XFER_COLL_CHUNK_LINK_TO_MULTI);
+ if(check_prop > 0) {
+ new_value = 1;
+ if(H5Pset(io_info->dxpl_id, H5D_XFER_COLL_CHUNK_LINK_TO_MULTI, &new_value) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTSET, FAIL, "unable to set property value")
+
+ }
+ }/* add this property because the library changes the option from one link to multiple chunks.*/
+#endif
+ }
+ if(io_option == H5D_ONE_LINK_CHUNK_IO_MORE_OPT){
+ io_option = H5D_MULTI_CHUNK_IO_MORE_OPT;
+#ifdef H5_HAVE_INSTRUMENTED_LIBRARY
+ { int new_value;
+ htri_t check_prop;
+ check_prop = H5Pexist(io_info->dxpl_id, H5D_XFER_COLL_CHUNK_LINK_TO_MULTI_OPT);
+ if(check_prop > 0) {
+ new_value = 1;
+ if(H5Pset(io_info->dxpl_id, H5D_XFER_COLL_CHUNK_LINK_TO_MULTI_OPT, &new_value) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTSET, FAIL, "unable to set property value")
+
+ }
+ }/* add this property because the library changes the option from one link to multiple chunks.*/
+#endif
+ }
#endif
- }
#ifdef H5_HAVE_INSTRUMENTED_LIBRARY
+{
+ htri_t check_prop;
+ int new_value;
+
/*** Test collective chunk user-input optimization APIs. ***/
- check_prop = H5Pexist(io_info->dxpl_id,H5D_XFER_COLL_CHUNK_LINK_HARD_NAME);
+ check_prop = H5Pexist(io_info->dxpl_id, H5D_XFER_COLL_CHUNK_LINK_HARD_NAME);
if(check_prop > 0) {
if(io_option == H5D_ONE_LINK_CHUNK_IO) {
- new_value = 0;
- if(H5Pset(io_info->dxpl_id,H5D_XFER_COLL_CHUNK_LINK_HARD_NAME,&new_value)<0)
- HGOTO_ERROR(H5E_PLIST, H5E_UNSUPPORTED, FAIL, "unable to get property value");
- }
- }
- check_prop = H5Pexist(io_info->dxpl_id,H5D_XFER_COLL_CHUNK_MULTI_HARD_NAME);
+ new_value = 0;
+ if(H5Pset(io_info->dxpl_id, H5D_XFER_COLL_CHUNK_LINK_HARD_NAME, &new_value) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTSET, FAIL, "unable to set property value")
+ } /* end if */
+ } /* end if */
+ check_prop = H5Pexist(io_info->dxpl_id, H5D_XFER_COLL_CHUNK_MULTI_HARD_NAME);
if(check_prop > 0) {
- if(io_option == H5D_MULTI_CHUNK_IO) {
- new_value = 0;
- if(H5Pset(io_info->dxpl_id,H5D_XFER_COLL_CHUNK_MULTI_HARD_NAME,&new_value)<0)
- HGOTO_ERROR(H5E_PLIST, H5E_UNSUPPORTED, FAIL, "unable to get property value");
- }
- }
- check_prop = H5Pexist(io_info->dxpl_id,H5D_XFER_COLL_CHUNK_LINK_NUM_TRUE_NAME);
+ if(io_option == H5D_MULTI_CHUNK_IO) {
+ new_value = 0;
+ if(H5Pset(io_info->dxpl_id, H5D_XFER_COLL_CHUNK_MULTI_HARD_NAME, &new_value) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTSET, FAIL, "unable to set property value")
+ } /* end if */
+ } /* end if */
+ check_prop = H5Pexist(io_info->dxpl_id, H5D_XFER_COLL_CHUNK_LINK_NUM_TRUE_NAME);
if(check_prop > 0) {
- if(io_option == H5D_ONE_LINK_CHUNK_IO_MORE_OPT) {
- new_value = 0;
- if(H5Pset(io_info->dxpl_id,H5D_XFER_COLL_CHUNK_LINK_NUM_TRUE_NAME,&new_value)<0)
- HGOTO_ERROR(H5E_PLIST, H5E_UNSUPPORTED, FAIL, "unable to get property value");
- }
- }
- check_prop = H5Pexist(io_info->dxpl_id,H5D_XFER_COLL_CHUNK_LINK_NUM_FALSE_NAME);
+ if(io_option == H5D_ONE_LINK_CHUNK_IO_MORE_OPT) {
+ new_value = 0;
+ if(H5Pset(io_info->dxpl_id, H5D_XFER_COLL_CHUNK_LINK_NUM_TRUE_NAME, &new_value) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTSET, FAIL, "unable to set property value")
+ } /* end if */
+ } /* end if */
+ check_prop = H5Pexist(io_info->dxpl_id, H5D_XFER_COLL_CHUNK_LINK_NUM_FALSE_NAME);
if(check_prop > 0) {
- if(temp_not_link_io){
- new_value = 0;
- if(H5Pset(io_info->dxpl_id,H5D_XFER_COLL_CHUNK_LINK_NUM_FALSE_NAME,&new_value)<0)
- HGOTO_ERROR(H5E_PLIST, H5E_UNSUPPORTED, FAIL, "unable to get property value");
- }
- }
-#endif
-
-#ifndef H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS
- if(io_option == H5D_ONE_LINK_CHUNK_IO )
- io_option = H5D_MULTI_CHUNK_IO ;/* We can not do this with one chunk IO. */
- if(io_option == H5D_ONE_LINK_CHUNK_IO_MORE_OPT)
- io_option = H5D_MULTI_CHUNK_IO_MORE_OPT;
+ if(temp_not_link_io) {
+ new_value = 0;
+ if(H5Pset(io_info->dxpl_id, H5D_XFER_COLL_CHUNK_LINK_NUM_FALSE_NAME, &new_value) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTSET, FAIL, "unable to set property value")
+ } /* end if */
+ } /* end if */
+}
#endif
/* step 2: Go ahead to do IO.*/
+#ifdef H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS
if(io_option == H5D_ONE_LINK_CHUNK_IO || io_option == H5D_ONE_LINK_CHUNK_IO_MORE_OPT) {
- if(H5D_link_chunk_collective_io(io_info,fm,buf,do_write,sum_chunk)<0)
- HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,"couldn't finish linked chunk MPI-IO");
- }
- else if(io_option == H5D_MULTI_CHUNK_IO) {
- if(H5D_multi_chunk_collective_io_no_opt(io_info,fm,buf,do_write)<0)
- HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,"couldn't finish multiple chunk MPI-IO");
- }
+ if(H5D_link_chunk_collective_io(io_info, type_info, fm, sum_chunk) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish linked chunk MPI-IO")
+ } /* end if */
+ else
+#endif /* H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS */
+ if(io_option == H5D_MULTI_CHUNK_IO) {
+ if(H5D_multi_chunk_collective_io_no_opt(io_info, type_info, fm, dx_plist) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish multiple chunk MPI-IO")
+ } /* end if */
else { /*multiple chunk IOs with opt */
- if(H5D_multi_chunk_collective_io(io_info,fm,buf,do_write)<0)
- HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,"couldn't finish multiple chunk MPI-IO");
- }
+ if(H5D_multi_chunk_collective_io(io_info, type_info, fm, dx_plist) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish optimized multiple chunk MPI-IO")
+ } /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -791,458 +733,580 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5D_link_chunk_collective_io
+ * Function: H5D_chunk_collective_read
*
- * Purpose: Routine for one collective IO with one MPI derived datatype to link with all chunks
+ * Purpose: Reads directly from chunks in file into application memory
+ * using collective I/O.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, March 4, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_chunk_collective_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t UNUSED nelmts, const H5S_t UNUSED *file_space, const H5S_t UNUSED *mem_space,
+ H5D_chunk_map_t *fm)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5D_chunk_collective_read, FAIL)
- 1. Sort the chunk address and chunk info
- 2. Build up MPI derived datatype for each chunk
- 3. Build up the final MPI derived datatype
- 4. Use common collective IO routine to do MPI-IO
+ /* Call generic selection operation */
+ if(H5D_chunk_collective_io(io_info, type_info, fm) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, FAIL, "read error")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_collective_read() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_collective_write
*
- * Return: Non-negative on success/Negative on failure
+ * Purpose: Write directly to chunks in file from application memory
+ * using collective I/O.
*
- * Programmer:
+ * Return: Non-negative on success/Negative on failure
*
- * Modifications:
+ * Programmer: Quincey Koziol
+ * Tuesday, March 4, 2008
*
*-------------------------------------------------------------------------
*/
+herr_t
+H5D_chunk_collective_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t UNUSED nelmts, const H5S_t UNUSED *file_space, const H5S_t UNUSED *mem_space,
+ H5D_chunk_map_t *fm)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5D_chunk_collective_write, FAIL)
+ /* Call generic selection operation */
+ if(H5D_chunk_collective_io(io_info, type_info, fm) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_chunk_collective_write() */
+
+#ifdef H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_link_chunk_collective_io
+ *
+ * Purpose: Routine for one collective IO with one MPI derived datatype to link with all chunks
+ *
+ * 1. Sort the chunk address and chunk info
+ * 2. Build up MPI derived datatype for each chunk
+ * 3. Build up the final MPI derived datatype
+ * 4. Use common collective IO routine to do MPI-IO
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Muqun Yang
+ * Monday, Feb. 13th, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
static herr_t
-H5D_link_chunk_collective_io(H5D_io_info_t *io_info,fm_map *fm,const void *buf, hbool_t do_write,int sum_chunk)
+H5D_link_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ H5D_chunk_map_t *fm, int sum_chunk)
{
- size_t src_type_size; /*size of source type */
- size_t dst_type_size; /*size of destination type*/
- hsize_t mpi_buf_extra_offset;
- hsize_t mpi_file_extra_offset;
- size_t mpi_buf_count;
- size_t mpi_file_count;
- hbool_t mbt_is_derived=0, /* Whether the buffer (memory) type is derived and needs to be free'd */
- mft_is_derived=0; /* Whether the file type is derived and needs to be free'd */
-
- int mpi_size,mpi_code; /* MPI return code */
-
- int i,num_chunk=0,total_chunks;
- size_t ori_num_chunk;
- hsize_t ori_total_chunks;
- haddr_t chunk_base_addr;
- haddr_t* total_chunk_addr_array=NULL;
- MPI_Datatype *chunk_mtype=NULL;
- MPI_Datatype *chunk_ftype=NULL;
- MPI_Datatype chunk_final_mtype;
- MPI_Datatype chunk_final_ftype;
- MPI_Aint *chunk_disp_array=NULL;
- MPI_Aint *chunk_mem_disp_array=NULL;
- int *blocklen=NULL;
- int blocklen_value;
- int actual_bsearch_coll_chunk_threshold;
- int bsearch_coll_chunk_threshold;
- int many_chunk_opt = 0;
-
- H5D_common_coll_info_t coll_info;
- H5D_chunk_addr_info_t* chunk_addr_info_array=NULL;
-
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_link_chunk_collective_io)
- ori_total_chunks = fm->total_chunks;
- H5_ASSIGN_OVERFLOW(total_chunks,ori_total_chunks,hsize_t,int);
-
- /* Handle with a special case when only one chunk is covered by all processes */
- if(total_chunks == 1){
- H5SL_node_t *chunk_node;
- H5D_chunk_info_t *chunk_info;
- H5D_storage_t store;
-
- chunk_node = H5SL_first(fm->fsel);
+ H5D_chunk_addr_info_t *chunk_addr_info_array = NULL;
+ hbool_t mbt_is_derived = FALSE;
+ hbool_t mft_is_derived = FALSE;
+ MPI_Datatype chunk_final_mtype; /* Final memory MPI datatype for all chunks with seletion */
+ MPI_Datatype chunk_final_ftype; /* Final file MPI datatype for all chunks with seletion */
+ H5D_storage_t ctg_store; /* Storage info for "fake" contiguous dataset */
+ size_t total_chunks;
+ haddr_t *total_chunk_addr_array = NULL;
+ MPI_Datatype *chunk_mtype = NULL;
+ MPI_Datatype *chunk_ftype = NULL;
+ MPI_Aint *chunk_disp_array = NULL;
+ MPI_Aint *chunk_mem_disp_array = NULL;
+ int *blocklen = NULL;
+ int mpi_code; /* MPI return code */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_link_chunk_collective_io)
+
+ /* Get the sum # of chunks, if not already available */
+ if(sum_chunk < 0) {
+ if(H5D_mpio_get_sum_chunk(io_info, fm, &sum_chunk) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSWAP, FAIL, "unable to obtain the total chunk number of all processes");
+ } /* end if */
+
+ /* Retrieve total # of chunks in dataset */
+ H5_ASSIGN_OVERFLOW(total_chunks, fm->total_chunks, hsize_t, size_t);
+
+ /* Handle special case when dataspace dimensions only allow one chunk in
+ * the dataset. [This sometimes is used by developers who want the
+ * equivalent of compressed contiguous datasets - QAK]
+ */
+ if(total_chunks == 1) {
+ H5D_chunk_ud_t udata; /* User data for querying chunk info */
+ hsize_t coords[H5O_LAYOUT_NDIMS]; /* Coordinates of chunk in file dataset's dataspace */
+ H5SL_node_t *chunk_node; /* Pointer to chunk node for selection */
+ H5S_t *fspace; /* Dataspace describing chunk & selection in it */
+ H5S_t *mspace; /* Dataspace describing selection in memory corresponding to this chunk */
+
+ /* Initialize the chunk coordinates */
+ /* (must be all zero, since there's only one chunk) */
+ HDmemset(coords, 0, sizeof(coords));
+
+ /* Look up address of chunk */
+ if(H5D_chunk_get_info(io_info->dset, io_info->dxpl_id, coords, &udata) < 0)
+ HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL, "couldn't get chunk info from skipped list")
+ ctg_store.contig.dset_addr = udata.addr;
+
+ /* Check for this process having selection in this chunk */
+ chunk_node = H5SL_first(fm->sel_chunks);
if(chunk_node == NULL) {
- if(H5D_istore_chunkmap(io_info, &chunk_base_addr, fm->down_chunks) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk address");
- if(H5D_inter_collective_io(io_info,NULL,NULL,chunk_base_addr,buf,do_write)<0)
- HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't finish shared collective MPI-IO");
- }
+ /* Set the dataspace info for I/O to NULL, this process doesn't have any I/O to perform */
+ fspace = mspace = NULL;
+ } /* end if */
else {
- if(NULL ==(chunk_info = H5SL_item(chunk_node)))
- HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't get chunk info from skipped list");
- io_info->store = &store;
- store.chunk.offset = chunk_info->coords;
- store.chunk.index = chunk_info->index;
-
- if(HADDR_UNDEF==(chunk_base_addr = H5D_istore_get_addr(io_info,NULL)))
- HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't get chunk info from skipped list");
-
+ H5D_chunk_info_t *chunk_info;
+
+ /* Get the chunk info, for the selection in the chunk */
+ if(NULL == (chunk_info = H5SL_item(chunk_node)))
+ HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL, "couldn't get chunk info from skipped list")
+
+ /* Set the dataspace info for I/O */
+ fspace = chunk_info->fspace;
+ mspace = chunk_info->mspace;
+ } /* end else */
+
+ /* Set up the base storage address for this chunk */
+ io_info->store = &ctg_store;
+
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
- HDfprintf(H5DEBUG(D),"before inter_collective_io for total chunk = 1 \n");
+if(H5DEBUG(D))
+ HDfprintf(H5DEBUG(D),"before inter_collective_io for total chunk = 1 \n");
#endif
- if(H5D_inter_collective_io(io_info,chunk_info->fspace,chunk_info->mspace,chunk_base_addr,buf,do_write)<0)
- HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't finish shared collective MPI-IO");
- }
- goto done;
- }
- /* Allocate chunking information */
- ori_num_chunk = H5SL_count(fm->fsel);
- H5_ASSIGN_OVERFLOW(num_chunk,ori_num_chunk,size_t,int);
+ /* Perform I/O */
+ if(H5D_inter_collective_io(io_info, type_info, fspace, mspace) < 0)
+ HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL, "couldn't finish shared collective MPI-IO")
+ } /* end if */
+ else {
+ size_t mpi_buf_count; /* Number of MPI types */
+ size_t num_chunk; /* Number of chunks for this process */
+ size_t u; /* Local index variable */
+
+ /* Get the number of chunks with a selection */
+ num_chunk = H5SL_count(fm->sel_chunks);
+ H5_CHECK_OVERFLOW(num_chunk, size_t, int);
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
- HDfprintf(H5DEBUG(D),"total_chunks = %d\n",(int)total_chunks);
+if(H5DEBUG(D))
+ HDfprintf(H5DEBUG(D),"total_chunks = %Zu, num_chunk = %Zu\n", total_chunks, num_chunk);
#endif
-
- if(num_chunk == 0)
- total_chunk_addr_array = H5MM_malloc(sizeof(haddr_t)*total_chunks);
- else
- {
- chunk_addr_info_array= H5MM_malloc(num_chunk*sizeof(H5D_chunk_addr_info_t));
- chunk_mtype = H5MM_malloc(num_chunk*sizeof(MPI_Datatype));
- chunk_ftype = H5MM_malloc(num_chunk*sizeof(MPI_Datatype));
- chunk_disp_array = H5MM_malloc(num_chunk*sizeof(MPI_Aint));
- chunk_mem_disp_array = H5MM_calloc(num_chunk*sizeof(MPI_Aint));
- blocklen = H5MM_malloc(num_chunk*sizeof(int));
- }
-
- /* Obtain information to do collective IO,
- in order to do collective IO, no datatype conversion should happen. */
- if((src_type_size = H5T_get_size(io_info->dset->shared->type))==0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_BADSIZE, FAIL, "datatype size invalid");
- dst_type_size = src_type_size;
-
- bsearch_coll_chunk_threshold = H5D_ALL_CHUNK_ADDR_THRES_COL;
-
- if((mpi_size = H5F_mpi_get_size(io_info->dset->oloc.file))<0)
- HGOTO_ERROR (H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi size");
-
- /* Calculate the actual threshold to obtain all chunk addresses collectively
- The bigger this number is, the more possible the use of obtaining chunk address collectively. */
- /* For non-optimization one-link IO,
- actual bsearch threshold is always 0,
- we would always want to obtain the chunk addresses individually
- for each process. */
- actual_bsearch_coll_chunk_threshold = sum_chunk*100/(total_chunks*mpi_size);
-
- if((actual_bsearch_coll_chunk_threshold > bsearch_coll_chunk_threshold)
- &&(sum_chunk/mpi_size >= H5D_ALL_CHUNK_ADDR_THRES_COL_NUM))
- many_chunk_opt = H5D_OBTAIN_ALL_CHUNK_ADDR_COL;
+
+ /* Set up MPI datatype for chunks selected */
+ if(num_chunk) {
+ hsize_t mpi_mem_extra_offset; /* Extra offset for memory MPI datatype */
+ hsize_t mpi_file_extra_offset; /* Extra offset for file MPI datatype */
+ size_t mpi_mem_count; /* Memory MPI datatype count */
+ size_t mpi_file_count; /* File MPI datatype count */
+ hbool_t locl_mbt_is_derived = FALSE, /* Whether the buffer (memory) type is derived and needs to be free'd */
+ local_mft_is_derived = FALSE; /* Whether the file type is derived and needs to be free'd */
+ int blocklen_value; /* Placeholder for array fill */
+
+ /* Allocate chunking information */
+ chunk_addr_info_array= H5MM_malloc(num_chunk * sizeof(H5D_chunk_addr_info_t));
+ chunk_mtype = H5MM_malloc(num_chunk * sizeof(MPI_Datatype));
+ chunk_ftype = H5MM_malloc(num_chunk * sizeof(MPI_Datatype));
+ chunk_disp_array = H5MM_malloc(num_chunk * sizeof(MPI_Aint));
+ chunk_mem_disp_array = H5MM_calloc(num_chunk * sizeof(MPI_Aint));
+ blocklen = H5MM_malloc(num_chunk * sizeof(int));
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
+if(H5DEBUG(D))
HDfprintf(H5DEBUG(D),"before sorting the chunk address \n");
#endif
-
- /* Sort the chunk address
- when chunk optimization selection is either H5D_OBTAIN_*/
-
- if(num_chunk == 0){ /* special case: this process doesn't select anything */
- if(H5D_istore_chunkmap(io_info, total_chunk_addr_array, fm->down_chunks)<0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk address");
- chunk_base_addr = total_chunk_addr_array[0];
- }
-
- else {
- if(H5D_sort_chunk(io_info,fm,chunk_addr_info_array,many_chunk_opt)<0)
- HGOTO_ERROR (H5E_DATASPACE, H5E_CANTSWAP, FAIL, "unable to sort chunk address");
- chunk_base_addr = chunk_addr_info_array[0].chunk_addr;
- }
+ /* Sort the chunk address */
+ if(H5D_sort_chunk(io_info, fm, chunk_addr_info_array, sum_chunk) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSWAP, FAIL, "unable to sort chunk address")
+ ctg_store.contig.dset_addr = chunk_addr_info_array[0].chunk_addr;
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
+if(H5DEBUG(D))
HDfprintf(H5DEBUG(D),"after sorting the chunk address \n");
#endif
-
- /* Obtain MPI derived datatype from all individual chunks */
- for ( i = 0; i < num_chunk; i++) {
- /* Disk MPI derived datatype */
- if(H5S_mpio_space_type(chunk_addr_info_array[i].chunk_info.fspace,src_type_size,&chunk_ftype[i],
- &mpi_file_count,&mpi_file_extra_offset,&mft_is_derived)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't create MPI file type");
-
- /* Buffer MPI derived datatype */
- if(H5S_mpio_space_type(chunk_addr_info_array[i].chunk_info.mspace,dst_type_size,&chunk_mtype[i],
- &mpi_buf_count,&mpi_buf_extra_offset,&mbt_is_derived)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't create MPI buf type");
-
- /* Chunk address relative to the first chunk */
- chunk_addr_info_array[i].chunk_addr -= chunk_base_addr;
- H5_ASSIGN_OVERFLOW(chunk_disp_array[i],chunk_addr_info_array[i].chunk_addr,haddr_t,MPI_Aint);
- }
-
- blocklen_value = 1;
- if(num_chunk){
-
- /* initialize the buffer with the constant value 1; this algo. is very fast. */
- H5V_array_fill(blocklen,&blocklen_value,sizeof(int),(size_t)num_chunk);
-
- /* Create final MPI derived datatype */
- if(MPI_SUCCESS != (mpi_code = MPI_Type_struct(num_chunk,blocklen,chunk_disp_array,chunk_ftype,&chunk_final_ftype)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_struct failed", mpi_code);
- if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&chunk_final_ftype)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code);
-
- if(MPI_SUCCESS != (mpi_code = MPI_Type_struct(num_chunk,blocklen,chunk_mem_disp_array,chunk_mtype,&chunk_final_mtype)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_struct failed", mpi_code);
- if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&chunk_final_mtype)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code);
-
- for ( i = 0; i< num_chunk;i++){
- if (MPI_SUCCESS != (mpi_code= MPI_Type_free( chunk_mtype+i )))
- HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code);
-
- if (MPI_SUCCESS != (mpi_code= MPI_Type_free( chunk_ftype+i )))
- HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code);
- }
-
- /* buffer, file derived datatypes should be true */
- coll_info.mbt_is_derived = 1;
- coll_info.mft_is_derived = 1;
- coll_info.mpi_buf_count = 1;
- coll_info.chunk_addr = chunk_base_addr;
-
- }
-
- else {/* no selection at all for this process */
- chunk_final_ftype = MPI_BYTE;
- chunk_final_mtype = MPI_BYTE;
-
- /* buffer, file derived datatypes should be true */
- coll_info.mbt_is_derived = 0;
- coll_info.mft_is_derived = 0;
- coll_info.mpi_buf_count = 0;
- coll_info.chunk_addr = chunk_base_addr;
- }
+
+ /* Obtain MPI derived datatype from all individual chunks */
+ for(u = 0; u < num_chunk; u++) {
+ /* Disk MPI derived datatype */
+ if(H5S_mpio_space_type(chunk_addr_info_array[u].chunk_info.fspace,
+ type_info->src_type_size, &chunk_ftype[u], &mpi_file_count,
+ &mpi_file_extra_offset, &local_mft_is_derived) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't create MPI file type")
+
+ /* Buffer MPI derived datatype */
+ if(H5S_mpio_space_type(chunk_addr_info_array[u].chunk_info.mspace,
+ type_info->dst_type_size, &chunk_mtype[u], &mpi_mem_count,
+ &mpi_mem_extra_offset, &locl_mbt_is_derived) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't create MPI buf type")
+
+ /* Chunk address relative to the first chunk */
+ chunk_addr_info_array[u].chunk_addr -= ctg_store.contig.dset_addr;
+ H5_ASSIGN_OVERFLOW(chunk_disp_array[u], chunk_addr_info_array[u].chunk_addr, haddr_t, MPI_Aint);
+ } /* end for */
+
+ /* Initialize the buffer with the constant value 1 */
+ blocklen_value = 1;
+ H5V_array_fill(blocklen, &blocklen_value, sizeof(int), num_chunk);
+
+ /* Create final MPI derived datatype for the file */
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_struct((int)num_chunk, blocklen, chunk_disp_array, chunk_ftype, &chunk_final_ftype)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_struct failed", mpi_code)
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&chunk_final_ftype)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code)
+
+ /* Create final MPI derived datatype for memory */
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_struct(num_chunk, blocklen, chunk_mem_disp_array, chunk_mtype, &chunk_final_mtype)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_struct failed", mpi_code)
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&chunk_final_mtype)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code)
+
+ /* Free the file & memory MPI datatypes for each chunk */
+ for(u = 0; u < num_chunk; u++) {
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_free(chunk_mtype + u)))
+ HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code)
+
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_free(chunk_ftype + u)))
+ HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code)
+ } /* end for */
+
+ /* buffer, file derived datatypes should be true */
+ mbt_is_derived = TRUE;
+ mft_is_derived = TRUE;
+ mpi_buf_count = (size_t)1;
+ } /* end if */
+ else { /* no selection at all for this process */
+ /* Allocate chunking information */
+ total_chunk_addr_array = H5MM_malloc(sizeof(haddr_t) * total_chunks);
+
+ /* Retrieve chunk address map */
+ if(H5D_chunk_addrmap(io_info, total_chunk_addr_array, fm->down_chunks) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk address")
+
+ /* Get chunk with lowest address */
+ ctg_store.contig.dset_addr = HADDR_MAX;
+ for(u = 0; u < total_chunks; u++)
+ if(total_chunk_addr_array[u] < ctg_store.contig.dset_addr)
+ ctg_store.contig.dset_addr = total_chunk_addr_array[u];
+ HDassert(ctg_store.contig.dset_addr != HADDR_MAX);
+
+ /* Set the MPI datatype */
+ chunk_final_ftype = MPI_BYTE;
+ chunk_final_mtype = MPI_BYTE;
+
+ /* buffer, file derived datatypes should be true */
+ mpi_buf_count = (size_t)0;
+ } /* end else */
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
+if(H5DEBUG(D))
HDfprintf(H5DEBUG(D),"before coming to final collective IO\n");
#endif
- if(H5D_final_collective_io(io_info,&chunk_final_ftype,&chunk_final_mtype,&coll_info,buf,do_write)<0)
- HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,"couldn't finish MPI-IO");
+ /* Set up the base storage address for this chunk */
+ io_info->store = &ctg_store;
+
+ /* Perform final collective I/O operation */
+ if(H5D_final_collective_io(io_info, type_info, mpi_buf_count, &chunk_final_ftype, &chunk_final_mtype) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish MPI-IO")
+ } /* end else */
done:
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
- HDfprintf(H5DEBUG(D),"before freeing memory inside H5D_link_collective_io ret_value = %d\n",ret_value);
+if(H5DEBUG(D))
+ HDfprintf(H5DEBUG(D),"before freeing memory inside H5D_link_collective_io ret_value = %d\n", ret_value);
#endif
- if (fm->total_chunks != 1) {
- if(num_chunk == 0) HDfree(total_chunk_addr_array);
- else {
- HDfree(chunk_addr_info_array);
- HDfree(chunk_mtype);
- HDfree(chunk_ftype);
- HDfree(chunk_disp_array);
- HDfree(chunk_mem_disp_array);
- HDfree(blocklen);
- }
- }
- FUNC_LEAVE_NOAPI(ret_value)
+ if(total_chunk_addr_array)
+ H5MM_xfree(total_chunk_addr_array);
+ if(chunk_addr_info_array)
+ H5MM_xfree(chunk_addr_info_array);
+ if(chunk_mtype)
+ H5MM_xfree(chunk_mtype);
+ if(chunk_ftype)
+ H5MM_xfree(chunk_ftype);
+ if(chunk_disp_array)
+ H5MM_xfree(chunk_disp_array);
+ if(chunk_mem_disp_array)
+ H5MM_xfree(chunk_mem_disp_array);
+ if(blocklen)
+ H5MM_xfree(blocklen);
+
+ /* Free the MPI buf and file types, if they were derived */
+ if(mbt_is_derived && MPI_SUCCESS != (mpi_code = MPI_Type_free(&chunk_final_mtype)))
+ HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code)
+ if(mft_is_derived && MPI_SUCCESS != (mpi_code = MPI_Type_free(&chunk_final_ftype)))
+ HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code)
+
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_link_chunk_collective_io */
+#endif /* H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS */
/*-------------------------------------------------------------------------
* Function: H5D_multi_chunk_collective_io
*
* Purpose: To do IO per chunk according to IO mode(collective/independent/none)
-
- 1. Use MPI_gather and MPI_Bcast to obtain IO mode in each chunk(collective/independent/none)
- 2. Depending on whether the IO mode is collective or independent or none,
- Create either MPI derived datatype for each chunk or just do independent IO
- 3. Use common collective IO routine to do MPI-IO
*
- * Return: Non-negative on success/Negative on failure
+ * 1. Use MPI_gather and MPI_Bcast to obtain IO mode in each chunk(collective/independent/none)
+ * 2. Depending on whether the IO mode is collective or independent or none,
+ * Create either MPI derived datatype for each chunk or just do independent IO
+ * 3. Use common collective IO routine to do MPI-IO
*
- * Programmer:
+ * Return: Non-negative on success/Negative on failure
*
- * Modifications:
+ * Programmer: Muqun Yang
+ * Monday, Feb. 13th, 2006
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5D_multi_chunk_collective_io(H5D_io_info_t *io_info,fm_map *fm,const void *buf, hbool_t do_write)
+static herr_t
+H5D_multi_chunk_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ H5D_chunk_map_t *fm, H5P_genplist_t *dx_plist)
{
- unsigned i, total_chunk;
- hsize_t ori_total_chunk;
- uint8_t *chunk_io_option;
-
- H5SL_node_t *chunk_node; /* Current node in chunk skip list */
- H5D_chunk_info_t *chunk_info=NULL;
- haddr_t *chunk_addr;
- H5D_storage_t store; /* union of EFL and chunk pointer in file space */
- hbool_t select_chunk;
- hbool_t last_io_mode_coll = TRUE;
-
- void *chunk = NULL; /* Pointer to the data chunk in cache */
- H5D_t *dataset=io_info->dset;/* Local pointer to dataset info */
- H5D_istore_ud1_t udata; /*B-tree pass-through */
- haddr_t caddr; /* Address of the cached chunk */
- size_t accessed_bytes; /*total accessed size in a chunk */
- unsigned idx_hint=0; /* Cache index hint */
- hbool_t dirty = TRUE; /* Flag for cache flushing */
- hbool_t relax=TRUE; /* Whether whole chunk is selected */
-
- herr_t ret_value = SUCCEED;
+ H5D_t *dataset = io_info->dset;/* Local pointer to dataset info */
+ H5D_io_info_t ctg_io_info; /* Contiguous I/O info object */
+ H5D_storage_t ctg_store; /* Chunk storage information as contiguous dataset */
+ H5D_io_info_t cpt_io_info; /* Compact I/O info object */
+ H5D_storage_t cpt_store; /* Chunk storage information as compact dataset */
+ hbool_t cpt_dirty; /* Temporary placeholder for compact storage "dirty" flag */
+ uint8_t *chunk_io_option = NULL;
+ haddr_t *chunk_addr = NULL;
+ H5D_storage_t store; /* union of EFL and chunk pointer in file space */
+ H5FD_mpio_xfer_t last_xfer_mode = H5FD_MPIO_COLLECTIVE; /* Last parallel transfer for this request (H5D_XFER_IO_XFER_MODE_NAME) */
+ H5FD_mpio_collective_opt_t last_coll_opt_mode = H5FD_MPIO_COLLECTIVE_IO; /* Last parallel transfer with independent IO or collective IO with this mode */
+ size_t total_chunk; /* Total # of chunks in dataset */
#ifdef H5Dmpio_DEBUG
- int mpi_rank;
+ int mpi_rank;
#endif
+ size_t u; /* Local index variable */
+ herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_multi_chunk_collective_io)
+ FUNC_ENTER_NOAPI_NOINIT(H5D_multi_chunk_collective_io)
#ifdef H5Dmpio_DEBUG
- mpi_rank = H5F_mpi_get_rank(io_info->dset->oloc.file);
+ mpi_rank = H5F_mpi_get_rank(io_info->dset->oloc.file);
#endif
- /* Allocate memories */
- ori_total_chunk = fm->total_chunks;
- H5_ASSIGN_OVERFLOW(total_chunk,ori_total_chunk,hsize_t,unsigned);
- HDassert(total_chunk!=0);
- chunk_io_option = (uint8_t *)H5MM_calloc(total_chunk*sizeof(MPI_BYTE));
- chunk_addr = (haddr_t *)H5MM_calloc(total_chunk*sizeof(haddr_t));
+ /* Retrieve total # of chunks in dataset */
+ H5_ASSIGN_OVERFLOW(total_chunk, fm->total_chunks, hsize_t, size_t);
+ HDassert(total_chunk != 0);
+
+ /* Allocate memories */
+ chunk_io_option = (uint8_t *)H5MM_calloc(total_chunk);
+ chunk_addr = (haddr_t *)H5MM_calloc(total_chunk * sizeof(haddr_t));
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
- HDfprintf(H5DEBUG(D),"total_chunk %u\n",total_chunk);
+if(H5DEBUG(D))
+ HDfprintf(H5DEBUG(D), "total_chunk %Zu\n", total_chunk);
#endif
- /* obtain IO option for each chunk */
- if(H5D_obtain_mpio_mode(io_info,fm,chunk_io_option,chunk_addr)<0)
- HGOTO_ERROR (H5E_DATASET, H5E_CANTRECV, FAIL, "unable to obtain MPIO mode");
+ /* Obtain IO option for each chunk */
+ if(H5D_obtain_mpio_mode(io_info, fm, dx_plist, chunk_io_option, chunk_addr) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTRECV, FAIL, "unable to obtain MPIO mode")
+
+ /* Set up contiguous I/O info object */
+ HDmemcpy(&ctg_io_info, io_info, sizeof(ctg_io_info));
+ ctg_io_info.store = &ctg_store;
+ ctg_io_info.layout_ops = *H5D_LOPS_CONTIG;
+
+ /* Initialize temporary contiguous storage info */
+ ctg_store.contig.dset_size = (hsize_t)io_info->dset->shared->layout.u.chunk.size;
+
+ /* Set up compact I/O info object */
+ HDmemcpy(&cpt_io_info, io_info, sizeof(cpt_io_info));
+ cpt_io_info.store = &cpt_store;
+ cpt_io_info.layout_ops = *H5D_LOPS_COMPACT;
+
+ /* Initialize temporary compact storage info */
+ cpt_store.compact.dirty = &cpt_dirty;
+
+ /* Set dataset storage for I/O info */
+ io_info->store = &store;
+
+ /* Loop over _all_ the chunks */
+ for(u = 0; u < total_chunk; u++) {
+ H5D_chunk_info_t *chunk_info; /* Chunk info for current chunk */
+ H5S_t *fspace; /* Dataspace describing chunk & selection in it */
+ H5S_t *mspace; /* Dataspace describing selection in memory corresponding to this chunk */
- for(i = 0; i < total_chunk; i++) {
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
- HDfprintf(H5DEBUG(D),"mpi_rank = %d, chunk index = %u\n",mpi_rank,i);
+if(H5DEBUG(D))
+ HDfprintf(H5DEBUG(D),"mpi_rank = %d, chunk index = %Zu\n", mpi_rank, u);
#endif
- select_chunk = fm->select_chunk[i];
- if(select_chunk == 1){/* Have selection elements in this chunk. Find the chunk info. */
- if(NULL ==(chunk_node = H5SL_first(fm->fsel)))
- HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't get chunk node from skipped list");
-
- while(chunk_node){
- if(NULL ==(chunk_info = H5SL_item(chunk_node)))
- HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't get chunk info from skipped list");
- if(chunk_info->index == i) {
- /* Set dataset storage for I/O info */
- io_info->store=&store;
- /* Pass in chunk's coordinates in a union. */
- store.chunk.offset = chunk_info->coords;
- store.chunk.index = chunk_info->index;
- break;
- }
-
- chunk_node = H5SL_next(chunk_node);
- }
- }
-
- if(chunk_io_option[i] == 1){ /*collective IO for this chunk,
- note: even there is no selection for this process,
- the process still needs to contribute MPI NONE TYPE.*/
+ /* Get the chunk info for this chunk, if there are elements selected */
+ chunk_info = fm->select_chunk[u];
+
+ /* Set the storage information for chunks with selections */
+ if(chunk_info) {
+ HDassert(chunk_info->index == u);
+
+ /* Pass in chunk's coordinates in a union. */
+ store.chunk.offset = chunk_info->coords;
+ store.chunk.index = chunk_info->index;
+ } /* end if */
+
+ /* Collective IO for this chunk,
+ * Note: even there is no selection for this process, the process still
+ * needs to contribute MPI NONE TYPE.
+ */
+ if(chunk_io_option[u] == 1) {
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
- HDfprintf(H5DEBUG(D),"inside collective chunk IO mpi_rank = %d, chunk index = %u\n",mpi_rank,i);
+if(H5DEBUG(D))
+ HDfprintf(H5DEBUG(D),"inside collective chunk IO mpi_rank = %d, chunk index = %Zu\n", mpi_rank, u);
#endif
-
- if(!last_io_mode_coll)
- /* Switch back to collective I/O */
- if(H5D_ioinfo_make_coll(io_info) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't switch to collective I/O")
-
- if(select_chunk){
- if(H5D_inter_collective_io(io_info,chunk_info->fspace,chunk_info->mspace,
- chunk_addr[i],buf,do_write )<0)
- HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,"couldn't finish shared collective MPI-IO");
-
- }
- else{
- if(H5D_inter_collective_io(io_info,NULL,NULL,
- chunk_addr[i],buf,do_write )<0)
- HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,"couldn't finish shared collective MPI-IO");
-
- }
- last_io_mode_coll = TRUE;
-
- }
- else {/*possible independent IO for this chunk*/
+
+ /* Set the file & memory dataspaces */
+ if(chunk_info) {
+ fspace = chunk_info->fspace;
+ mspace = chunk_info->mspace;
+ } /* end if */
+ else {
+ fspace = mspace = NULL;
+ } /* end else */
+
+ /* Switch back to collective I/O */
+ if(last_xfer_mode != H5FD_MPIO_COLLECTIVE) {
+ if(H5D_ioinfo_xfer_mode(io_info, dx_plist, H5FD_MPIO_COLLECTIVE) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't switch to collective I/O")
+ last_xfer_mode = H5FD_MPIO_COLLECTIVE;
+ } /* end if */
+ if(last_coll_opt_mode != H5FD_MPIO_COLLECTIVE_IO) {
+ if(H5D_ioinfo_coll_opt_mode(io_info, dx_plist, H5FD_MPIO_COLLECTIVE_IO) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't switch to collective I/O")
+ last_coll_opt_mode = H5FD_MPIO_COLLECTIVE_IO;
+ } /* end if */
+
+ /* Initialize temporary contiguous storage address */
+ ctg_store.contig.dset_addr = chunk_addr[u];
+
+ /* Perform the I/O */
+ if(H5D_inter_collective_io(&ctg_io_info, type_info, fspace, mspace) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish shared collective MPI-IO")
+ } /* end if */
+ else { /* possible independent IO for this chunk */
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
- HDfprintf(H5DEBUG(D),"inside independent IO mpi_rank = %d, chunk index = %u\n",mpi_rank,i);
+if(H5DEBUG(D))
+ HDfprintf(H5DEBUG(D),"inside independent IO mpi_rank = %d, chunk index = %Zu\n", mpi_rank, u);
#endif
-
- HDassert(chunk_io_option[i] == 0);
+
+ HDassert(chunk_io_option[u] == 0);
#if !defined(H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS) || !defined(H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS)
- if(!select_chunk)
- continue; /* this process has nothing to do with this chunk, continue! */
- if(last_io_mode_coll)
+ /* Check if this process has somethign to do with this chunk */
+ if(chunk_info) {
+ H5D_io_info_t *chk_io_info; /* Pointer to I/O info object for this chunk */
+ H5D_chunk_ud_t udata; /* B-tree pass-through */
+ void *chunk; /* Pointer to the data chunk in cache */
+ uint32_t accessed_bytes; /* Total accessed size in a chunk */
+ unsigned idx_hint = 0; /* Cache index hint */
+
/* Switch to independent I/O */
- if(H5D_ioinfo_make_ind(io_info) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't switch to independent I/O")
-
- /* Load the chunk into cache. But if the whole chunk is written,
- * simply allocate space instead of load the chunk. */
- if(HADDR_UNDEF==(caddr = H5D_istore_get_addr(io_info, &udata)))
- HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't get chunk info from skipped list");
-
- if (H5D_istore_if_load(dataset, caddr)) {
- accessed_bytes = chunk_info->chunk_points * H5T_get_size(dataset->shared->type);
- if((do_write && (accessed_bytes != dataset->shared->layout.u.chunk.size)) || !do_write)
- relax=FALSE;
-
- if(NULL == (chunk = H5D_istore_lock(io_info, &udata, relax, &idx_hint)))
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk")
- } else
- chunk = NULL;
-
- if(do_write) {
- if((io_info->ops.write)(io_info,
- chunk_info->chunk_points,H5T_get_size(io_info->dset->shared->type),
- chunk_info->fspace,chunk_info->mspace,caddr,chunk, buf) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "optimized write failed")
- }
- else {
- if((io_info->ops.read)(io_info,
- chunk_info->chunk_points,H5T_get_size(io_info->dset->shared->type),
- chunk_info->fspace,chunk_info->mspace,caddr,chunk, buf) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "optimized read failed")
- }
+ if(last_xfer_mode != H5FD_MPIO_INDEPENDENT) {
+ if(H5D_ioinfo_xfer_mode(io_info, dx_plist, H5FD_MPIO_INDEPENDENT) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't switch to independent I/O")
+ last_xfer_mode = H5FD_MPIO_INDEPENDENT;
+ } /* end if */
- /* Release the cache lock on the chunk. */
- if (H5D_istore_if_load(dataset, caddr)) {
- if(!do_write) dirty = FALSE;
+ /* Load the chunk into cache. But if the whole chunk is written,
+ * simply allocate space instead of load the chunk.
+ */
+ if(H5D_chunk_get_info(io_info->dset, io_info->dxpl_id, chunk_info->coords, &udata) < 0)
+ HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL, "couldn't get chunk info from skipped list")
- if(H5D_istore_unlock(io_info, dirty, idx_hint, chunk, accessed_bytes) < 0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk")
- }
-#else
- if(!last_io_mode_coll)
- /* using independent I/O with file setview.*/
- if(H5D_ioinfo_make_coll_opt(io_info) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't switch to collective I/O")
- if(select_chunk){
- if(H5D_inter_collective_io(io_info,chunk_info->fspace,chunk_info->mspace,
- chunk_addr[i],buf,do_write )<0)
- HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,"couldn't finish shared collective MPI-IO");
- }
- else {
- if(H5D_inter_collective_io(io_info,NULL,NULL,
- chunk_addr[i],buf,do_write )<0)
- HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,"couldn't finish shared collective MPI-IO");
- }
+ /* Load the chunk into cache and lock it. */
+ if(H5D_chunk_cacheable(io_info, udata.addr)) {
+ hbool_t entire_chunk = TRUE; /* Whether whole chunk is selected */
+
+ /* Compute # of bytes accessed in chunk */
+ accessed_bytes = chunk_info->chunk_points * type_info->src_type_size;
+
+ /* Determine if we will access all the data in the chunk */
+ if(((io_info->op_type == H5D_IO_OP_WRITE) && (accessed_bytes != ctg_store.contig.dset_size))
+ || (io_info->op_type != H5D_IO_OP_WRITE))
+ entire_chunk = FALSE;
+
+ /* Lock the chunk into the cache */
+ if(NULL == (chunk = H5D_chunk_lock(io_info, &udata, entire_chunk, &idx_hint)))
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk")
+
+ /* Set up the storage buffer information for this chunk */
+ cpt_store.compact.buf = chunk;
+
+ /* Point I/O info at contiguous I/O info for this chunk */
+ chk_io_info = &cpt_io_info;
+ } /* end if */
+ else {
+ /* Set up the storage address information for this chunk */
+ ctg_store.contig.dset_addr = udata.addr;
+
+ /* No chunk cached */
+ chunk = NULL;
+
+ /* Point I/O info at temporary I/O info for this chunk */
+ chk_io_info = &ctg_io_info;
+ } /* end else */
+
+ if(io_info->op_type == H5D_IO_OP_WRITE) {
+ if((io_info->io_ops.single_write)(chk_io_info, type_info,
+ (hsize_t)chunk_info->chunk_points, chunk_info->fspace, chunk_info->mspace) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "optimized write failed")
+ } /* end if */
+ else {
+ if((io_info->io_ops.single_read)(chk_io_info, type_info,
+ (hsize_t)chunk_info->chunk_points, chunk_info->fspace, chunk_info->mspace) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "optimized read failed")
+ } /* end else */
+ /* Release the cache lock on the chunk. */
+ if(chunk && H5D_chunk_unlock(io_info, (io_info->op_type == H5D_IO_OP_WRITE), idx_hint, chunk, accessed_bytes) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk")
+ } /* end if */
+#else /* !defined(H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS) || !defined(H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS) */
+ /* Set the file & memory dataspaces */
+ if(chunk_info) {
+ fspace = chunk_info->fspace;
+ mspace = chunk_info->mspace;
+ } /* end if */
+ else {
+ fspace = mspace = NULL;
+ } /* end else */
+
+ /* Using independent I/O with file setview.*/
+ if(last_coll_opt_mode != H5FD_MPIO_INDIVIDUAL_IO) {
+ if(H5D_ioinfo_coll_opt_mode(io_info, dx_plist, H5FD_MPIO_INDIVIDUAL_IO) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't switch to individual I/O")
+ last_coll_opt_mode = H5FD_MPIO_INDIVIDUAL_IO;
+ } /* end if */
+
+ /* Initialize temporary contiguous storage address */
+ ctg_store.contig.dset_addr = chunk_addr[u];
+
+ /* Perform the I/O */
+ if(H5D_inter_collective_io(&ctg_io_info, type_info, fspace, mspace) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish shared collective MPI-IO")
#ifdef H5D_DEBUG
if(H5DEBUG(D))
HDfprintf(H5DEBUG(D),"after inter collective IO\n");
#endif
-#endif
- last_io_mode_coll = FALSE;
- }
- }
- if(!last_io_mode_coll)
- /* Switch back to collective I/O */
- if(H5D_ioinfo_make_coll(io_info) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't switch to collective I/O")
+#endif /* !defined(H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS) || !defined(H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS) */
+ } /* end else */
+ } /* end for */
+
done:
- HDfree(chunk_io_option);
- HDfree(chunk_addr);
+ if(chunk_io_option)
+ H5MM_xfree(chunk_io_option);
+ if(chunk_addr)
+ H5MM_xfree(chunk_addr);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_multi_chunk_collective_io */
@@ -1256,158 +1320,198 @@ done:
* non-contiguous(or with holes) storage efficiently.
* Under this case, the one independent IO call may consist of
* many small disk IOs. So we may use independent IO with derived datatype
- to replace the independent IO when we find this chunk is not good to
- do collective IO. However, according to our performance study,
- this approach may not overcome the overhead caused by MPI gather/scatter.
- So we decide to leave the original collective IO per chunk approach as
- an option for users. NO MPI gather/scatter calls are used.
- HDF5 will try to collective IO if possible.
- If users choose to use
- H5Pset_dxpl_mpio_chunk_opt(dxpl_id,H5FD_MPIO_OPT_MULTI_IO),
- this function will be called.
- The HDF5 library won't do any IO management but leave it to MPI-IO to figure
- out.
+ * to replace the independent IO when we find this chunk is not good to
+ * do collective IO. However, according to our performance study,
+ * this approach may not overcome the overhead caused by MPI gather/scatter.
+ * So we decide to leave the original collective IO per chunk approach as
+ * an option for users. NO MPI gather/scatter calls are used.
+ * HDF5 will try to collective IO if possible.
+ * If users choose to use
+ * H5Pset_dxpl_mpio_chunk_opt(dxpl_id,H5FD_MPIO_OPT_MULTI_IO),
+ * this function will be called.
+ * The HDF5 library won't do any IO management but leave it to MPI-IO to figure
+ * out.
*
* Return: Non-negative on success/Negative on failure
*
- * Programmer:
- *
- * Modifications:
+ * Programmer: Muqun Yang
+ * Monday, Feb. 13th, 2006
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5D_multi_chunk_collective_io_no_opt(H5D_io_info_t *io_info,fm_map *fm,const void *buf, hbool_t do_write)
+static herr_t
+H5D_multi_chunk_collective_io_no_opt(H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info, H5D_chunk_map_t *fm, H5P_genplist_t *dx_plist)
{
- int count_chunk,min_num_chunk;
- haddr_t chunk_addr;
- H5SL_node_t *chunk_node; /* Current node in chunk skip list */
- H5D_storage_t store; /* union of EFL and chunk pointer in file space */
- H5D_chunk_info_t *chunk_info; /* chunk information */
- hbool_t make_ind, make_coll; /* Flags to indicate that the MPI mode should change */
-
- void *chunk = NULL; /* Pointer to the data chunk in cache */
- H5D_t *dataset=io_info->dset;/* Local pointer to dataset info */
- H5D_istore_ud1_t udata; /*B-tree pass-through */
- size_t accessed_bytes; /*total accessed size in a chunk */
- unsigned idx_hint=0; /* Cache index hint */
- hbool_t dirty = TRUE; /* Flag for cache flushing */
- hbool_t relax=TRUE; /* Whether whole chunk is selected */
- herr_t ret_value = SUCCEED;
-
-#ifdef H5Dmpio_DEBUG
- int mpi_rank;
-#endif
+ H5D_t *dataset = io_info->dset;/* Local pointer to dataset info */
+ H5SL_node_t *chunk_node; /* Current node in chunk skip list */
+ H5D_io_info_t ctg_io_info; /* Contiguous I/O info object */
+ H5D_storage_t ctg_store; /* Chunk storage information as contiguous dataset */
+ H5D_io_info_t cpt_io_info; /* Compact I/O info object */
+ H5D_storage_t cpt_store; /* Chunk storage information as compact dataset */
+ hbool_t cpt_dirty; /* Temporary placeholder for compact storage "dirty" flag */
+ int min_chunk = -1; /* Minimum # of chunks all processes will operate on */
+ int count_chunk; /* How many chunks have we operated on? */
+ H5D_storage_t store; /* union of EFL and chunk pointer in file space */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_multi_chunk_collective_io_no_opt)
- FUNC_ENTER_NOAPI_NOINIT(H5D_multi_chunk_collective_io_no_opt)
#ifdef H5D_DEBUG
- if(H5DEBUG(D)){
+if(H5DEBUG(D)) {
+ int mpi_rank;
+
mpi_rank = H5F_mpi_get_rank(io_info->dset->oloc.file);
- HDfprintf(H5DEBUG(D),"coming to multi_chunk_collective_io_no_opt\n");
- }
+ HDfprintf(H5DEBUG(D), "coming to multi_chunk_collective_io_no_opt\n");
+}
#endif
- if(H5D_mpio_get_min_chunk(io_info,fm,&min_num_chunk)<0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get minimum number of chunk");
- count_chunk = 0;
-
- /* Get first node in chunk skip list */
- chunk_node=H5SL_first(fm->fsel);
-
- /* Iterate through chunks to be operated on */
- while(chunk_node) {
- H5D_chunk_info_t *chunk_info; /* chunk information */
- hbool_t make_ind, make_coll; /* Flags to indicate that the MPI mode should change */
-
- /* Get the actual chunk information from the skip list node */
- chunk_info=H5SL_item(chunk_node);
-
- /* Set dataset storage for I/O info */
- io_info->store=&store;
-
- /* Pass in chunk's coordinates in a union. */
- store.chunk.offset = chunk_info->coords;
- store.chunk.index = chunk_info->index;
-
- /* Reset flags for changing parallel I/O mode */
- make_ind = make_coll = FALSE;
-
- count_chunk++;
- /* If the number of chunk is greater than minimum number of chunk,
- Do independent read */
- if(count_chunk > min_num_chunk) {
- /* Switch to independent I/O (permanently) */
- make_ind = TRUE;
- }
+ /* Set up contiguous I/O info object */
+ HDmemcpy(&ctg_io_info, io_info, sizeof(ctg_io_info));
+ ctg_io_info.store = &ctg_store;
+ ctg_io_info.layout_ops = *H5D_LOPS_CONTIG;
+
+ /* Initialize temporary contiguous storage info */
+ ctg_store.contig.dset_size = (hsize_t)io_info->dset->shared->layout.u.chunk.size;
+
+ /* Set up compact I/O info object */
+ HDmemcpy(&cpt_io_info, io_info, sizeof(cpt_io_info));
+ cpt_io_info.store = &cpt_store;
+ cpt_io_info.layout_ops = *H5D_LOPS_COMPACT;
+
+ /* Initialize temporary compact storage info */
+ cpt_store.compact.dirty = &cpt_dirty;
+
+ /* Set dataset storage for I/O info */
+ io_info->store = &store;
+
+ /* Get the min. # of chunks */
+ if(H5D_mpio_get_min_chunk(io_info, fm, &min_chunk) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get minimum number of chunk")
+ HDassert(min_chunk >= 0);
+
+ /* Get first node in chunk skip list */
+ chunk_node = H5SL_first(fm->sel_chunks);
+ count_chunk = 0;
+
+ /* Iterate through chunks to be operated on */
+ while(chunk_node) {
+ H5D_chunk_info_t *chunk_info; /* chunk information */
+ H5D_chunk_ud_t udata; /* B-tree pass-through */
+ hbool_t make_ind, make_coll; /* Flags to indicate that the MPI mode should change */
+
+ /* Get the actual chunk information from the skip list node */
+ chunk_info = H5SL_item(chunk_node);
+
+ /* Pass in chunk's coordinates in a union. */
+ store.chunk.offset = chunk_info->coords;
+ store.chunk.index = chunk_info->index;
+
+ /* Reset flags for changing parallel I/O mode */
+ make_ind = make_coll = FALSE;
+
+ count_chunk++;
+ /* If the number of chunk is greater than minimum number of chunk,
+ * Do independent read.
+ */
+ if(count_chunk > min_chunk)
+ /* Switch to independent I/O (permanently) */
+ make_ind = TRUE;
#ifndef H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS
/* This case needs to be improved to check if the selected space
is regular. If all selections are regular, collective IO can still be done.
However, since we find an MPI-IO bug at a DOE machine(mcr) that cannot
- handle collective I/O selection for this case correctly,
+ handle collective I/O selection for this case correctly,
we turn off this optimization but leave the following code
for future optimization. Otherwise, the following else {} doesn't make sense.
KY 2006/8/4/ */
- else {
- /* Switch to independent I/O (temporarily) */
- make_ind = TRUE;
- make_coll = TRUE;
- } /* end else */
+ else {
+ /* Switch to independent I/O (temporarily) */
+ make_ind = TRUE;
+ make_coll = TRUE;
+ } /* end else */
#endif /* H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS */
+ /* Retrieve the chunk's address */
+ if(H5D_chunk_get_info(io_info->dset, io_info->dxpl_id, chunk_info->coords, &udata) < 0)
+ HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL, "couldn't get chunk info from skipped list")
+
+ /* Independent I/O */
+ if(make_ind) {
+ void *chunk; /* Pointer to the data chunk in cache */
+ H5D_io_info_t *chk_io_info; /* Pointer to I/O info object for this chunk */
+ uint32_t accessed_bytes = 0; /* Total accessed size in a chunk */
+ unsigned idx_hint = 0; /* Cache index hint */
+
/* Switch to independent I/O */
- if(make_ind)
- if(H5D_ioinfo_make_ind(io_info) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't switch to independent I/O")
+ if(H5D_ioinfo_xfer_mode(io_info, dx_plist, H5FD_MPIO_INDEPENDENT) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't switch to independent I/O")
- if(HADDR_UNDEF==(chunk_addr = H5D_istore_get_addr(io_info, &udata)))
- HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't get chunk info from skipped list");
+ /* Load the chunk into cache and lock it. */
+ if(H5D_chunk_cacheable(io_info, udata.addr)) {
+ hbool_t entire_chunk = TRUE; /* Whether whole chunk is selected */
- if(make_ind) {/*independent I/O */
- /* Load the chunk into cache. But if the whole chunk is written,
- * simply allocate space instead of load the chunk. */
- if (H5D_istore_if_load(dataset, chunk_addr)) {
- accessed_bytes = chunk_info->chunk_points * H5T_get_size(dataset->shared->type);
- if((do_write && (accessed_bytes != dataset->shared->layout.u.chunk.size)) || !do_write)
- relax=FALSE;
-
- if(NULL == (chunk = H5D_istore_lock(io_info, &udata, relax, &idx_hint)))
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk")
- } else
- chunk = NULL;
-
- if(do_write) {
- if((io_info->ops.write)(io_info,
- chunk_info->chunk_points,H5T_get_size(io_info->dset->shared->type),
- chunk_info->fspace,chunk_info->mspace, chunk_addr, chunk, buf) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "optimized write failed")
- } else {
- if((io_info->ops.read)(io_info,
- chunk_info->chunk_points,H5T_get_size(io_info->dset->shared->type),
- chunk_info->fspace,chunk_info->mspace, chunk_addr, chunk, buf) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "optimized read failed")
- }
+ /* Compute # of bytes accessed in chunk */
+ accessed_bytes = chunk_info->chunk_points * type_info->src_type_size;
- /* Release the cache lock on the chunk. */
- if (H5D_istore_if_load(dataset, chunk_addr)) {
- if(!do_write) dirty = FALSE;
-
- if(H5D_istore_unlock(io_info, dirty, idx_hint, chunk, accessed_bytes) < 0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk")
- }
- }
- else { /*collective I/O */
- if(H5D_inter_collective_io(io_info,chunk_info->fspace,chunk_info->mspace,
- chunk_addr,buf,do_write ) < 0)
- HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,"couldn't finish shared collective MPI-IO");
- }
-
- if(make_coll)
- if(H5D_ioinfo_make_coll(io_info) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't switch to independent I/O")
- /* Get the next chunk node in the skip list */
- chunk_node=H5SL_next(chunk_node);
- } /* end while */
+ /* Determine if we will access all the data in the chunk */
+ if(((io_info->op_type == H5D_IO_OP_WRITE) && (accessed_bytes != ctg_store.contig.dset_size))
+ || (io_info->op_type != H5D_IO_OP_WRITE))
+ entire_chunk = FALSE;
+
+ /* Lock the chunk into the cache */
+ if(NULL == (chunk = H5D_chunk_lock(io_info, &udata, entire_chunk, &idx_hint)))
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk")
+
+ /* Set up the storage buffer information for this chunk */
+ cpt_store.compact.buf = chunk;
+
+ /* Point I/O info at contiguous I/O info for this chunk */
+ chk_io_info = &cpt_io_info;
+ } /* end if */
+ else {
+ /* Set up the storage address information for this chunk */
+ ctg_store.contig.dset_addr = udata.addr;
+
+ /* No chunk cached */
+ chunk = NULL;
+
+ /* Point I/O info at temporary I/O info for this chunk */
+ chk_io_info = &ctg_io_info;
+ } /* end else */
+
+ if(io_info->op_type == H5D_IO_OP_WRITE) {
+ if((io_info->io_ops.single_write)(chk_io_info, type_info,
+ (hsize_t)chunk_info->chunk_points, chunk_info->fspace, chunk_info->mspace) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "optimized write failed")
+ } /* end if */
+ else {
+ if((io_info->io_ops.single_read)(chk_io_info, type_info,
+ (hsize_t)chunk_info->chunk_points, chunk_info->fspace, chunk_info->mspace) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "optimized read failed")
+ } /* end ese */
+
+ /* Release the cache lock on the chunk. */
+ if(chunk)
+ if(H5D_chunk_unlock(io_info, (io_info->op_type == H5D_IO_OP_WRITE), idx_hint, chunk, accessed_bytes) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk")
+ } /* end if */
+ else { /*collective I/O */
+ /* Set up the storage address information for this chunk */
+ ctg_store.contig.dset_addr = udata.addr;
+
+ if(H5D_inter_collective_io(&ctg_io_info, type_info, chunk_info->fspace, chunk_info->mspace) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,"couldn't finish shared collective MPI-IO")
+ } /* end else */
+
+ if(make_coll)
+ if(H5D_ioinfo_xfer_mode(io_info, dx_plist, H5FD_MPIO_COLLECTIVE) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't switch to independent I/O")
+
+ /* Get the next chunk node in the skip list */
+ chunk_node = H5SL_next(chunk_node);
+ } /* end while */
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1418,615 +1522,510 @@ done:
* Function: H5D_inter_collective_io
*
* Purpose: Routine for the shared part of collective IO between multiple chunk
- collective IO and contiguous collective IO
-
+ * collective IO and contiguous collective IO
*
* Return: Non-negative on success/Negative on failure
*
- * Programmer:
- *
- * Modifications:
+ * Programmer: Muqun Yang
+ * Monday, Feb. 13th, 2006
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5D_inter_collective_io(H5D_io_info_t *io_info,const H5S_t *file_space,const H5S_t *mem_space,
- haddr_t addr, const void *buf, hbool_t do_write )
+static herr_t
+H5D_inter_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ const H5S_t *file_space, const H5S_t *mem_space)
{
+ size_t mpi_buf_count; /* # of MPI types */
+ hbool_t mbt_is_derived = FALSE;
+ hbool_t mft_is_derived = FALSE;
+ MPI_Datatype mpi_file_type, mpi_buf_type;
+ int mpi_code; /* MPI return code */
+ herr_t ret_value = SUCCEED; /* return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_inter_collective_io)
- size_t mpi_buf_count, mpi_file_count; /* Number of "objects" to transfer */
- MPI_Datatype mpi_file_type,mpi_buf_type;
- hsize_t mpi_buf_offset, mpi_file_offset; /* Offset within dataset where selection (ie. MPI type) begins */
- hbool_t mbt_is_derived=0, /* Whether the buffer (memory) type is derived and needs to be free'd */
- mft_is_derived=0; /* Whether the file type is derived and needs to be free'd */
- H5D_common_coll_info_t coll_info;
- herr_t ret_value = SUCCEED; /* return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_inter_collective_io)
- if((file_space!=NULL) && (mem_space != NULL)) {
- /*Obtain disk and memory MPI derived datatype */
- if(H5S_mpio_space_type(file_space,H5T_get_size(io_info->dset->shared->type),
- &mpi_file_type,&mpi_file_count,&mpi_file_offset,&mft_is_derived)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't create MPI file type");
-
- if(H5S_mpio_space_type(mem_space,H5T_get_size(io_info->dset->shared->type),
- &mpi_buf_type,&mpi_buf_count,&mpi_buf_offset,&mbt_is_derived)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL,"couldn't create MPI buffer type");
-
- }
- else {
- /* For non-selection, participate with a none MPI derived datatype, the count is 0. */
- mpi_buf_type = MPI_BYTE;
- mpi_file_type = MPI_BYTE;
- mpi_file_count = 0;
- mpi_buf_count = 0;
- }
-
- coll_info.mbt_is_derived = mbt_is_derived;
- coll_info.mft_is_derived = mft_is_derived;
- coll_info.mpi_buf_count = mpi_buf_count;
- coll_info.chunk_addr = addr;
+ if((file_space != NULL) && (mem_space != NULL)) {
+ hsize_t mpi_buf_offset, mpi_file_offset; /* Offset within dataset where selection (ie. MPI type) begins */
+ size_t mpi_file_count; /* Number of file "objects" to transfer */
+
+ /* Obtain disk and memory MPI derived datatype */
+ if(H5S_mpio_space_type(file_space, type_info->src_type_size,
+ &mpi_file_type, &mpi_file_count, &mpi_file_offset, &mft_is_derived) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't create MPI file type")
+ if(H5S_mpio_space_type(mem_space, type_info->src_type_size,
+ &mpi_buf_type, &mpi_buf_count, &mpi_buf_offset, &mbt_is_derived) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "couldn't create MPI buffer type")
+ } /* end if */
+ else {
+ /* For non-selection, participate with a none MPI derived datatype, the count is 0. */
+ mpi_buf_type = MPI_BYTE;
+ mpi_file_type = MPI_BYTE;
+ mpi_buf_count = (size_t)0;
+ mbt_is_derived = FALSE;
+ mft_is_derived = FALSE;
+ } /* end else */
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
- HDfprintf(H5DEBUG(D),"before final collective IO \n");
+if(H5DEBUG(D))
+ HDfprintf(H5DEBUG(D),"before final collective IO \n");
#endif
- if(H5D_final_collective_io(io_info,&mpi_file_type,&mpi_buf_type,&coll_info,buf,do_write)<0)
- HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL,"couldn't finish collective MPI-IO");
- done:
+ /* Perform final collective I/O operation */
+ if(H5D_final_collective_io(io_info, type_info, mpi_buf_count, &mpi_file_type, &mpi_buf_type) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "couldn't finish collective MPI-IO")
+
+done:
+ /* Free the MPI buf and file types, if they were derived */
+ if(mbt_is_derived && MPI_SUCCESS != (mpi_code = MPI_Type_free(&mpi_buf_type)))
+ HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code)
+ if(mft_is_derived && MPI_SUCCESS != (mpi_code = MPI_Type_free(&mpi_file_type)))
+ HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code)
+
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
+if(H5DEBUG(D))
HDfprintf(H5DEBUG(D),"before leaving inter_collective_io ret_value = %d\n",ret_value);
#endif
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_inter_collective_io */
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_inter_collective_io() */
/*-------------------------------------------------------------------------
* Function: H5D_final_collective_io
*
* Purpose: Routine for the common part of collective IO with different storages.
-
*
* Return: Non-negative on success/Negative on failure
*
- * Programmer:
- *
- * Modifications:
+ * Programmer: Muqun Yang
+ * Monday, Feb. 13th, 2006
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5D_final_collective_io(H5D_io_info_t *io_info,MPI_Datatype*mpi_file_type,MPI_Datatype *mpi_buf_type,
- H5D_common_coll_info_t* coll_info, const void *buf, hbool_t do_write)
+static herr_t
+H5D_final_collective_io(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ size_t mpi_buf_count, MPI_Datatype *mpi_file_type, MPI_Datatype *mpi_buf_type)
{
-
-
- int mpi_code; /* MPI return code */
- hbool_t plist_is_setup=0; /* Whether the dxpl has been customized */
- herr_t ret_value = SUCCEED;
-
+ int mpi_code; /* MPI return code */
+ hbool_t plist_is_setup = FALSE; /* Whether the dxpl has been customized */
+ herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT(H5D_final_collective_io)
- /*
- * Pass buf type, file type to the file driver.
- */
-
- if(H5FD_mpi_setup_collective(io_info->dxpl_id, *mpi_buf_type, *mpi_file_type)<0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set MPI-I/O properties");
-
- plist_is_setup=1;
-#ifdef H5D_DEBUG
- if(H5DEBUG(D)){
- HDfprintf(H5DEBUG(D),"chunk addr %Hu\n",coll_info->chunk_addr);
- HDfprintf(H5DEBUG(D),"mpi_buf_count %d\n",coll_info->mpi_buf_count);
- }
-
-#endif
+ /* Pass buf type, file type to the file driver. */
+ if(H5FD_mpi_setup_collective(io_info->dxpl_id, *mpi_buf_type, *mpi_file_type) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set MPI-I/O properties")
+ plist_is_setup = TRUE;
- if(do_write) {
- if((io_info->ops.write)(io_info,
- coll_info->mpi_buf_count,0,NULL,NULL,coll_info->chunk_addr,
- NULL, buf) < 0)
+ if(io_info->op_type == H5D_IO_OP_WRITE) {
+ if((io_info->io_ops.single_write)(io_info, type_info,
+ (hsize_t)mpi_buf_count, NULL, NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "optimized write failed")
- }
+ } /* end if */
else {
- if((io_info->ops.read)(io_info,
- coll_info->mpi_buf_count,0,NULL,NULL,coll_info->chunk_addr,
- NULL, buf) < 0)
+ if((io_info->io_ops.single_read)(io_info, type_info,
+ (hsize_t)mpi_buf_count, NULL, NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "optimized read failed")
- }
+ } /* end else */
done:
- /* Reset the dxpl settings */
- if(plist_is_setup) {
- if(H5FD_mpi_teardown_collective(io_info->dxpl_id)<0)
- HDONE_ERROR(H5E_DATASPACE, H5E_CANTFREE, FAIL, "unable to reset dxpl values");
- } /* end if */
-
- /* free the MPI buf and file types */
- if (coll_info->mbt_is_derived) {
- if (MPI_SUCCESS != (mpi_code= MPI_Type_free( mpi_buf_type )))
- HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code);
- }
- if (coll_info->mft_is_derived) {
- if (MPI_SUCCESS != (mpi_code= MPI_Type_free( mpi_file_type )))
- HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code);
- }
+ /* Reset the dxpl settings */
+ if(plist_is_setup)
+ if(H5FD_mpi_teardown_collective(io_info->dxpl_id) < 0)
+ HDONE_ERROR(H5E_DATASPACE, H5E_CANTFREE, FAIL, "unable to reset dxpl values")
+
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
+if(H5DEBUG(D))
HDfprintf(H5DEBUG(D),"ret_value before leaving final_collective_io=%d\n",ret_value);
#endif
-
FUNC_LEAVE_NOAPI(ret_value)
-}/* end H5D_final_collective_io */
+} /* end H5D_final_collective_io */
/*-------------------------------------------------------------------------
* Function: H5D_sort_chunk
*
* Purpose: Routine to sort chunks in increasing order of chunk address
- Each chunk address is also obtained.
-
- Description:
- For most cases, the chunk address has already been sorted in increasing order.
- The special sorting flag is used to optimize this common case.
- quick sort is used for necessary sorting.
-
- Parameters:
- Input: H5D_io_info_t* io_info,
- fm_map *fm(global chunk map struct)
- Input/Output: H5D_chunk_addr_info_t chunk_addr_info_array[] : array to store chunk address and information
- many_chunk_opt : flag to optimize the way to obtain chunk addresses
- for many chunks
+ * Each chunk address is also obtained.
*
- * Return: Non-negative on success/Negative on failure
+ * Description:
+ * For most cases, the chunk address has already been sorted in increasing order.
+ * The special sorting flag is used to optimize this common case.
+ * quick sort is used for necessary sorting.
*
- * Programmer:
+ * Parameters:
+ * Input: H5D_io_info_t* io_info,
+ * H5D_chunk_map_t *fm(global chunk map struct)
+ * Input/Output: H5D_chunk_addr_info_t chunk_addr_info_array[] : array to store chunk address and information
+ * many_chunk_opt : flag to optimize the way to obtain chunk addresses
+ * for many chunks
+ *
+ * Return: Non-negative on success/Negative on failure
*
- * Modifications:
+ * Programmer: Muqun Yang
+ * Monday, Feb. 13th, 2006
*
*-------------------------------------------------------------------------
*/
-
-static herr_t
-H5D_sort_chunk(H5D_io_info_t * io_info,
- fm_map *fm,
- H5D_chunk_addr_info_t chunk_addr_info_array[],
- int many_chunk_opt)
+static herr_t
+H5D_sort_chunk(H5D_io_info_t *io_info, const H5D_chunk_map_t *fm,
+ H5D_chunk_addr_info_t chunk_addr_info_array[], int sum_chunk)
{
-
-
- H5SL_node_t *chunk_node; /* Current node in chunk skip list */
+ H5SL_node_t *chunk_node; /* Current node in chunk skip list */
H5D_chunk_info_t *chunk_info; /* Current chunking info. of this node. */
- haddr_t chunk_addr; /* Current chunking address of this node */
- haddr_t *total_chunk_addr_array=NULL; /* The array of chunk address for the total number of chunk */
- int i,mpi_code;
- int total_chunks;
- size_t num_chunks;
- int mpi_type_cleanup = 0;
- int tchunk_addr_cleanup = 0;
- MPI_Datatype chunk_addrtype;
- H5D_storage_t store; /*union of EFL and chunk pointer in file space */
- hbool_t do_sort = FALSE;
- herr_t ret_value = SUCCEED; /*return value */
-
+ haddr_t chunk_addr; /* Current chunking address of this node */
+ haddr_t *total_chunk_addr_array = NULL; /* The array of chunk address for the total number of chunk */
+ hbool_t do_sort = FALSE; /* Whether the addresses need to be sorted */
+ int bsearch_coll_chunk_threshold;
+ int many_chunk_opt = H5D_OBTAIN_ONE_CHUNK_ADDR_IND;
+ int mpi_size; /* Number of MPI processes */
+ int mpi_code; /* MPI return code */
+ int i; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
FUNC_ENTER_NOAPI_NOINIT(H5D_sort_chunk)
- num_chunks = H5SL_count(fm->fsel);
+ /* Retrieve # of MPI processes */
+ if((mpi_size = H5F_mpi_get_size(io_info->dset->oloc.file)) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi size")
+
+ /* Calculate the actual threshold to obtain all chunk addresses collectively
+ * The bigger this number is, the more possible the use of obtaining chunk
+ * address collectively.
+ */
+ /* For non-optimization one-link IO, actual bsearch threshold is always
+ * 0, we would always want to obtain the chunk addresses individually
+ * for each process.
+ */
+ bsearch_coll_chunk_threshold = (sum_chunk * 100) / ((int)fm->total_chunks * mpi_size);
+ if((bsearch_coll_chunk_threshold > H5D_ALL_CHUNK_ADDR_THRES_COL)
+ && ((sum_chunk / mpi_size) >= H5D_ALL_CHUNK_ADDR_THRES_COL_NUM))
+ many_chunk_opt = H5D_OBTAIN_ALL_CHUNK_ADDR_COL;
+
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
- HDfprintf(H5DEBUG(D),"many_chunk_opt= %d\n",many_chunk_opt);
+if(H5DEBUG(D))
+ HDfprintf(H5DEBUG(D), "many_chunk_opt= %d\n", many_chunk_opt);
#endif
/* If we need to optimize the way to obtain the chunk address */
- if(many_chunk_opt != H5D_OBTAIN_ONE_CHUNK_ADDR_IND){
+ if(many_chunk_opt != H5D_OBTAIN_ONE_CHUNK_ADDR_IND) {
+ int mpi_rank;
- int mpi_rank, root;
- total_chunks = (int)fm->total_chunks;
- total_chunk_addr_array = H5MM_malloc(sizeof(haddr_t)*total_chunks);
- tchunk_addr_cleanup = 1;
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
- HDfprintf(H5DEBUG(D),"Coming inside H5D_OBTAIN_ALL_CHUNK_ADDR_COL\n");
+if(H5DEBUG(D))
+ HDfprintf(H5DEBUG(D), "Coming inside H5D_OBTAIN_ALL_CHUNK_ADDR_COL\n");
#endif
- root = 0;
- if((mpi_rank = H5F_mpi_get_rank(io_info->dset->oloc.file))<0)
- HGOTO_ERROR (H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi rank");
-
- /*Create received MPI derived datatype */
- if(MPI_SUCCESS !=(mpi_code = MPI_Type_contiguous((int)(sizeof(haddr_t)*total_chunks), MPI_BYTE, &chunk_addrtype)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code);
- if(MPI_SUCCESS !=(mpi_code = MPI_Type_commit(&chunk_addrtype)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code);
-
- mpi_type_cleanup = 1;
-
- if(mpi_rank == root) {
- if(H5D_istore_chunkmap(io_info, total_chunk_addr_array, fm->down_chunks)<0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk address");
- }
+ /* Allocate array for chunk addresses */
+ if(NULL == (total_chunk_addr_array = H5MM_malloc(sizeof(haddr_t) * (size_t)fm->total_chunks)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory chunk address array")
+
+ /* Retrieve all the chunk addresses with process 0 */
+ if((mpi_rank = H5F_mpi_get_rank(io_info->dset->oloc.file)) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi rank")
+ if(mpi_rank == 0) {
+ if(H5D_chunk_addrmap(io_info, total_chunk_addr_array, fm->down_chunks) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk address")
+ } /* end if */
+
/* Broadcasting the MPI_IO option info. and chunk address info. */
- if(MPI_SUCCESS !=(mpi_code = MPI_Bcast(total_chunk_addr_array,1,chunk_addrtype,root,io_info->comm)))
- HMPI_GOTO_ERROR(FAIL, "MPI_BCast failed", mpi_code);
+ if(MPI_SUCCESS != (mpi_code = MPI_Bcast(total_chunk_addr_array, (int)(sizeof(haddr_t) * fm->total_chunks), MPI_BYTE, (int)0, io_info->comm)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_BCast failed", mpi_code)
} /* end if */
- /* Get first node in chunk skip list */
- if(NULL ==(chunk_node = H5SL_first(fm->fsel)))
- HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't get chunk node from skipped list");
- /* Set dataset storage for I/O info */
- io_info->store = &store;
- if(NULL ==(chunk_info = H5SL_item(chunk_node)))
- HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't get chunk info from skipped list");
- store.chunk.offset = chunk_info->coords;
- store.chunk.index = chunk_info->index;
+ /* Start at first node in chunk skip list */
i = 0;
- if(many_chunk_opt == H5D_OBTAIN_ONE_CHUNK_ADDR_IND){
- if(HADDR_UNDEF==(chunk_addr = H5D_istore_get_addr(io_info,NULL)))
- HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't get chunk info from skipped list");
+ if(NULL == (chunk_node = H5SL_first(fm->sel_chunks)))
+ HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't get chunk node from skipped list")
-#ifdef H5D_DEBUG
- if(H5DEBUG(D))
- HDfprintf(H5DEBUG(D),"coming to obtain each chunk address individually \n");
-#endif
- }
- else
- chunk_addr = total_chunk_addr_array[chunk_info->index];
+ /* Iterate over all chunks for this process */
+ while(chunk_node) {
+ if(NULL == (chunk_info = H5SL_item(chunk_node)))
+ HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't get chunk info from skipped list")
- chunk_addr_info_array[i].chunk_addr = chunk_addr;
- chunk_addr_info_array[i].chunk_info = *chunk_info;
+ if(many_chunk_opt == H5D_OBTAIN_ONE_CHUNK_ADDR_IND) {
+ H5D_chunk_ud_t udata; /* User data for querying chunk info */
- chunk_node = H5SL_next(chunk_node);
+ /* Get address of chunk */
+ if(H5D_chunk_get_info(io_info->dset, io_info->dxpl_id, chunk_info->coords, &udata) < 0)
+ HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL, "couldn't get chunk info from skipped list")
+ chunk_addr = udata.addr;
+ } /* end if */
+ else
+ chunk_addr = total_chunk_addr_array[chunk_info->index];
- while(chunk_node) {
+ /* Check if chunk addresses are not in increasing order in the file */
+ if(i > 0 && chunk_addr < chunk_addr_info_array[i - 1].chunk_addr)
+ do_sort = TRUE;
+
+ /* Set the address & info for this chunk */
+ chunk_addr_info_array[i].chunk_addr = chunk_addr;
+ chunk_addr_info_array[i].chunk_info = *chunk_info;
+
+ /* Advance to next chunk in list */
+ i++;
+ chunk_node = H5SL_next(chunk_node);
+ } /* end while */
- chunk_info = H5SL_item(chunk_node);
- store.chunk.offset = chunk_info->coords;
- store.chunk.index = chunk_info->index;
-
- if(many_chunk_opt == H5D_OBTAIN_ONE_CHUNK_ADDR_IND){
- if(HADDR_UNDEF==(chunk_addr = H5D_istore_get_addr(io_info,NULL)))
- HGOTO_ERROR(H5E_STORAGE, H5E_CANTGET, FAIL,"couldn't get chunk info from skipped list");
- }
- else
- chunk_addr = total_chunk_addr_array[chunk_info->index];
-
- if(chunk_addr < chunk_addr_info_array[i].chunk_addr) do_sort = TRUE;
- chunk_addr_info_array[i+1].chunk_addr = chunk_addr;
- chunk_addr_info_array[i+1].chunk_info =*chunk_info;
- i++;
- chunk_node = H5SL_next(chunk_node);
- }
#ifdef H5D_DEBUG
- if(H5DEBUG(D))
- HDfprintf(H5DEBUG(D),"before Qsort\n");
+if(H5DEBUG(D))
+ HDfprintf(H5DEBUG(D), "before Qsort\n");
#endif
- if(do_sort)
- HDqsort(chunk_addr_info_array,num_chunks,sizeof(chunk_addr_info_array),H5D_cmp_chunk_addr);
+ if(do_sort) {
+ size_t num_chunks = H5SL_count(fm->sel_chunks);
+
+ HDqsort(chunk_addr_info_array, num_chunks, sizeof(chunk_addr_info_array[0]), H5D_cmp_chunk_addr);
+ } /* end if */
done:
+ if(total_chunk_addr_array)
+ H5MM_xfree(total_chunk_addr_array);
- if(tchunk_addr_cleanup)
- HDfree(total_chunk_addr_array);
- if(mpi_type_cleanup) {
- if (MPI_SUCCESS != (mpi_code= MPI_Type_free( &chunk_addrtype )))
- HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code);
- }
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_sort_chunk() */
-
+
/*-------------------------------------------------------------------------
* Function: H5D_obtain_mpio_mode
*
* Purpose: Routine to obtain each io mode(collective,independent or none) for each chunk;
- Each chunk address is also obtained.
-
- Description:
-
- 1) Each process provides two piece of information for all chunks having selection
- a) chunk index
- b) wheather this chunk is regular(for MPI derived datatype not working case)
-
- 2) Gather all the information to the root process
-
- 3) Root process will do the following:
- a) Obtain chunk addresses for all chunks in this data space
- b) With the consideration of the user option, calculate IO mode for each chunk
- c) Build MPI derived datatype to combine "chunk address" and "assign_io" information
- in order to do MPI Bcast only once
- d) MPI Bcast the IO mode and chunk address information for each chunk.
- 4) Each process then retrieves IO mode and chunk address information to assign_io_mode and chunk_addr.
-
- Parameters:
-
- Input: H5D_io_info_t* io_info,
- fm_map *fm,(global chunk map struct)
- Output: uint8_t assign_io_mode[], : IO mode, collective, independent or none
- haddr_t chunk_addr[], : chunk address array for each chunk
+ * Each chunk address is also obtained.
*
- * Return: Non-negative on success/Negative on failure
+ * Description:
*
- * Programmer:
+ * 1) Each process provides two piece of information for all chunks having selection
+ * a) chunk index
+ * b) wheather this chunk is regular(for MPI derived datatype not working case)
+ *
+ * 2) Gather all the information to the root process
+ *
+ * 3) Root process will do the following:
+ * a) Obtain chunk addresses for all chunks in this data space
+ * b) With the consideration of the user option, calculate IO mode for each chunk
+ * c) Build MPI derived datatype to combine "chunk address" and "assign_io" information
+ * in order to do MPI Bcast only once
+ * d) MPI Bcast the IO mode and chunk address information for each chunk.
+ * 4) Each process then retrieves IO mode and chunk address information to assign_io_mode and chunk_addr.
*
- * Modifications:
+ * Parameters:
+ *
+ * Input: H5D_io_info_t* io_info,
+ * H5D_chunk_map_t *fm,(global chunk map struct)
+ * Output: uint8_t assign_io_mode[], : IO mode, collective, independent or none
+ * haddr_t chunk_addr[], : chunk address array for each chunk
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Muqun Yang
+ * Monday, Feb. 13th, 2006
*
*-------------------------------------------------------------------------
*/
-
-static herr_t
-H5D_obtain_mpio_mode(H5D_io_info_t* io_info,
- fm_map *fm,
- uint8_t assign_io_mode[],
- haddr_t chunk_addr[])
+static herr_t
+H5D_obtain_mpio_mode(H5D_io_info_t* io_info, H5D_chunk_map_t *fm,
+ H5P_genplist_t *dx_plist, uint8_t assign_io_mode[], haddr_t chunk_addr[])
{
-
- int total_chunks;
- hsize_t ori_total_chunks;
- unsigned percent_nproc_per_chunk,threshold_nproc_per_chunk;
- H5FD_mpio_chunk_opt_t chunk_opt_mode;
- uint8_t* io_mode_info=NULL;
- uint8_t* recv_io_mode_info=NULL;
- uint8_t* mergebuf=NULL;
- uint8_t* tempbuf;
-
- H5SL_node_t* chunk_node;
- H5D_chunk_info_t* chunk_info;
-
- MPI_Datatype bastype[2];
- MPI_Datatype chunk_addrtype;
- int bascount;
- int basblock[2];
- MPI_Aint basdisp[2];
- MPI_Datatype rtype;
- MPI_Datatype stype;
- int mpi_size,mpi_rank;
- MPI_Comm comm;
- int ic,root;
- int mpi_code;
- H5P_genplist_t *plist;
- int mem_cleanup = 0,
- mpi_type_cleanup = 0;
-
+ int total_chunks;
+ unsigned percent_nproc_per_chunk,threshold_nproc_per_chunk;
+ H5FD_mpio_chunk_opt_t chunk_opt_mode;
+ uint8_t* io_mode_info=NULL;
+ uint8_t* recv_io_mode_info=NULL;
+ uint8_t* mergebuf=NULL;
+ uint8_t* tempbuf;
+ H5SL_node_t* chunk_node;
+ H5D_chunk_info_t* chunk_info;
+ int mpi_size,mpi_rank;
+ MPI_Comm comm;
+ int ic,root;
+ int mpi_code;
+ int mem_cleanup = 0;
#ifdef H5_HAVE_INSTRUMENTED_LIBRARY
- int new_value;
- htri_t check_prop;
+ int new_value;
+ htri_t check_prop;
#endif
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_obtain_mpio_mode)
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_obtain_mpio_mode)
-
- /* Assign the rank 0 to the root */
- root = 0;
- comm = io_info->comm;
-
- /* Obtain the number of process and the current rank of the process */
- if((mpi_rank = H5F_mpi_get_rank(io_info->dset->oloc.file))<0)
- HGOTO_ERROR (H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi rank");
- if((mpi_size = H5F_mpi_get_size(io_info->dset->oloc.file))<0)
- HGOTO_ERROR (H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi size");
-
- /* Allocate memory */
- ori_total_chunks = fm->total_chunks;
- H5_ASSIGN_OVERFLOW(total_chunks,ori_total_chunks,hsize_t,int);
-
- /* Obtain the data transfer properties */
- if(NULL == (plist = H5I_object(io_info->dxpl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")
-
- percent_nproc_per_chunk=H5P_peek_unsigned(plist,H5D_XFER_MPIO_CHUNK_OPT_RATIO_NAME);
+ /* Assign the rank 0 to the root */
+ root = 0;
+ comm = io_info->comm;
+
+ /* Obtain the number of process and the current rank of the process */
+ if((mpi_rank = H5F_mpi_get_rank(io_info->dset->oloc.file)) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi rank")
+ if((mpi_size = H5F_mpi_get_size(io_info->dset->oloc.file)) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi size")
+
+ /* Setup parameters */
+ H5_ASSIGN_OVERFLOW(total_chunks, fm->total_chunks, hsize_t, int);
+ percent_nproc_per_chunk = H5P_peek_unsigned(dx_plist, H5D_XFER_MPIO_CHUNK_OPT_RATIO_NAME);
#if defined(H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS) && defined(H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS)
-
- chunk_opt_mode=(H5FD_mpio_chunk_opt_t)H5P_peek_unsigned(plist,H5D_XFER_MPIO_CHUNK_OPT_HARD_NAME);
-
- if((chunk_opt_mode == H5FD_MPIO_CHUNK_MULTI_IO) || (percent_nproc_per_chunk == 0)){
- if(H5D_istore_chunkmap(io_info, chunk_addr, fm->down_chunks) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk address");
- for(ic = 0; ic<total_chunks;ic++)
- assign_io_mode[ic] = H5D_CHUNK_IO_MODE_COL;
- goto done;
- }
-#endif
- threshold_nproc_per_chunk = mpi_size * percent_nproc_per_chunk/100;
-
- io_mode_info = (uint8_t *)H5MM_calloc(total_chunks*sizeof(MPI_BYTE));
- mergebuf = H5MM_malloc((sizeof(haddr_t)+sizeof(MPI_BYTE))*total_chunks);
- tempbuf = mergebuf + sizeof(MPI_BYTE)*total_chunks;
- if(mpi_rank == root)
- recv_io_mode_info = (uint8_t *)H5MM_malloc(total_chunks*sizeof(MPI_BYTE)*mpi_size);
-
- mem_cleanup = 1;
-
- chunk_node = H5SL_first(fm->fsel);
-
- /*Obtain the regularity and selection information for all chunks in this process. */
- while(chunk_node){
-
- chunk_info = H5SL_item(chunk_node);
+ chunk_opt_mode = (H5FD_mpio_chunk_opt_t)H5P_peek_unsigned(dx_plist, H5D_XFER_MPIO_CHUNK_OPT_HARD_NAME);
+ if((chunk_opt_mode == H5FD_MPIO_CHUNK_MULTI_IO) || (percent_nproc_per_chunk == 0)) {
+ if(H5D_chunk_addrmap(io_info, chunk_addr, fm->down_chunks) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk address");
+ for(ic = 0; ic < total_chunks; ic++)
+ assign_io_mode[ic] = H5D_CHUNK_IO_MODE_COL;
+
+ HGOTO_DONE(SUCCEED)
+ } /* end if */
+#endif
+ threshold_nproc_per_chunk = mpi_size * percent_nproc_per_chunk/100;
+
+ /* Allocate memory */
+ io_mode_info = (uint8_t *)H5MM_calloc(total_chunks);
+ mergebuf = H5MM_malloc((sizeof(haddr_t) + 1) * total_chunks);
+ tempbuf = mergebuf + total_chunks;
+ if(mpi_rank == root)
+ recv_io_mode_info = (uint8_t *)H5MM_malloc(total_chunks * mpi_size);
+
+ mem_cleanup = 1;
+
+ /* Obtain the regularity and selection information for all chunks in this process. */
+ chunk_node = H5SL_first(fm->sel_chunks);
+ while(chunk_node) {
+ chunk_info = H5SL_item(chunk_node);
#ifndef H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS
- /* regularity information: 1, selection information: 2 */
- if(H5S_SELECT_IS_REGULAR(chunk_info->fspace) == TRUE &&
- H5S_SELECT_IS_REGULAR(chunk_info->mspace) == TRUE)
+ /* regularity information: 1, selection information: 2 */
+ if(H5S_SELECT_IS_REGULAR(chunk_info->fspace) == TRUE &&
+ H5S_SELECT_IS_REGULAR(chunk_info->mspace) == TRUE)
#endif
- io_mode_info[chunk_info->index] = H5D_CHUNK_SELECT_REG; /* this chunk is selected and is "regular" without defining H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS. */
+ io_mode_info[chunk_info->index] = H5D_CHUNK_SELECT_REG; /* this chunk is selected and is "regular" without defining H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS. */
#ifndef H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS
- else
- io_mode_info[chunk_info->index] = H5D_CHUNK_SELECT_IRREG; /* this chunk is selected and is irregular*/
+ else
+ io_mode_info[chunk_info->index] = H5D_CHUNK_SELECT_IRREG; /* this chunk is selected and is irregular*/
#endif
+ chunk_node = H5SL_next(chunk_node);
+ } /* end while */
+
+ /*Gather all the information */
+ if(MPI_SUCCESS != (mpi_code = MPI_Gather(io_mode_info, total_chunks, MPI_BYTE, recv_io_mode_info, total_chunks, MPI_BYTE, root, comm)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Gather failed", mpi_code)
- chunk_node = H5SL_next(chunk_node);
- }
-
- /*Create sent MPI derived datatype */
- if(MPI_SUCCESS !=(mpi_code = MPI_Type_contiguous(total_chunks,MPI_BYTE,&stype)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Comm_rank failed", mpi_code);
- if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&stype)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code);
-
- /*Create received basic MPI derived datatype */
- bascount = 2;
- basblock[0] = total_chunks;
- basblock[1] = total_chunks;
- basdisp[0] = 0;
- basdisp[1] = (MPI_Aint)(sizeof(MPI_BYTE)*total_chunks);/* may need to check overflow */
- bastype[0] = MPI_BYTE;
-
- if(MPI_SUCCESS !=(mpi_code = MPI_Type_contiguous(sizeof(haddr_t),MPI_BYTE,&chunk_addrtype)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_contiguous failed", mpi_code);
- if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&chunk_addrtype)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code);
- bastype[1] = chunk_addrtype;
-
- if(MPI_SUCCESS !=(mpi_code = MPI_Type_struct(bascount,basblock,basdisp,bastype,&rtype)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_struct failed", mpi_code);
- if(MPI_SUCCESS !=(mpi_code = MPI_Type_commit(&rtype)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Type_commit failed", mpi_code);
-
- /* Set up a flag to clean up the MPI derived datatype later */
- mpi_type_cleanup = 1;
-
- /*Gather all the information */
- if(MPI_SUCCESS !=(mpi_code = MPI_Gather(io_mode_info,1,stype,recv_io_mode_info,1,stype,root,comm)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Gather failed", mpi_code);
-
- /* Calculate the mode for IO(collective, independent or none) at root process */
- if(mpi_rank == root) {
-
- int nproc;
- int* nproc_per_chunk;
+ /* Calculate the mode for IO(collective, independent or none) at root process */
+ if(mpi_rank == root) {
+ int nproc;
+ int* nproc_per_chunk;
#if !defined(H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS) || !defined(H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS)
- int* ind_this_chunk;
+ int* ind_this_chunk;
#endif
- /* pre-computing: calculate number of processes and
- regularity of the selection occupied in each chunk */
- nproc_per_chunk = (int*)H5MM_calloc(total_chunks*sizeof(int));
+ /* pre-computing: calculate number of processes and
+ regularity of the selection occupied in each chunk */
+ nproc_per_chunk = (int*)H5MM_calloc(total_chunks * sizeof(int));
#if !defined(H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS) || !defined(H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS)
- ind_this_chunk = (int*)H5MM_calloc(total_chunks*sizeof(int));
+ ind_this_chunk = (int*)H5MM_calloc(total_chunks * sizeof(int));
#endif
- /* calculating the chunk address */
- if(H5D_istore_chunkmap(io_info, chunk_addr, fm->down_chunks)<0){
- HDfree(nproc_per_chunk);
+ /* calculating the chunk address */
+ if(H5D_chunk_addrmap(io_info, chunk_addr, fm->down_chunks) < 0) {
+ HDfree(nproc_per_chunk);
#if !defined(H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS) || !defined(H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS)
- HDfree(ind_this_chunk);
+ HDfree(ind_this_chunk);
#endif
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk address");
- }
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get chunk address")
+ } /* end if */
+
+ /* checking for number of process per chunk and regularity of the selection*/
+ for(nproc = 0; nproc < mpi_size; nproc++) {
+ uint8_t *tmp_recv_io_mode_info = recv_io_mode_info + (nproc * total_chunks);
- /* checking for number of process per chunk and regularity of the selection*/
- for (nproc = 0;nproc <mpi_size;nproc++){
- uint8_t *tmp_recv_io_mode_info = recv_io_mode_info + nproc*total_chunks;
- /* calculate the number of process per chunk and adding irregular selection option */
- for(ic = 0; ic < total_chunks; ic++, tmp_recv_io_mode_info++){
- if(*tmp_recv_io_mode_info != 0) {
- nproc_per_chunk[ic]++;
+ /* Calculate the number of process per chunk and adding irregular selection option */
+ for(ic = 0; ic < total_chunks; ic++, tmp_recv_io_mode_info++) {
+ if(*tmp_recv_io_mode_info != 0) {
+ nproc_per_chunk[ic]++;
#ifndef H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS
- if(*tmp_recv_io_mode_info == H5D_CHUNK_SELECT_IRREG)
- ind_this_chunk[ic] = 1;
+ if(*tmp_recv_io_mode_info == H5D_CHUNK_SELECT_IRREG)
+ ind_this_chunk[ic] = 1;
#endif
- }
+ } /* end if */
#ifndef H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS
else {
- /*checking whether we have a selection in this chunk */
- ind_this_chunk[ic] = 1;
- }
+ /*checking whether we have a selection in this chunk */
+ ind_this_chunk[ic] = 1;
+ } /* end else */
#endif
- }
-
- }
+ } /* end for */
+ } /* end for */
- /* Calculating MPIO mode for each chunk (collective, independent, none) */
- for(ic = 0; ic < total_chunks; ic++){
- if(nproc_per_chunk[ic]>MAX(1,threshold_nproc_per_chunk)){
+ /* Calculating MPIO mode for each chunk (collective, independent, none) */
+ for(ic = 0; ic < total_chunks; ic++) {
+ if(nproc_per_chunk[ic] > MAX(1, threshold_nproc_per_chunk)) {
#if !defined(H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS) || !defined(H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS)
- if(!ind_this_chunk[ic]) assign_io_mode[ic] = H5D_CHUNK_IO_MODE_COL;
+ if(!ind_this_chunk[ic])
+ assign_io_mode[ic] = H5D_CHUNK_IO_MODE_COL;
#else
- assign_io_mode[ic] = H5D_CHUNK_IO_MODE_COL;
+ assign_io_mode[ic] = H5D_CHUNK_IO_MODE_COL;
#endif
- }
- }
+ } /* end if */
+ } /* end for */
- /* merge buffer io_mode info and chunk addr into one */
- HDmemcpy(mergebuf,assign_io_mode,sizeof(MPI_BYTE)*total_chunks);
- HDmemcpy(tempbuf,chunk_addr,sizeof(haddr_t)*total_chunks);
+ /* merge buffer io_mode info and chunk addr into one */
+ HDmemcpy(mergebuf, assign_io_mode, total_chunks);
+ HDmemcpy(tempbuf, chunk_addr, sizeof(haddr_t) * total_chunks);
- HDfree(nproc_per_chunk);
+ HDfree(nproc_per_chunk);
#if !defined(H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS) || !defined(H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS)
- HDfree(ind_this_chunk);
+ HDfree(ind_this_chunk);
#endif
- }
+ } /* end if */
- /* Broadcasting the MPI_IO option info. and chunk address info. */
- if(MPI_SUCCESS !=(mpi_code = MPI_Bcast(mergebuf,1,rtype,root,comm)))
- HMPI_GOTO_ERROR(FAIL, "MPI_BCast failed", mpi_code);
+ /* Broadcasting the MPI_IO option info. and chunk address info. */
+ if(MPI_SUCCESS != (mpi_code = MPI_Bcast(mergebuf, ((sizeof(haddr_t) + 1) * total_chunks), MPI_BYTE, root, comm)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_BCast failed", mpi_code)
- HDmemcpy(assign_io_mode,mergebuf,sizeof(MPI_BYTE)*total_chunks);
- HDmemcpy(chunk_addr,tempbuf,sizeof(haddr_t)*total_chunks);
+ HDmemcpy(assign_io_mode, mergebuf, total_chunks);
+ HDmemcpy(chunk_addr, tempbuf, sizeof(haddr_t) * total_chunks);
#ifdef H5_HAVE_INSTRUMENTED_LIBRARY
- check_prop = H5Pexist(io_info->dxpl_id,H5D_XFER_COLL_CHUNK_MULTI_RATIO_COLL_NAME);
+ check_prop = H5Pexist(io_info->dxpl_id, H5D_XFER_COLL_CHUNK_MULTI_RATIO_COLL_NAME);
if(check_prop > 0) {
#if !defined(H5_MPI_COMPLEX_DERIVED_DATATYPE_WORKS) || !defined(H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS)
- new_value = 0;
- if(H5Pset(io_info->dxpl_id,H5D_XFER_COLL_CHUNK_MULTI_RATIO_COLL_NAME,&new_value)<0)
- HGOTO_ERROR(H5E_PLIST, H5E_UNSUPPORTED, FAIL, "unable to set property value");
-#else
- for(ic = 0; ic < total_chunks; ic++){
- if(assign_io_mode[ic] == H5D_CHUNK_IO_MODE_COL) {
- new_value = 0;
- if(H5Pset(io_info->dxpl_id,H5D_XFER_COLL_CHUNK_MULTI_RATIO_COLL_NAME,&new_value)<0)
- HGOTO_ERROR(H5E_PLIST, H5E_UNSUPPORTED, FAIL, "unable to set property value");
- break;
- }
- }
-#endif
- }
- check_prop = H5Pexist(io_info->dxpl_id,H5D_XFER_COLL_CHUNK_MULTI_RATIO_IND_NAME);
- if(check_prop > 0) {
- int temp_count = 0;
- for(ic = 0; ic < total_chunks; ic++){
- if(assign_io_mode[ic] == H5D_CHUNK_IO_MODE_COL) {
- temp_count++;
- break;
- }
- }
- if(temp_count==0){
new_value = 0;
- if(H5Pset(io_info->dxpl_id,H5D_XFER_COLL_CHUNK_MULTI_RATIO_IND_NAME,&new_value)<0)
- HGOTO_ERROR(H5E_PLIST, H5E_UNSUPPORTED, FAIL, "unable to set property value");
- }
- }
+ if(H5Pset(io_info->dxpl_id, H5D_XFER_COLL_CHUNK_MULTI_RATIO_COLL_NAME, &new_value) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_UNSUPPORTED, FAIL, "unable to set property value")
+#else
+ for(ic = 0; ic < total_chunks; ic++) {
+ if(assign_io_mode[ic] == H5D_CHUNK_IO_MODE_COL) {
+ new_value = 0;
+ if(H5Pset(io_info->dxpl_id,H5D_XFER_COLL_CHUNK_MULTI_RATIO_COLL_NAME,&new_value) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_UNSUPPORTED, FAIL, "unable to set property value")
+ break;
+ } /* end if */
+ } /* end for */
#endif
-
-done:
-
- if(mpi_type_cleanup) {
- if (MPI_SUCCESS != (mpi_code= MPI_Type_free( &chunk_addrtype )))
- HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code);
-
- if (MPI_SUCCESS != (mpi_code= MPI_Type_free( &stype )))
- HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code);
+ } /* end if */
- if (MPI_SUCCESS != (mpi_code= MPI_Type_free( &rtype )))
- HMPI_DONE_ERROR(FAIL, "MPI_Type_free failed", mpi_code);
- }
+ check_prop = H5Pexist(io_info->dxpl_id, H5D_XFER_COLL_CHUNK_MULTI_RATIO_IND_NAME);
+ if(check_prop > 0) {
+ int temp_count = 0;
+
+ for(ic = 0; ic < total_chunks; ic++) {
+ if(assign_io_mode[ic] == H5D_CHUNK_IO_MODE_COL) {
+ temp_count++;
+ break;
+ } /* end if */
+ } /* end for */
+ if(temp_count == 0) {
+ new_value = 0;
+ if(H5Pset(io_info->dxpl_id, H5D_XFER_COLL_CHUNK_MULTI_RATIO_IND_NAME, &new_value) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_UNSUPPORTED, FAIL, "unable to set property value")
+ } /* end if */
+ } /* end if */
+#endif
- if(mem_cleanup){
- HDfree(io_mode_info);
- HDfree(mergebuf);
- if(mpi_rank == root)
- HDfree(recv_io_mode_info);
- }
+done:
+ if(mem_cleanup) {
+ HDfree(io_mode_info);
+ HDfree(mergebuf);
+ if(mpi_rank == root)
+ HDfree(recv_io_mode_info);
+ } /* end if */
FUNC_LEAVE_NOAPI(ret_value)
-}/* end H5D_obtain_mpio_mode*/
+} /* end H5D_obtain_mpio_mode() */
static int
H5D_cmp_chunk_addr(const void *chunk_addr_info1, const void *chunk_addr_info2)
@@ -2034,12 +2033,11 @@ H5D_cmp_chunk_addr(const void *chunk_addr_info1, const void *chunk_addr_info2)
haddr_t addr1, addr2;
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_cmp_chunk_addr)
-
+
addr1 = ((const H5D_chunk_addr_info_t *)chunk_addr_info1)->chunk_addr;
addr2 = ((const H5D_chunk_addr_info_t *)chunk_addr_info2)->chunk_addr;
FUNC_LEAVE_NOAPI(H5F_addr_cmp(addr1, addr2))
-
}
#endif /* H5_HAVE_PARALLEL */
diff --git a/src/H5Doh.c b/src/H5Doh.c
index 01447a3..88ab971 100644
--- a/src/H5Doh.c
+++ b/src/H5Doh.c
@@ -48,7 +48,8 @@
static void *H5O_dset_get_copy_file_udata(void);
static void H5O_dset_free_copy_file_udata(void *);
static htri_t H5O_dset_isa(H5O_t *loc);
-static hid_t H5O_dset_open(const H5G_loc_t *obj_loc, hid_t dxpl_id);
+static hid_t H5O_dset_open(const H5G_loc_t *obj_loc, hid_t lapl_id,
+ hid_t dxpl_id, hbool_t app_ref);
static void *H5O_dset_create(H5F_t *f, void *_crt_info, H5G_loc_t *obj_loc,
hid_t dxpl_id);
static H5O_loc_t *H5O_dset_get_oloc(hid_t obj_id);
@@ -151,11 +152,11 @@ H5O_dset_free_copy_file_udata(void *_udata)
H5T_close(udata->src_dtype);
/* Release copy of dataset's filter pipeline, if it was set */
- if (udata->src_pline)
+ if(udata->src_pline)
H5O_msg_free(H5O_PLINE_ID, udata->src_pline);
/* Release space for 'copy file' user data */
- H5FL_FREE(H5D_copy_file_ud_t, udata);
+ (void)H5FL_FREE(H5D_copy_file_ud_t, udata);
FUNC_LEAVE_NOAPI_VOID
} /* end H5O_dset_free_copy_file_udata() */
@@ -219,21 +220,35 @@ done:
*-------------------------------------------------------------------------
*/
static hid_t
-H5O_dset_open(const H5G_loc_t *obj_loc, hid_t dxpl_id)
+H5O_dset_open(const H5G_loc_t *obj_loc, hid_t lapl_id, hid_t dxpl_id, hbool_t app_ref)
{
H5D_t *dset = NULL; /* Dataset opened */
+ htri_t isdapl; /* lapl_id is a dapl */
+ hid_t dapl_id; /* dapl to use to open this dataset */
hid_t ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_dset_open)
HDassert(obj_loc);
+ /* If the lapl passed in is a dapl, use it. Otherwise, use the default dapl */
+ if(lapl_id == H5P_DEFAULT)
+ isdapl = FALSE;
+ else
+ if((isdapl = H5P_isa_class(lapl_id, H5P_DATASET_ACCESS)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTCOMPARE, FAIL, "unable to compare property list classes")
+
+ if(isdapl)
+ dapl_id = lapl_id;
+ else
+ dapl_id = H5P_DATASET_ACCESS_DEFAULT;
+
/* Open the dataset */
- if(NULL == (dset = H5D_open(obj_loc, dxpl_id)))
+ if(NULL == (dset = H5D_open(obj_loc, dapl_id, dxpl_id)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "unable to open dataset")
/* Register an ID for the dataset */
- if((ret_value = H5I_register(H5I_DATASET, dset)) < 0)
+ if((ret_value = H5I_register(H5I_DATASET, dset, app_ref)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataset")
done:
@@ -273,7 +288,8 @@ H5O_dset_create(H5F_t *f, void *_crt_info, H5G_loc_t *obj_loc, hid_t dxpl_id)
HDassert(obj_loc);
/* Create the the dqtaset */
- if(NULL == (dset = H5D_create(f, crt_info->type_id, crt_info->space, crt_info->dcpl_id, dxpl_id)))
+ if(NULL == (dset = H5D_create(f, crt_info->type_id, crt_info->space,
+ crt_info->dcpl_id, crt_info->dapl_id, dxpl_id)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to create dataset")
/* Set up the new dataset's location */
@@ -316,7 +332,7 @@ H5O_dset_get_oloc(hid_t obj_id)
FUNC_ENTER_NOAPI_NOINIT(H5O_dset_get_oloc)
/* Get the dataset */
- if(NULL == (dset = H5I_object(obj_id)))
+ if(NULL == (dset = (H5D_t *)H5I_object(obj_id)))
HGOTO_ERROR(H5E_OHDR, H5E_BADATOM, NULL, "couldn't get object from ID")
/* Get the dataset's object header location */
@@ -361,7 +377,7 @@ H5O_dset_bh_info(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5_ih_info_t *bh_info)
/* Check for chunked dataset storage */
if((layout.type == H5D_CHUNKED) && H5F_addr_defined(layout.u.chunk.addr))
- if(H5D_istore_bh_info(f, dxpl_id, &layout, &(bh_info->index_size)) < 0)
+ if(H5D_chunk_bh_info(f, dxpl_id, &layout, &(bh_info->index_size)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't determine chunked dataset btree info")
done:
diff --git a/src/H5Dpkg.h b/src/H5Dpkg.h
index 34a32ee..b0d7d6a 100644
--- a/src/H5Dpkg.h
+++ b/src/H5Dpkg.h
@@ -49,89 +49,324 @@
#define H5D_MINHDR_SIZE 256
/* [Simple] Macro to construct a H5D_io_info_t from it's components */
-#define H5D_BUILD_IO_INFO(io_info,ds,dxpl_c,dxpl_i,str) \
- (io_info)->dset=ds; \
- (io_info)->dxpl_cache=dxpl_c; \
- (io_info)->dxpl_id=dxpl_i; \
- (io_info)->store=str
+#define H5D_BUILD_IO_INFO_WRT(io_info, ds, dxpl_c, dxpl_i, str, buf) \
+ (io_info)->dset = ds; \
+ (io_info)->dxpl_cache = dxpl_c; \
+ (io_info)->dxpl_id = dxpl_i; \
+ (io_info)->store = str; \
+ (io_info)->op_type = H5D_IO_OP_WRITE; \
+ (io_info)->u.wbuf = buf
+#define H5D_BUILD_IO_INFO_RD(io_info, ds, dxpl_c, dxpl_i, str, buf) \
+ (io_info)->dset = ds; \
+ (io_info)->dxpl_cache = dxpl_c; \
+ (io_info)->dxpl_id = dxpl_i; \
+ (io_info)->store = str; \
+ (io_info)->op_type = H5D_IO_OP_READ; \
+ (io_info)->u.rbuf = buf
+
+#define H5D_CHUNK_HASH(D, ADDR) H5F_addr_hash(ADDR, (D)->cache.chunk.nslots)
/****************************/
/* Package Private Typedefs */
/****************************/
-/*
- * If there is no data type conversion then it might be possible to
- * transfer data points between application memory and the file in one
- * step without going through the data type conversion buffer.
- */
-
-/* Read from file to application w/o intermediate scratch buffer */
+/* Typedef for datatype information for raw data I/O operation */
+typedef struct H5D_type_info_t {
+ /* Initial values */
+ const H5T_t *mem_type; /* Pointer to memory datatype */
+ const H5T_t *dset_type; /* Pointer to dataset datatype */
+ H5T_path_t *tpath; /* Datatype conversion path */
+ hid_t src_type_id; /* Source datatype ID */
+ hid_t dst_type_id; /* Destination datatype ID */
+
+ /* Computed/derived values */
+ size_t src_type_size; /* Size of source type */
+ size_t dst_type_size; /* Size of destination type*/
+ size_t max_type_size; /* Size of largest source/destination type */
+ hbool_t is_conv_noop; /* Whether the type conversion is a NOOP */
+ hbool_t is_xform_noop; /* Whether the data transform is a NOOP */
+ const H5T_subset_info_t *cmpd_subset; /* Info related to the compound subset conversion functions */
+ H5T_bkg_t need_bkg; /* Type of background buf needed */
+ size_t request_nelmts; /* Requested strip mine */
+ uint8_t *tconv_buf; /* Datatype conv buffer */
+ hbool_t tconv_buf_allocated; /* Whether the type conversion buffer was allocated */
+ uint8_t *bkg_buf; /* Background buffer */
+ hbool_t bkg_buf_allocated; /* Whether the background buffer was allocated */
+} H5D_type_info_t;
+
+/* Forward declaration of structs used below */
struct H5D_io_info_t;
-typedef herr_t (*H5D_io_read_func_t)(struct H5D_io_info_t *io_info,
- size_t nelmts, size_t elmt_size,
- const H5S_t *file_space, const H5S_t *mem_space, haddr_t addr,
- void *chunk, void *buf/*out*/);
-
-
-/* Write directly from app buffer to file */
-typedef herr_t (*H5D_io_write_func_t)(struct H5D_io_info_t *io_info,
- size_t nelmts, size_t elmt_size,
- const H5S_t *file_space, const H5S_t *mem_space, haddr_t addr,
- void *chunk, const void *buf);
+struct H5D_chunk_map_t;
/* Function pointers for I/O on particular types of dataset layouts */
-typedef ssize_t (*H5D_io_readvv_func_t)(const struct H5D_io_info_t *io_info,
+typedef herr_t (*H5D_layout_new_func_t)(H5F_t *f, hid_t dapl_id, hid_t dxpl_id,
+ H5D_t *dset, const H5P_genplist_t *dc_plist);
+typedef herr_t (*H5D_layout_io_init_func_t)(const struct H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
+ struct H5D_chunk_map_t *cm);
+typedef herr_t (*H5D_layout_read_func_t)(struct H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info, hsize_t nelmts, const H5S_t *file_space,
+ const H5S_t *mem_space, struct H5D_chunk_map_t *fm);
+typedef herr_t (*H5D_layout_write_func_t)(struct H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info, hsize_t nelmts, const H5S_t *file_space,
+ const H5S_t *mem_space, struct H5D_chunk_map_t *fm);
+typedef ssize_t (*H5D_layout_readvv_func_t)(const struct H5D_io_info_t *io_info,
size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[],
- haddr_t chunk_addr, void *chunk, void *buf);
-typedef ssize_t (*H5D_io_writevv_func_t)(const struct H5D_io_info_t *io_info,
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[]);
+typedef ssize_t (*H5D_layout_writevv_func_t)(const struct H5D_io_info_t *io_info,
size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[],
- haddr_t chunk_addr, void *chunk, const void *buf);
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[]);
+typedef herr_t (*H5D_layout_io_term_func_t)(const struct H5D_chunk_map_t *cm);
+
+/* Typedef for grouping layout I/O routines */
+typedef struct H5D_layout_ops_t {
+ H5D_layout_new_func_t new; /* Layout constructor for new datasets */
+ H5D_layout_io_init_func_t io_init; /* I/O initialization routine */
+ H5D_layout_read_func_t ser_read; /* High-level I/O routine for reading data in serial */
+ H5D_layout_write_func_t ser_write; /* High-level I/O routine for writing data in serial */
+#ifdef H5_HAVE_PARALLEL
+ H5D_layout_read_func_t par_read; /* High-level I/O routine for reading data in parallel */
+ H5D_layout_write_func_t par_write; /* High-level I/O routine for writing data in parallel */
+#endif /* H5_HAVE_PARALLEL */
+ H5D_layout_readvv_func_t readvv; /* Low-level I/O routine for reading data */
+ H5D_layout_writevv_func_t writevv; /* Low-level I/O routine for writing data */
+ H5D_layout_io_term_func_t io_term; /* I/O shutdown routine */
+} H5D_layout_ops_t;
+
+/* Function pointers for either multiple or single block I/O access */
+typedef herr_t (*H5D_io_single_read_func_t)(const struct H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space);
+typedef herr_t (*H5D_io_single_write_func_t)(const struct H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space);
/* Typedef for raw data I/O framework info */
typedef struct H5D_io_ops_t {
- H5D_io_read_func_t read; /* Direct I/O routine for reading */
- H5D_io_write_func_t write; /* Direct I/O routine for writing */
- H5D_io_readvv_func_t readvv; /* I/O routine for reading data */
- H5D_io_writevv_func_t writevv; /* I/O routine for writing data */
+ H5D_layout_read_func_t multi_read; /* High-level I/O routine for reading data */
+ H5D_layout_write_func_t multi_write; /* High-level I/O routine for writing data */
+ H5D_io_single_read_func_t single_read; /* I/O routine for reading single block */
+ H5D_io_single_write_func_t single_write; /* I/O routine for writing single block */
} H5D_io_ops_t;
+/* Typedefs for dataset storage information */
+typedef struct {
+ haddr_t dset_addr; /* Address of dataset in file */
+ hsize_t dset_size; /* Total size of dataset in file */
+} H5D_contig_storage_t;
+
+typedef struct {
+ hsize_t index; /* "Index" of chunk in dataset (must be first for TBBT routines) */
+ hsize_t *offset; /* Chunk's coordinates in elements */
+} H5D_chunk_storage_t;
+
+typedef struct {
+ void *buf; /* Buffer for compact dataset */
+ hbool_t *dirty; /* Pointer to dirty flag to mark */
+} H5D_compact_storage_t;
+
+typedef union H5D_storage_t {
+ H5D_contig_storage_t contig; /* Contiguous information for dataset */
+ H5D_chunk_storage_t chunk; /* Chunk information for dataset */
+ H5D_compact_storage_t compact; /* Compact information for dataset */
+ H5O_efl_t efl; /* External file list information for dataset */
+} H5D_storage_t;
+
/* Typedef for raw data I/O operation info */
typedef struct H5D_io_info_t {
H5D_t *dset; /* Pointer to dataset being operated on */
#ifndef H5_HAVE_PARALLEL
const
#endif /* H5_HAVE_PARALLEL */
- H5D_dxpl_cache_t *dxpl_cache; /* Pointer to cache DXPL info */
+ H5D_dxpl_cache_t *dxpl_cache; /* Pointer to cached DXPL info */
hid_t dxpl_id; /* Original DXPL ID */
#ifdef H5_HAVE_PARALLEL
MPI_Comm comm; /* MPI communicator for file */
- hbool_t xfer_mode_changed; /* Whether the transfer mode was changed */
- hbool_t xfer_opt_mode_changed;
+ hbool_t using_mpi_vfd; /* Whether the file is using an MPI-based VFD */
+ struct {
+ H5FD_mpio_xfer_t xfer_mode; /* Parallel transfer for this request (H5D_XFER_IO_XFER_MODE_NAME) */
+ H5FD_mpio_collective_opt_t coll_opt_mode; /* Parallel transfer with independent IO or collective IO with this mode */
+ H5D_io_ops_t io_ops; /* I/O operation function pointers */
+ } orig;
#endif /* H5_HAVE_PARALLEL */
- const H5D_storage_t *store; /* Dataset storage info */
- H5D_io_ops_t ops; /* I/O operation function pointers */
-#ifdef H5S_DEBUG
- H5S_iostats_t *stats; /* I/O statistics */
-#endif /* H5S_DEBUG */
+ H5D_storage_t *store; /* Dataset storage info */
+ H5D_layout_ops_t layout_ops; /* Dataset layout I/O operation function pointers */
+ H5D_io_ops_t io_ops; /* I/O operation function pointers */
+ enum {
+ H5D_IO_OP_READ, /* Read operation */
+ H5D_IO_OP_WRITE /* Write operation */
+ } op_type;
+ union {
+ void *rbuf; /* Pointer to buffer for read */
+ const void *wbuf; /* Pointer to buffer to write */
+ } u;
} H5D_io_info_t;
+
+/******************/
+/* Chunk typedefs */
+/******************/
+
+/* Typedef for chunked dataset index operation info */
+typedef struct H5D_chk_idx_info_t {
+ H5F_t *f; /* File pointer for operation */
+ hid_t dxpl_id; /* DXPL ID for operation */
+ H5O_layout_t *layout; /* Layout info for chunks */
+} H5D_chk_idx_info_t;
+
+/*
+ * "Generic" chunk record. Each chunk is keyed by the minimum logical
+ * N-dimensional coordinates and the datatype size of the chunk.
+ * The fastest-varying dimension is assumed to reference individual bytes of
+ * the array, so a 100-element 1-D array of 4-byte integers would really be a
+ * 2-D array with the slow varying dimension of size 100 and the fast varying
+ * dimension of size 4 (the storage dimensionality has very little to do with
+ * the real dimensionality).
+ *
+ * The chunk's file address, filter mask and size on disk are not key values.
+ */
+typedef struct H5D_chunk_rec_t {
+ uint32_t nbytes; /* Size of stored data */
+ hsize_t offset[H5O_LAYOUT_NDIMS]; /* Logical offset to start*/
+ unsigned filter_mask; /* Excluded filters */
+ haddr_t chunk_addr; /* Address of chunk in file */
+} H5D_chunk_rec_t;
+
+/*
+ * Common data exchange structure for indexed storage nodes. This structure is
+ * passed through the indexing layer to the methods for the objects
+ * to which the index points.
+ */
+typedef struct H5D_chunk_common_ud_t {
+ /* downward */
+ const H5O_layout_t *mesg; /*layout message */
+ const hsize_t *offset; /*logical offset of chunk*/
+} H5D_chunk_common_ud_t;
+
+/* B-tree callback info for various operations */
+typedef struct H5D_chunk_ud_t {
+ H5D_chunk_common_ud_t common; /* Common info for B-tree user data (must be first) */
+
+ /* Upward */
+ uint32_t nbytes; /*size of stored data */
+ unsigned filter_mask; /*excluded filters */
+ haddr_t addr; /*file address of chunk */
+} H5D_chunk_ud_t;
+
+/* Typedef for "generic" chunk callbacks */
+typedef int (*H5D_chunk_cb_func_t)(const H5D_chunk_rec_t *chunk_rec,
+ void *udata);
+
+/* Typedefs for chunk operations */
+typedef herr_t (*H5D_chunk_init_func_t)(const H5D_chk_idx_info_t *idx_info);
+typedef herr_t (*H5D_chunk_create_func_t)(const H5D_chk_idx_info_t *idx_info);
+typedef herr_t (*H5D_chunk_insert_func_t)(const H5D_chk_idx_info_t *idx_info,
+ H5D_chunk_ud_t *udata);
+typedef herr_t (*H5D_chunk_get_addr_func_t)(const H5D_chk_idx_info_t *idx_info,
+ H5D_chunk_ud_t *udata);
+typedef int (*H5D_chunk_iterate_func_t)(const H5D_chk_idx_info_t *idx_info,
+ H5D_chunk_cb_func_t chunk_cb, void *chunk_udata);
+typedef herr_t (*H5D_chunk_remove_func_t)(const H5D_chk_idx_info_t *idx_info,
+ H5D_chunk_common_ud_t *udata);
+typedef herr_t (*H5D_chunk_delete_func_t)(const H5D_chk_idx_info_t *idx_info);
+typedef herr_t (*H5D_chunk_copy_setup_func_t)(const H5D_chk_idx_info_t *idx_info_src,
+ const H5D_chk_idx_info_t *idx_info_dst);
+typedef herr_t (*H5D_chunk_copy_shutdown_func_t)(H5O_layout_t *layout_src,
+ H5O_layout_t *layout_dst);
+typedef herr_t (*H5D_chunk_size_func_t)(const H5D_chk_idx_info_t *idx_info,
+ hsize_t *idx_size);
+typedef herr_t (*H5D_chunk_dest_func_t)(const H5D_chk_idx_info_t *idx_info);
+
+/* Typedef for grouping chunk I/O routines */
+typedef struct H5D_chunk_ops_t {
+ H5D_chunk_init_func_t init; /* Routine to initialize indexing information in memory */
+ H5D_chunk_create_func_t create; /* Routine to create chunk index */
+ H5D_chunk_insert_func_t insert; /* Routine to insert a chunk into an index */
+ H5D_chunk_get_addr_func_t get_addr; /* Routine to retrieve address of chunk in file */
+ H5D_chunk_iterate_func_t iterate; /* Routine to iterate over chunks */
+ H5D_chunk_remove_func_t remove; /* Routine to remove a chunk from an index */
+ H5D_chunk_delete_func_t delete; /* Routine to delete index & all chunks from file*/
+ H5D_chunk_copy_setup_func_t copy_setup; /* Routine to perform any necessary setup for copying chunks */
+ H5D_chunk_copy_shutdown_func_t copy_shutdown; /* Routine to perform any necessary shutdown for copying chunks */
+ H5D_chunk_size_func_t size; /* Routine to get size of indexing information */
+ H5D_chunk_dest_func_t dest; /* Routine to destroy indexing information in memory */
+} H5D_chunk_ops_t;
+
+/* Structure holding information about a chunk's selection for mapping */
+typedef struct H5D_chunk_info_t {
+ hsize_t index; /* "Index" of chunk in dataset */
+ uint32_t chunk_points; /* Number of elements selected in chunk */
+ hsize_t coords[H5O_LAYOUT_NDIMS]; /* Coordinates of chunk in file dataset's dataspace */
+ H5S_t *fspace; /* Dataspace describing chunk & selection in it */
+ unsigned fspace_shared; /* Indicate that the file space for a chunk is shared and shouldn't be freed */
+ H5S_t *mspace; /* Dataspace describing selection in memory corresponding to this chunk */
+ unsigned mspace_shared; /* Indicate that the memory space for a chunk is shared and shouldn't be freed */
+} H5D_chunk_info_t;
+
+/* Main structure holding the mapping between file chunks and memory */
+typedef struct H5D_chunk_map_t {
+ H5O_layout_t *layout; /* Dataset layout information*/
+ hsize_t nelmts; /* Number of elements selected in file & memory dataspaces */
+
+ const H5S_t *file_space; /* Pointer to the file dataspace */
+ unsigned f_ndims; /* Number of dimensions for file dataspace */
+ hsize_t f_dims[H5O_LAYOUT_NDIMS]; /* File dataspace dimensions */
+
+ const H5S_t *mem_space; /* Pointer to the memory dataspace */
+ H5S_t *mchunk_tmpl; /* Dataspace template for new memory chunks */
+ H5S_sel_iter_t mem_iter; /* Iterator for elements in memory selection */
+ unsigned m_ndims; /* Number of dimensions for memory dataspace */
+ H5S_sel_type msel_type; /* Selection type in memory */
+
+ H5SL_t *sel_chunks; /* Skip list containing information for each chunk selected */
+
+ H5S_t *single_space; /* Dataspace for single chunk */
+ H5D_chunk_info_t *single_chunk_info; /* Pointer to single chunk's info */
+ hbool_t use_single; /* Whether I/O is on a single element */
+
+ hsize_t last_index; /* Index of last chunk operated on */
+ H5D_chunk_info_t *last_chunk_info; /* Pointer to last chunk's info */
+
+ hsize_t chunks[H5O_LAYOUT_NDIMS]; /* Number of chunks in each dimension */
+ hsize_t chunk_dim[H5O_LAYOUT_NDIMS]; /* Size of chunk in each dimension */
+ hsize_t down_chunks[H5O_LAYOUT_NDIMS]; /* "down" size of number of chunks in each dimension */
+
+#ifdef H5_HAVE_PARALLEL
+ hsize_t total_chunks; /* Number of chunks covered by dataspace */
+ H5D_chunk_info_t **select_chunk; /* Store the information about whether this chunk is selected or not */
+#endif /* H5_HAVE_PARALLEL */
+} H5D_chunk_map_t;
+
+/* Cached information about a particular chunk */
+typedef struct H5D_chunk_cached_t{
+ hbool_t valid; /*whether cache info is valid*/
+ hsize_t offset[H5O_LAYOUT_NDIMS]; /*logical offset to start*/
+ uint32_t nbytes; /*size of stored data */
+ unsigned filter_mask; /*excluded filters */
+ haddr_t addr; /*file address of chunk */
+} H5D_chunk_cached_t;
+
/* The raw data chunk cache */
typedef struct H5D_rdcc_t {
-#ifdef H5D_ISTORE_DEBUG
- unsigned ninits; /* Number of chunk creations */
- unsigned nhits; /* Number of cache hits */
- unsigned nmisses;/* Number of cache misses */
- unsigned nflushes;/* Number of cache flushes */
-#endif /* H5D_ISTORE_DEBUG */
+ struct {
+ unsigned ninits; /* Number of chunk creations */
+ unsigned nhits; /* Number of cache hits */
+ unsigned nmisses;/* Number of cache misses */
+ unsigned nflushes;/* Number of cache flushes */
+ } stats;
size_t nbytes; /* Current cached raw data in bytes */
size_t nslots; /* Number of chunk slots allocated */
+ double w0; /* Chunk preemption policy */
struct H5D_rdcc_ent_t *head; /* Head of doubly linked list */
struct H5D_rdcc_ent_t *tail; /* Tail of doubly linked list */
int nused; /* Number of chunk slots in use */
+ H5D_chunk_cached_t last; /* Cached copy of last chunk information */
struct H5D_rdcc_ent_t **slot; /* Chunk slots, each points to a chunk*/
+ H5SL_t *sel_chunks; /* Skip list containing information for each chunk selected */
+ H5S_t *single_space; /* Dataspace for single element I/O on chunks */
+ H5D_chunk_info_t *single_chunk_info; /* Pointer to single chunk's info */
} H5D_rdcc_t;
/* The raw data contiguous data cache */
@@ -150,15 +385,15 @@ typedef struct H5D_rdcdc_t {
* there will be two IDs and two H5D_t structs, both sharing one H5D_shared_t.
*/
typedef struct H5D_shared_t {
- size_t fo_count; /* reference count */
+ size_t fo_count; /* Reference count */
hid_t type_id; /* ID for dataset's datatype */
- H5T_t *type; /* datatype of this dataset */
- H5S_t *space; /* dataspace of this dataset */
+ H5T_t *type; /* Datatype for this dataset */
+ H5S_t *space; /* Dataspace of this dataset */
hbool_t space_dirty; /* Whether the dataspace info needs to be flushed to the file */
- hid_t dcpl_id; /* dataset creation property id */
+ hbool_t layout_dirty; /* Whether the layout info needs to be flushed to the file */
+ hid_t dcpl_id; /* Dataset creation property id */
H5D_dcpl_cache_t dcpl_cache; /* Cached DCPL values */
- H5D_io_ops_t io_ops; /* I/O operations */
- H5O_layout_t layout; /* data layout */
+ H5O_layout_t layout; /* Data layout */
hbool_t checked_filters;/* TRUE if dataset passes can_apply check */
/* Buffered/cached information for types of raw data storage*/
@@ -187,47 +422,16 @@ typedef enum {
} H5D_time_alloc_t;
-/* Structure holding information about a chunk's selection for mapping */
-typedef struct H5D_chunk_info_t {
- hsize_t index; /* "Index" of chunk in dataset */
- size_t chunk_points; /* Number of elements selected in chunk */
- H5S_t *fspace; /* Dataspace describing chunk & selection in it */
- hsize_t coords[H5O_LAYOUT_NDIMS]; /* Coordinates of chunk in file dataset's dataspace */
- H5S_t *mspace; /* Dataspace describing selection in memory corresponding to this chunk */
- unsigned mspace_shared; /* Indicate that the memory space for a chunk is shared and shouldn't be freed */
-} H5D_chunk_info_t;
-
-/* Main structure holding the mapping between file chunks and memory */
-typedef struct fm_map {
- H5SL_t *fsel; /* Skip list containing file dataspaces for all chunks */
- hsize_t last_index; /* Index of last chunk operated on */
- H5D_chunk_info_t *last_chunk_info; /* Pointer to last chunk's info */
- const H5S_t *file_space; /* Pointer to the file dataspace */
- const H5S_t *mem_space; /* Pointer to the memory dataspace */
- unsigned mem_space_copy; /* Flag to indicate that the memory dataspace must be copied */
- hsize_t f_dims[H5O_LAYOUT_NDIMS]; /* File dataspace dimensions */
- H5S_t *mchunk_tmpl; /* Dataspace template for new memory chunks */
- unsigned f_ndims; /* Number of dimensions for file dataspace */
- H5S_sel_iter_t mem_iter; /* Iterator for elements in memory selection */
- unsigned m_ndims; /* Number of dimensions for memory dataspace */
- hsize_t chunks[H5O_LAYOUT_NDIMS]; /* Number of chunks in each dimension */
- hsize_t chunk_dim[H5O_LAYOUT_NDIMS]; /* Size of chunk in each dimension */
- hsize_t down_chunks[H5O_LAYOUT_NDIMS]; /* "down" size of number of chunks in each dimension */
- H5O_layout_t *layout; /* Dataset layout information*/
- H5S_sel_type msel_type; /* Selection type in memory */
- hsize_t total_chunks; /* Number of total chunks */
- hbool_t *select_chunk; /* store the information about whether this chunk is selected or not */
-} fm_map;
-
/* Typedef for dataset creation operation */
typedef struct {
hid_t type_id; /* Datatype for dataset */
const H5S_t *space; /* Dataspace for dataset */
hid_t dcpl_id; /* Dataset creation property list */
+ hid_t dapl_id; /* Dataset access property list */
} H5D_obj_create_t;
/* Typedef for filling a buffer with a fill value */
-typedef struct {
+typedef struct H5D_fill_buf_info_t {
hbool_t alloc_vl_during_refill; /* Whether to allocate VL-datatype fill buffer during refill */
H5MM_allocate_t fill_alloc_func; /* Routine to call for allocating fill buffer */
void *fill_alloc_info; /* Extra info for allocation routine */
@@ -251,47 +455,6 @@ typedef struct {
hbool_t has_vlen_fill_type; /* Whether the datatype for the fill value has a variable-length component */
} H5D_fill_buf_info_t;
-/*************************/
-/* For chunk lock */
-/*************************/
-/*
- * B-tree key. A key contains the minimum logical N-dimensional address and
- * the logical size of the chunk to which this key refers. The
- * fastest-varying dimension is assumed to reference individual bytes of the
- * array, so a 100-element 1-d array of 4-byte integers would really be a 2-d
- * array with the slow varying dimension of size 100 and the fast varying
- * dimension of size 4 (the storage dimensionality has very little to do with
- * the real dimensionality).
- *
- * Only the first few values of the OFFSET and SIZE fields are actually
- * stored on disk, depending on the dimensionality.
- *
- * The chunk's file address is part of the B-tree and not part of the key.
- */
-typedef struct H5D_istore_key_t {
- size_t nbytes; /*size of stored data */
- hsize_t offset[H5O_LAYOUT_NDIMS]; /*logical offset to start*/
- unsigned filter_mask; /*excluded filters */
-} H5D_istore_key_t;
-
-
-/*
- * Common data exchange structure for indexed storage nodes. This structure is
- * passed through the B-link tree layer to the methods for the objects
- * to which the B-link tree points.
- */
-typedef struct H5D_istore_bt_ud_common_t {
- /* downward */
- H5D_istore_key_t key; /*key values */
- const H5O_layout_t *mesg; /*layout message */
-} H5D_istore_bt_ud_common_t;
-
-/* B-tree callback info for various operations */
-typedef struct H5D_istore_ud1_t {
- H5D_istore_bt_ud_common_t common; /* Common info for B-tree user data (must be first) */
- haddr_t addr; /*file address of chunk */
-} H5D_istore_ud1_t;
-
/* Internal data structure for computing variable-length dataset's total size */
typedef struct {
hid_t dataset_id; /* ID of the dataset we are working on */
@@ -303,26 +466,52 @@ typedef struct {
hsize_t size; /* Accumulated number of bytes for the selection */
} H5D_vlen_bufsize_t;
+/* Raw data chunks are cached. Each entry in the cache is: */
+typedef struct H5D_rdcc_ent_t {
+ hbool_t locked; /*entry is locked in cache */
+ hbool_t dirty; /*needs to be written to disk? */
+ hsize_t offset[H5O_LAYOUT_NDIMS]; /*chunk name */
+ uint32_t rd_count; /*bytes remaining to be read */
+ uint32_t wr_count; /*bytes remaining to be written */
+ haddr_t chunk_addr; /*address of chunk in file */
+ uint32_t chunk_size; /*size of a chunk */
+ size_t alloc_size; /*amount allocated for the chunk */
+ uint8_t *chunk; /*the unfiltered chunk data */
+ unsigned idx; /*index in hash table */
+ struct H5D_rdcc_ent_t *next;/*next item in doubly-linked list */
+ struct H5D_rdcc_ent_t *prev;/*previous item in doubly-linked list */
+} H5D_rdcc_ent_t;
+typedef H5D_rdcc_ent_t *H5D_rdcc_ent_ptr_t; /* For free lists */
+
/*****************************/
/* Package Private Variables */
/*****************************/
extern H5D_dxpl_cache_t H5D_def_dxpl_cache;
+/* Storage layout class I/O operations */
+H5_DLLVAR const H5D_layout_ops_t H5D_LOPS_CONTIG[1];
+H5_DLLVAR const H5D_layout_ops_t H5D_LOPS_EFL[1];
+H5_DLLVAR const H5D_layout_ops_t H5D_LOPS_COMPACT[1];
+H5_DLLVAR const H5D_layout_ops_t H5D_LOPS_CHUNK[1];
+
+/* Chunked layout operations */
+H5_DLLVAR const H5D_chunk_ops_t H5D_COPS_BTREE[1];
+
/******************************/
/* Package Private Prototypes */
/******************************/
H5_DLL H5D_t *H5D_create(H5F_t *file, hid_t type_id, const H5S_t *space,
- hid_t dcpl_id, hid_t dxpl_id);
+ hid_t dcpl_id, hid_t dapl_id, hid_t dxpl_id);
H5_DLL H5D_t *H5D_create_named(const H5G_loc_t *loc, const char *name,
hid_t type_id, const H5S_t *space, hid_t lcpl_id, hid_t dcpl_id,
hid_t dapl_id, hid_t dxpl_id);
H5_DLL herr_t H5D_get_space_status(H5D_t *dset, H5D_space_status_t *allocation,
hid_t dxpl_id);
-H5_DLL herr_t H5D_alloc_storage(H5F_t *f, hid_t dxpl_id, H5D_t *dset, H5D_time_alloc_t time_alloc,
- hbool_t update_time, hbool_t full_overwrite);
+H5_DLL herr_t H5D_alloc_storage(H5D_t *dset, hid_t dxpl_id, H5D_time_alloc_t time_alloc,
+ hbool_t full_overwrite);
H5_DLL hsize_t H5D_get_storage_size(H5D_t *dset, hid_t dxpl_id);
H5_DLL haddr_t H5D_get_offset(const H5D_t *dset);
H5_DLL herr_t H5D_iterate(void *buf, hid_t type_id, const H5S_t *space,
@@ -332,109 +521,83 @@ H5_DLL herr_t H5D_vlen_get_buf_size(void *elem, hid_t type_id, unsigned ndim,
const hsize_t *point, void *op_data);
H5_DLL herr_t H5D_check_filters(H5D_t *dataset);
H5_DLL herr_t H5D_set_extent(H5D_t *dataset, const hsize_t *size, hid_t dxpl_id);
-
-/* Functions that perform serial I/O operations */
-H5_DLL herr_t H5D_select_fscat(H5D_io_info_t *io_info,
- const H5S_t *file_space, H5S_sel_iter_t *file_iter, size_t nelmts,
- haddr_t chunk_addr, void *chunk, const void *_buf);
-H5_DLL size_t H5D_select_fgath(H5D_io_info_t *io_info,
- const H5S_t *file_space, H5S_sel_iter_t *file_iter, size_t nelmts,
- haddr_t chunk_addr, void *chunk, void *buf);
-H5_DLL herr_t H5D_select_mscat(const void *_tscat_buf,
- const H5S_t *space, H5S_sel_iter_t *iter, size_t nelmts,
- const H5D_dxpl_cache_t *dxpl_cache, void *_buf/*out*/);
-H5_DLL size_t H5D_select_mgath(const void *_buf,
+H5_DLL herr_t H5D_get_dxpl_cache(hid_t dxpl_id, H5D_dxpl_cache_t **cache);
+
+/* Functions that perform direct serial I/O operations */
+H5_DLL herr_t H5D_select_read(const H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space);
+H5_DLL herr_t H5D_select_write(const H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space);
+
+/* Functions that perform scatter-gather serial I/O operations */
+H5_DLL herr_t H5D_scatter_mem(const void *_tscat_buf,
const H5S_t *space, H5S_sel_iter_t *iter, size_t nelmts,
- const H5D_dxpl_cache_t *dxpl_cache, void *_tgath_buf/*out*/);
-H5_DLL herr_t H5D_select_read(H5D_io_info_t *io_info,
- size_t nelmts, size_t elmt_size,
- const H5S_t *file_space, const H5S_t *mem_space,
- haddr_t addr, void *chunk/*in*/, void *buf/*out*/);
-H5_DLL herr_t H5D_select_write(H5D_io_info_t *io_info,
- size_t nelmts, size_t elmt_size,
- const H5S_t *file_space, const H5S_t *mem_space,
- haddr_t addr, void *chunk/*in*/, const void *buf/*out*/);
+ const H5D_dxpl_cache_t *dxpl_cache, void *_buf);
+H5_DLL herr_t H5D_scatgath_read(const H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space);
+H5_DLL herr_t H5D_scatgath_write(const H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space);
/* Functions that operate on contiguous storage */
-H5_DLL herr_t H5D_contig_create(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout);
+H5_DLL herr_t H5D_contig_alloc(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout);
H5_DLL herr_t H5D_contig_fill(H5D_t *dset, hid_t dxpl_id);
H5_DLL haddr_t H5D_contig_get_addr(const H5D_t *dset);
+H5_DLL herr_t H5D_contig_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
+ H5D_chunk_map_t *fm);
+H5_DLL herr_t H5D_contig_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
+ H5D_chunk_map_t *fm);
H5_DLL ssize_t H5D_contig_readvv(const H5D_io_info_t *io_info,
size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[],
- haddr_t UNUSED address, void UNUSED *pointer, void *buf);
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[]);
H5_DLL ssize_t H5D_contig_writevv(const H5D_io_info_t *io_info,
size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[],
- haddr_t UNUSED address, void UNUSED *pointer, const void *buf);
-H5_DLL herr_t H5D_contig_copy(H5F_t *f_src, const H5O_layout_t *layout_src, H5F_t *f_dst,
+ size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[]);
+H5_DLL herr_t H5D_contig_copy(H5F_t *f_src, const H5O_layout_t *layout_src, H5F_t *f_dst,
H5O_layout_t *layout_dst, H5T_t *src_dtype, H5O_copy_t *cpy_info, hid_t dxpl_id);
+/* Functions that operate on chunked dataset storage */
+H5_DLL hbool_t H5D_chunk_cacheable(const H5D_io_info_t *io_info, haddr_t caddr);
+H5_DLL herr_t H5D_chunk_cinfo_cache_reset(H5D_chunk_cached_t *last);
+H5_DLL herr_t H5D_chunk_create(H5D_t *dset /*in,out*/, hid_t dxpl_id);
+H5_DLL herr_t H5D_chunk_init(H5F_t *f, hid_t dapl_id, hid_t dxpl_id, const H5D_t *dset);
+H5_DLL herr_t H5D_chunk_get_info(const H5D_t *dset, hid_t dxpl_id,
+ const hsize_t *chunk_offset, H5D_chunk_ud_t *udata);
+H5_DLL void *H5D_chunk_lock(const H5D_io_info_t *io_info,
+ H5D_chunk_ud_t *udata, hbool_t relax, unsigned *idx_hint/*in,out*/);
+H5_DLL herr_t H5D_chunk_unlock(const H5D_io_info_t *io_info,
+ hbool_t dirty, unsigned idx_hint, void *chunk, uint32_t naccessed);
+H5_DLL herr_t H5D_chunk_flush(H5D_t *dset, hid_t dxpl_id, unsigned flags);
+H5_DLL herr_t H5D_chunk_allocated(H5D_t *dset, hid_t dxpl_id, hsize_t *nbytes);
+H5_DLL herr_t H5D_chunk_allocate(H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite);
+H5_DLL herr_t H5D_chunk_prune_by_extent(H5D_t *dset, hid_t dxpl_id,
+ const hsize_t *old_dims);
+#ifdef H5_HAVE_PARALLEL
+H5_DLL herr_t H5D_chunk_addrmap(const H5D_io_info_t *io_info,
+ haddr_t chunk_addr[], const hsize_t down_chunks[]);
+#endif /* H5_HAVE_PARALLEL */
+H5_DLL herr_t H5D_chunk_update_cache(H5D_t *dset, hid_t dxpl_id);
+H5_DLL herr_t H5D_chunk_copy(H5F_t *f_src, H5O_layout_t *layout_src,
+ H5F_t *f_dst, H5O_layout_t *layout_dst, H5T_t *src_dtype,
+ H5O_copy_t *cpy_info, H5O_pline_t *pline, hid_t dxpl_id);
+H5_DLL herr_t H5D_chunk_bh_info(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout,
+ hsize_t *btree_size);
+H5_DLL herr_t H5D_chunk_dump_index(H5D_t *dset, hid_t dxpl_id, FILE *stream);
+H5_DLL herr_t H5D_chunk_dest(H5F_t *f, hid_t dxpl_id, H5D_t *dset);
+#ifdef H5D_CHUNK_DEBUG
+H5_DLL herr_t H5D_chunk_stats(const H5D_t *dset, hbool_t headers);
+#endif /* H5D_CHUNK_DEBUG */
+
/* Functions that operate on compact dataset storage */
H5_DLL herr_t H5D_compact_fill(H5D_t *dset, hid_t dxpl_id);
-H5_DLL ssize_t H5D_compact_readvv(const H5D_io_info_t *io_info,
- size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_size_arr[], hsize_t dset_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_size_arr[], hsize_t mem_offset_arr[],
- haddr_t UNUSED addr, void UNUSED *pointer/*in*/, void *buf);
-H5_DLL ssize_t H5D_compact_writevv(const H5D_io_info_t *io_info,
- size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_size_arr[], hsize_t dset_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_size_arr[], hsize_t mem_offset_arr[],
- haddr_t UNUSED addr, void UNUSED *pointer/*in*/, const void *buf);
H5_DLL herr_t H5D_compact_copy(H5F_t *f_src, H5O_layout_t *layout_src,
H5F_t *f_dst, H5O_layout_t *layout_dst, H5T_t *src_dtype, H5O_copy_t *cpy_info, hid_t dxpl_id);
-/* Functions that operate on indexed storage */
-/* forward reference for collective-chunk IO use */
-struct H5D_istore_ud1_t; /*define in H5Distore.c*/
-H5_DLL herr_t H5D_istore_init (const H5F_t *f, const H5D_t *dset);
-H5_DLL herr_t H5D_istore_flush (H5D_t *dset, hid_t dxpl_id, unsigned flags);
-H5_DLL herr_t H5D_istore_create(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout);
-H5_DLL herr_t H5D_istore_dest (H5D_t *dset, hid_t dxpl_id);
-H5_DLL herr_t H5D_istore_allocate (H5D_t *dset, hid_t dxpl_id,
- hbool_t full_overwrite);
-H5_DLL hsize_t H5D_istore_allocated(H5D_t *dset, hid_t dxpl_id);
-H5_DLL herr_t H5D_istore_bh_info(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout,
- hsize_t *btree_size);
-H5_DLL herr_t H5D_istore_prune_by_extent(const H5D_io_info_t *io_info,
- const hsize_t *old_dims);
-H5_DLL herr_t H5D_istore_initialize_by_extent(H5D_io_info_t *io_info);
-H5_DLL herr_t H5D_istore_update_cache(H5D_t *dset, hid_t dxpl_id);
-H5_DLL herr_t H5D_istore_dump_btree(H5F_t *f, hid_t dxpl_id, FILE *stream, unsigned ndims,
- haddr_t addr);
-H5_DLL herr_t H5D_istore_chunkmap(const H5D_io_info_t *io_info, haddr_t chunk_addr[],hsize_t down_chunks[] );
-#ifdef H5D_ISTORE_DEBUG
-H5_DLL herr_t H5D_istore_stats (H5D_t *dset, hbool_t headers);
-#endif /* H5D_ISTORE_DEBUG */
-H5_DLL ssize_t H5D_istore_readvv(const H5D_io_info_t *io_info,
- size_t chunk_max_nseq, size_t *chunk_curr_seq, size_t chunk_len_arr[],
- hsize_t chunk_offset_arr[], size_t mem_max_nseq, size_t *mem_curr_seq,
- size_t mem_len_arr[], hsize_t mem_offset_arr[], haddr_t chunk_addr, void *chunk, void *buf);
-H5_DLL ssize_t H5D_istore_writevv(const H5D_io_info_t *io_info,
- size_t chunk_max_nseq, size_t *chunk_curr_seq, size_t chunk_len_arr[],
- hsize_t chunk_offset_arr[], size_t mem_max_nseq, size_t *mem_curr_seq,
- size_t mem_len_arr[], hsize_t mem_offset_arr[], haddr_t chunk_addr, void *chunk,
- const void *buf);
-H5_DLL haddr_t H5D_istore_get_addr(const H5D_io_info_t *io_info,
- struct H5D_istore_ud1_t *_udata);
-H5_DLL herr_t H5D_istore_copy(H5F_t *f_src, H5O_layout_t *layout_src,
- H5F_t *f_dst, H5O_layout_t *layout_dst, H5T_t *src_dtype,
- H5O_copy_t *cpy_info, H5O_pline_t *pline, hid_t dxpl_id);
-H5_DLL void * H5D_istore_lock(const H5D_io_info_t *io_info, H5D_istore_ud1_t *udata,
- hbool_t relax, unsigned *idx_hint/*in,out*/);
-H5_DLL herr_t H5D_istore_unlock(const H5D_io_info_t *io_info,
- hbool_t dirty, unsigned idx_hint, void *chunk, size_t naccessed);
-H5_DLL hbool_t H5D_istore_if_load(H5D_t *dataset, haddr_t caddr);
-
-/* Functions that operate on external file list (efl) storage */
-H5_DLL ssize_t H5D_efl_readvv(const H5D_io_info_t *io_info,
- size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[],
- haddr_t UNUSED addr, void UNUSED *pointer/*in*/, void *buf);
-H5_DLL ssize_t H5D_efl_writevv(const H5D_io_info_t *io_info,
- size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[],
- size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[],
- haddr_t UNUSED addr, void UNUSED *pointer/*in*/, const void *buf);
-
/* Functions that perform fill value operations on datasets */
H5_DLL herr_t H5D_fill(const void *fill, const H5T_t *fill_type, void *buf,
const H5T_t *buf_type, const H5S_t *space, hid_t dxpl_id);
@@ -456,36 +619,37 @@ H5_DLL herr_t H5D_fill_term(H5D_fill_buf_info_t *fb_info);
#define H5Dmpio_DEBUG
#endif /*H5Dmpio_DEBUG*/
#endif/*H5S_DEBUG*/
-/* MPI-IO function to read , it will select either regular or irregular read */
-H5_DLL herr_t H5D_mpio_select_read(H5D_io_info_t *io_info,
- size_t nelmts, size_t elmt_size,
- const struct H5S_t *file_space, const struct H5S_t *mem_space,
- haddr_t addr, void UNUSED *pointer/*in*/, void *buf/*out*/);
-
-/* MPI-IO function to read , it will select either regular or irregular read */
-H5_DLL herr_t H5D_mpio_select_write(H5D_io_info_t *io_info,
- size_t nelmts, size_t elmt_size,
- const struct H5S_t *file_space, const struct H5S_t *mem_space,
- haddr_t addr, void UNUSED *pointer/*in*/, const void *buf);
-
-/* MPI-IO function to handle contiguous collective IO */
-H5_DLL herr_t
-H5D_contig_collective_io(H5D_io_info_t *io_info,
- const H5S_t *file_space,const H5S_t *mem_space,
- const void *_buf,hbool_t do_write);
-
-/* MPI-IO function to handle chunked collective IO */
-H5_DLL herr_t
-H5D_chunk_collective_io(H5D_io_info_t * io_info,fm_map *fm, const void*buf,
- hbool_t do_write);
+/* MPI-IO function to read, it will select either regular or irregular read */
+H5_DLL herr_t H5D_mpio_select_read(const H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space);
+
+/* MPI-IO function to write, it will select either regular or irregular read */
+H5_DLL herr_t H5D_mpio_select_write(const H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space);
+
+/* MPI-IO functions to handle contiguous collective IO */
+H5_DLL herr_t H5D_contig_collective_read(H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info, hsize_t nelmts, const H5S_t *file_space,
+ const H5S_t *mem_space, H5D_chunk_map_t *fm);
+H5_DLL herr_t H5D_contig_collective_write(H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info, hsize_t nelmts, const H5S_t *file_space,
+ const H5S_t *mem_space, H5D_chunk_map_t *fm);
+
+/* MPI-IO functions to handle chunked collective IO */
+H5_DLL herr_t H5D_chunk_collective_read(H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info, hsize_t nelmts, const H5S_t *file_space,
+ const H5S_t *mem_space, H5D_chunk_map_t *fm);
+H5_DLL herr_t H5D_chunk_collective_write(H5D_io_info_t *io_info,
+ const H5D_type_info_t *type_info, hsize_t nelmts, const H5S_t *file_space,
+ const H5S_t *mem_space, H5D_chunk_map_t *fm);
+
/* MPI-IO function to check if a direct I/O transfer is possible between
* memory and the file */
-H5_DLL htri_t H5D_mpio_opt_possible(const H5D_io_info_t *io_info, const H5S_t *mem_space,
- const H5S_t *file_space, const H5T_path_t *tpath);
-
-#ifndef H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS
-H5_DLL herr_t H5D_mpio_chunk_adjust_iomode(H5D_io_info_t *io_info,const fm_map *fm);
-#endif /* H5_MPI_SPECIAL_COLLECTIVE_IO_WORKS */
+H5_DLL htri_t H5D_mpio_opt_possible(const H5D_io_info_t *io_info,
+ const H5S_t *file_space, const H5S_t *mem_space,
+ const H5D_type_info_t *type_info, const H5D_chunk_map_t *fm);
#endif /* H5_HAVE_PARALLEL */
diff --git a/src/H5Dprivate.h b/src/H5Dprivate.h
index 410dc43..96a35cc 100644
--- a/src/H5Dprivate.h
+++ b/src/H5Dprivate.h
@@ -50,6 +50,11 @@
#define H5D_CRT_EXT_FILE_LIST_NAME "efl" /* External file list */
#define H5D_CRT_DATA_PIPELINE_NAME "pline" /* Data filter pipeline */
+/* ======== Dataset access property names ======== */
+#define H5D_ACS_DATA_CACHE_NUM_SLOTS_NAME "rdcc_nslots" /* Size of raw data chunk cache(slots) */
+#define H5D_ACS_DATA_CACHE_BYTE_SIZE_NAME "rdcc_nbytes" /* Size of raw data chunk cache(bytes) */
+#define H5D_ACS_PREEMPT_READ_CHUNKS_NAME "rdcc_w0" /* Preemption read chunks first */
+
/* ======== Data transfer properties ======== */
#define H5D_XFER_MAX_TEMP_BUF_NAME "max_temp_buf" /* Maximum temp buffer size */
#define H5D_XFER_TCONV_BUF_NAME "tconv_buf" /* Type conversion buffer */
@@ -65,7 +70,6 @@
#define H5D_XFER_HYPER_VECTOR_SIZE_NAME "vec_size" /* Hyperslab vector size */
#ifdef H5_HAVE_PARALLEL
#define H5D_XFER_IO_XFER_MODE_NAME "io_xfer_mode" /* I/O transfer mode */
-#define H5D_XFER_IO_XFER_OPT_MODE_NAME "io_xfer_opt_mode" /* I/O optimization transfer mode (using MPI-IO independent IO with file set view) */
#define H5D_XFER_MPIO_COLLECTIVE_OPT_NAME "mpio_collective_opt" /* Optimization of MPI-IO transfer mode */
#define H5D_XFER_MPIO_CHUNK_OPT_HARD_NAME "mpio_chunk_opt_hard"
#define H5D_XFER_MPIO_CHUNK_OPT_NUM_NAME "mpio_chunk_opt_num"
@@ -83,9 +87,13 @@
#define H5D_XFER_COLL_CHUNK_LINK_NUM_FALSE_NAME "coll_chunk_link_false"
#define H5D_XFER_COLL_CHUNK_MULTI_RATIO_COLL_NAME "coll_chunk_multi_coll"
#define H5D_XFER_COLL_CHUNK_MULTI_RATIO_IND_NAME "coll_chunk_multi_ind"
+#define H5D_XFER_COLL_CHUNK_LINK_TO_MULTI "coll_chunk_link_mul"/* Internal transferring from link to multiple chunk */
+#define H5D_XFER_COLL_CHUNK_LINK_TO_MULTI_OPT "coll_chunk_link_mul_opt"/* Internal transferring from link opt to multiple chunk opt*/
+
/* Definitions for all collective chunk instrumentation properties */
#define H5D_XFER_COLL_CHUNK_SIZE sizeof(unsigned)
#define H5D_XFER_COLL_CHUNK_DEF 1
+#define H5D_XFER_COLL_CHUNK_FIX 0
#endif /* H5_HAVE_INSTRUMENTED_LIBRARY */
/* Default temporary buffer size */
@@ -107,23 +115,6 @@
/* Typedef for dataset in memory (defined in H5Dpkg.h) */
typedef struct H5D_t H5D_t;
-/* Typedef for dataset storage information */
-typedef struct {
- hsize_t index; /* "Index" of chunk in dataset (must be first for TBBT routines) */
- hsize_t *offset; /* Chunk's coordinates in elements */
-} H5D_chunk_storage_t;
-
-typedef struct {
- haddr_t dset_addr; /* Address of dataset in file */
- hsize_t dset_size; /* Total size of dataset in file */
-} H5D_contig_storage_t;
-
-typedef union H5D_storage_t {
- H5O_efl_t efl; /* External file list information for dataset */
- H5D_chunk_storage_t chunk; /* Chunk information for dataset */
- H5D_contig_storage_t contig; /* Contiguous information for dataset */
-} H5D_storage_t;
-
/* Typedef for cached dataset transfer property list information */
typedef struct H5D_dxpl_cache_t {
size_t max_temp_buf; /* Maximum temporary buffer size (H5D_XFER_MAX_TEMP_BUF_NAME) */
@@ -135,7 +126,7 @@ typedef struct H5D_dxpl_cache_t {
size_t vec_size; /* Size of hyperslab vector (H5D_XFER_HYPER_VECTOR_SIZE_NAME) */
#ifdef H5_HAVE_PARALLEL
H5FD_mpio_xfer_t xfer_mode; /* Parallel transfer for this request (H5D_XFER_IO_XFER_MODE_NAME) */
- H5FD_mpio_collective_opt_t xfer_opt_mode; /* Parallel transfer with independent IO or collective IO with this mode */
+ H5FD_mpio_collective_opt_t coll_opt_mode; /* Parallel transfer with independent IO or collective IO with this mode */
#endif /*H5_HAVE_PARALLEL*/
H5Z_cb_t filter_cb; /* Filter callback function (H5D_XFER_FILTER_CB_NAME) */
H5Z_data_xform_t *data_xform_prop; /* Data transform prop (H5D_XFER_XFORM_NAME) */
@@ -157,14 +148,12 @@ typedef struct H5D_dcpl_cache_t {
/******************************/
H5_DLL herr_t H5D_init(void);
-H5_DLL H5D_t *H5D_open(const H5G_loc_t *loc, hid_t dxpl_id);
+H5_DLL H5D_t *H5D_open(const H5G_loc_t *loc, hid_t dapl_id, hid_t dxpl_id);
H5_DLL herr_t H5D_close(H5D_t *dataset);
H5_DLL H5O_loc_t *H5D_oloc(H5D_t *dataset);
H5_DLL H5G_name_t *H5D_nameof(H5D_t *dataset);
H5_DLL H5T_t *H5D_typeof(const H5D_t *dset);
H5_DLL herr_t H5D_flush(const H5F_t *f, hid_t dxpl_id, unsigned flags);
-H5_DLL herr_t H5D_get_dxpl_cache(hid_t dxpl_id, H5D_dxpl_cache_t **cache);
-H5_DLL herr_t H5D_get_dxpl_cache_real(hid_t dxpl_id, H5D_dxpl_cache_t *cache);
/* Functions that operate on vlen data */
H5_DLL herr_t H5D_vlen_reclaim(hid_t type_id, H5S_t *space, hid_t plist_id,
@@ -174,10 +163,11 @@ H5_DLL herr_t H5D_vlen_reclaim(hid_t type_id, H5S_t *space, hid_t plist_id,
H5_DLL herr_t H5D_contig_delete(H5F_t *f, hid_t dxpl_id,
const H5O_layout_t *layout);
+/* Functions that operate on chunked storage */
+H5_DLL herr_t H5D_chunk_delete(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout);
+
/* Functions that operate on indexed storage */
-H5_DLL herr_t H5D_istore_delete(H5F_t *f, hid_t dxpl_id,
- const H5O_layout_t *layout);
-H5_DLL herr_t H5D_istore_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream,
+H5_DLL herr_t H5D_btree_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream,
int indent, int fwidth, unsigned ndims);
#endif /* _H5Dprivate_H */
diff --git a/src/H5Dpublic.h b/src/H5Dpublic.h
index d7f6574..636c449 100644
--- a/src/H5Dpublic.h
+++ b/src/H5Dpublic.h
@@ -29,6 +29,11 @@
/* Public Macros */
/*****************/
+/* Macros used to "unset" chunk cache configuration parameters */
+#define H5D_CHUNK_CACHE_NSLOTS_DEFAULT ((size_t) -1)
+#define H5D_CHUNK_CACHE_NBYTES_DEFAULT ((size_t) -1)
+#define H5D_CHUNK_CACHE_W0_DEFAULT -1.
+
/*******************/
/* Public Typedefs */
/*******************/
@@ -101,6 +106,7 @@ H5_DLL hid_t H5Dget_space(hid_t dset_id);
H5_DLL herr_t H5Dget_space_status(hid_t dset_id, H5D_space_status_t *allocation);
H5_DLL hid_t H5Dget_type(hid_t dset_id);
H5_DLL hid_t H5Dget_create_plist(hid_t dset_id);
+H5_DLL hid_t H5Dget_access_plist(hid_t dset_id);
H5_DLL hsize_t H5Dget_storage_size(hid_t dset_id);
H5_DLL haddr_t H5Dget_offset(hid_t dset_id);
H5_DLL herr_t H5Dread(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id,
@@ -113,11 +119,11 @@ H5_DLL herr_t H5Dvlen_reclaim(hid_t type_id, hid_t space_id, hid_t plist_id, voi
H5_DLL herr_t H5Dvlen_get_buf_size(hid_t dataset_id, hid_t type_id, hid_t space_id, hsize_t *size);
H5_DLL herr_t H5Dfill(const void *fill, hid_t fill_type, void *buf,
hid_t buf_type, hid_t space);
-H5_DLL herr_t H5Dset_extent(hid_t dset_id, const hsize_t *size);
+H5_DLL herr_t H5Dset_extent(hid_t dset_id, const hsize_t size[]);
H5_DLL herr_t H5Ddebug(hid_t dset_id);
/* Symbols defined for compatibility with previous versions of the HDF5 API.
- *
+ *
* Use of these symbols is deprecated.
*/
#ifndef H5_NO_DEPRECATED_SYMBOLS
@@ -132,7 +138,7 @@ H5_DLL herr_t H5Ddebug(hid_t dset_id);
H5_DLL hid_t H5Dcreate1(hid_t file_id, const char *name, hid_t type_id,
hid_t space_id, hid_t dcpl_id);
H5_DLL hid_t H5Dopen1(hid_t file_id, const char *name);
-H5_DLL herr_t H5Dextend(hid_t dset_id, const hsize_t *size);
+H5_DLL herr_t H5Dextend(hid_t dset_id, const hsize_t size[]);
#endif /* H5_NO_DEPRECATED_SYMBOLS */
diff --git a/src/H5Dscatgath.c b/src/H5Dscatgath.c
new file mode 100644
index 0000000..867303f
--- /dev/null
+++ b/src/H5Dscatgath.c
@@ -0,0 +1,900 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5D_PACKAGE /*suppress error about including H5Dpkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Dpkg.h" /* Dataset functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5FLprivate.h" /* Free Lists */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+static size_t H5D_gather_file(const H5D_io_info_t *io_info,
+ const H5S_t *file_space, H5S_sel_iter_t *file_iter, size_t nelmts,
+ void *buf);
+static herr_t H5D_scatter_file(const H5D_io_info_t *io_info,
+ const H5S_t *file_space, H5S_sel_iter_t *file_iter, size_t nelmts,
+ const void *buf);
+static size_t H5D_gather_mem(const void *_buf,
+ const H5S_t *space, H5S_sel_iter_t *iter, size_t nelmts,
+ const H5D_dxpl_cache_t *dxpl_cache, void *_tgath_buf/*out*/);
+static herr_t H5D_compound_opt_read(size_t nelmts, const H5S_t *mem_space,
+ H5S_sel_iter_t *iter, const H5D_dxpl_cache_t *dxpl_cache,
+ const H5D_type_info_t *type_info, void *user_buf/*out*/);
+static herr_t H5D_compound_opt_write(size_t nelmts, const H5D_type_info_t *type_info);
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* Declare a free list to manage sequences of size_t */
+H5FL_SEQ_EXTERN(size_t);
+
+/* Declare a free list to manage sequences of hsize_t */
+H5FL_SEQ_EXTERN(hsize_t);
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_scatter_file
+ *
+ * Purpose: Scatters dataset elements from the type conversion buffer BUF
+ * to the file F where the data points are arranged according to
+ * the file dataspace FILE_SPACE and stored according to
+ * LAYOUT and EFL. Each element is ELMT_SIZE bytes.
+ * The caller is requesting that NELMTS elements are copied.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, June 20, 2002
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_scatter_file(const H5D_io_info_t *_io_info,
+ const H5S_t *space, H5S_sel_iter_t *iter, size_t nelmts,
+ const void *_buf)
+{
+ H5D_io_info_t tmp_io_info; /* Temporary I/O info object */
+ hsize_t _off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets */
+ hsize_t *off = NULL; /* Pointer to sequence offsets */
+ hsize_t mem_off; /* Offset in memory */
+ size_t mem_curr_seq; /* "Current sequence" in memory */
+ size_t dset_curr_seq; /* "Current sequence" in dataset */
+ size_t _len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths */
+ size_t *len = NULL; /* Array to store sequence lengths */
+ size_t orig_mem_len, mem_len; /* Length of sequence in memory */
+ size_t nseq; /* Number of sequences generated */
+ size_t nelem; /* Number of elements used in sequences */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_scatter_file)
+
+ /* Check args */
+ HDassert(_io_info);
+ HDassert(space);
+ HDassert(iter);
+ HDassert(nelmts > 0);
+ HDassert(_buf);
+
+ /* Set up temporary I/O info object */
+ HDmemcpy(&tmp_io_info, _io_info, sizeof(*_io_info));
+ tmp_io_info.op_type = H5D_IO_OP_WRITE;
+ tmp_io_info.u.wbuf = _buf;
+
+ /* Allocate the vector I/O arrays */
+ if(tmp_io_info.dxpl_cache->vec_size > H5D_IO_VECTOR_SIZE) {
+ if(NULL == (len = H5FL_SEQ_MALLOC(size_t, tmp_io_info.dxpl_cache->vec_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array")
+ if(NULL == (off = H5FL_SEQ_MALLOC(hsize_t, tmp_io_info.dxpl_cache->vec_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array")
+ } /* end if */
+ else {
+ len = _len;
+ off = _off;
+ } /* end else */
+
+ /* Loop until all elements are written */
+ while(nelmts > 0) {
+ /* Get list of sequences for selection to write */
+ if(H5S_SELECT_GET_SEQ_LIST(space, H5S_GET_SEQ_LIST_SORTED, iter, tmp_io_info.dxpl_cache->vec_size, nelmts, &nseq, &nelem, off, len) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed")
+
+ /* Reset the current sequence information */
+ mem_curr_seq = dset_curr_seq = 0;
+ orig_mem_len = mem_len = nelem * iter->elmt_size;
+ mem_off = 0;
+
+ /* Write sequence list out */
+ if((*tmp_io_info.layout_ops.writevv)(&tmp_io_info, nseq, &dset_curr_seq,
+ len, off, (size_t)1, &mem_curr_seq, &mem_len, &mem_off) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error")
+
+ /* Update buffer */
+ tmp_io_info.u.wbuf = (const uint8_t *)tmp_io_info.u.wbuf + orig_mem_len;
+
+ /* Decrement number of elements left to process */
+ nelmts -= nelem;
+ } /* end while */
+
+done:
+ /* Release resources, if allocated */
+ if(len && len != _len)
+ H5FL_SEQ_FREE(size_t, len);
+ if(off && off != _off)
+ H5FL_SEQ_FREE(hsize_t, off);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D_scatter_file() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_gather_file
+ *
+ * Purpose: Gathers data points from file F and accumulates them in the
+ * type conversion buffer BUF. The LAYOUT argument describes
+ * how the data is stored on disk and EFL describes how the data
+ * is organized in external files. ELMT_SIZE is the size in
+ * bytes of a datum which this function treats as opaque.
+ * FILE_SPACE describes the dataspace of the dataset on disk
+ * and the elements that have been selected for reading (via
+ * hyperslab, etc). This function will copy at most NELMTS
+ * elements.
+ *
+ * Return: Success: Number of elements copied.
+ * Failure: 0
+ *
+ * Programmer: Quincey Koziol
+ * Monday, June 24, 2002
+ *
+ *-------------------------------------------------------------------------
+ */
+static size_t
+H5D_gather_file(const H5D_io_info_t *_io_info,
+ const H5S_t *space, H5S_sel_iter_t *iter, size_t nelmts,
+ void *_buf/*out*/)
+{
+ H5D_io_info_t tmp_io_info; /* Temporary I/O info object */
+ hsize_t _off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets */
+ hsize_t *off = NULL; /* Pointer to sequence offsets */
+ hsize_t mem_off; /* Offset in memory */
+ size_t mem_curr_seq; /* "Current sequence" in memory */
+ size_t dset_curr_seq; /* "Current sequence" in dataset */
+ size_t _len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths */
+ size_t *len = NULL; /* Pointer to sequence lengths */
+ size_t orig_mem_len, mem_len; /* Length of sequence in memory */
+ size_t nseq; /* Number of sequences generated */
+ size_t nelem; /* Number of elements used in sequences */
+ size_t ret_value = nelmts; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_gather_file)
+
+ /* Check args */
+ HDassert(_io_info);
+ HDassert(_io_info->dset);
+ HDassert(_io_info->store);
+ HDassert(space);
+ HDassert(iter);
+ HDassert(nelmts > 0);
+ HDassert(_buf);
+
+ /* Set up temporary I/O info object */
+ HDmemcpy(&tmp_io_info, _io_info, sizeof(*_io_info));
+ tmp_io_info.op_type = H5D_IO_OP_READ;
+ tmp_io_info.u.rbuf = _buf;
+
+ /* Allocate the vector I/O arrays */
+ if(tmp_io_info.dxpl_cache->vec_size > H5D_IO_VECTOR_SIZE) {
+ if(NULL == (len = H5FL_SEQ_MALLOC(size_t, tmp_io_info.dxpl_cache->vec_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate I/O length vector array")
+ if(NULL == (off = H5FL_SEQ_MALLOC(hsize_t, tmp_io_info.dxpl_cache->vec_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate I/O offset vector array")
+ } /* end if */
+ else {
+ len = _len;
+ off = _off;
+ } /* end else */
+
+ /* Loop until all elements are read */
+ while(nelmts > 0) {
+ /* Get list of sequences for selection to read */
+ if(H5S_SELECT_GET_SEQ_LIST(space, H5S_GET_SEQ_LIST_SORTED, iter, tmp_io_info.dxpl_cache->vec_size, nelmts, &nseq, &nelem, off, len) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, 0, "sequence length generation failed")
+
+ /* Reset the current sequence information */
+ mem_curr_seq = dset_curr_seq = 0;
+ orig_mem_len = mem_len = nelem * iter->elmt_size;
+ mem_off = 0;
+
+ /* Read sequence list in */
+ if((*tmp_io_info.layout_ops.readvv)(&tmp_io_info, nseq, &dset_curr_seq,
+ len, off, (size_t)1, &mem_curr_seq, &mem_len, &mem_off) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, 0, "read error")
+
+ /* Update buffer */
+ tmp_io_info.u.rbuf = (uint8_t *)tmp_io_info.u.rbuf + orig_mem_len;
+
+ /* Decrement number of elements left to process */
+ nelmts -= nelem;
+ } /* end while */
+
+done:
+ /* Release resources, if allocated */
+ if(len && len != _len)
+ H5FL_SEQ_FREE(size_t, len);
+ if(off && off != _off)
+ H5FL_SEQ_FREE(hsize_t, off);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D_gather_file() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_scatter_mem
+ *
+ * Purpose: Scatters NELMTS data points from the scatter buffer
+ * TSCAT_BUF to the application buffer BUF. Each element is
+ * ELMT_SIZE bytes and they are organized in application memory
+ * according to SPACE.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Monday, July 8, 2002
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_scatter_mem (const void *_tscat_buf, const H5S_t *space,
+ H5S_sel_iter_t *iter, size_t nelmts, const H5D_dxpl_cache_t *dxpl_cache,
+ void *_buf/*out*/)
+{
+ uint8_t *buf = (uint8_t *)_buf; /* Get local copies for address arithmetic */
+ const uint8_t *tscat_buf = (const uint8_t *)_tscat_buf;
+ hsize_t _off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets */
+ hsize_t *off = NULL; /* Pointer to sequence offsets */
+ size_t _len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths */
+ size_t *len = NULL; /* Pointer to sequence lengths */
+ size_t curr_len; /* Length of bytes left to process in sequence */
+ size_t nseq; /* Number of sequences generated */
+ size_t curr_seq; /* Current sequence being processed */
+ size_t nelem; /* Number of elements used in sequences */
+ herr_t ret_value = SUCCEED; /* Number of elements scattered */
+
+ FUNC_ENTER_NOAPI(H5D_scatter_mem, FAIL)
+
+ /* Check args */
+ HDassert(tscat_buf);
+ HDassert(space);
+ HDassert(iter);
+ HDassert(nelmts > 0);
+ HDassert(buf);
+
+ /* Allocate the vector I/O arrays */
+ if(dxpl_cache->vec_size > H5D_IO_VECTOR_SIZE) {
+ if(NULL == (len = H5FL_SEQ_MALLOC(size_t, dxpl_cache->vec_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array")
+ if(NULL == (off = H5FL_SEQ_MALLOC(hsize_t, dxpl_cache->vec_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array")
+ } /* end if */
+ else {
+ len = _len;
+ off = _off;
+ } /* end else */
+
+ /* Loop until all elements are written */
+ while(nelmts > 0) {
+ /* Get list of sequences for selection to write */
+ if(H5S_SELECT_GET_SEQ_LIST(space, 0, iter, dxpl_cache->vec_size, nelmts, &nseq, &nelem, off, len) < 0)
+ HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, 0, "sequence length generation failed")
+
+ /* Loop, while sequences left to process */
+ for(curr_seq = 0; curr_seq < nseq; curr_seq++) {
+ /* Get the number of bytes in sequence */
+ curr_len = len[curr_seq];
+
+ HDmemcpy(buf + off[curr_seq], tscat_buf, curr_len);
+
+ /* Advance offset in destination buffer */
+ tscat_buf += curr_len;
+ } /* end for */
+
+ /* Decrement number of elements left to process */
+ nelmts -= nelem;
+ } /* end while */
+
+done:
+ /* Release resources, if allocated */
+ if(len && len != _len)
+ H5FL_SEQ_FREE(size_t, len);
+ if(off && off != _off)
+ H5FL_SEQ_FREE(hsize_t, off);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D_scatter_mem() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_gather_mem
+ *
+ * Purpose: Gathers dataset elements from application memory BUF and
+ * copies them into the gather buffer TGATH_BUF.
+ * Each element is ELMT_SIZE bytes and arranged in application
+ * memory according to SPACE.
+ * The caller is requesting that at most NELMTS be gathered.
+ *
+ * Return: Success: Number of elements copied.
+ * Failure: 0
+ *
+ * Programmer: Quincey Koziol
+ * Monday, June 24, 2002
+ *
+ *-------------------------------------------------------------------------
+ */
+static size_t
+H5D_gather_mem(const void *_buf, const H5S_t *space,
+ H5S_sel_iter_t *iter, size_t nelmts, const H5D_dxpl_cache_t *dxpl_cache,
+ void *_tgath_buf/*out*/)
+{
+ const uint8_t *buf = (const uint8_t *)_buf; /* Get local copies for address arithmetic */
+ uint8_t *tgath_buf = (uint8_t *)_tgath_buf;
+ hsize_t _off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets */
+ hsize_t *off = NULL; /* Pointer to sequence offsets */
+ size_t _len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths */
+ size_t *len = NULL; /* Pointer to sequence lengths */
+ size_t curr_len; /* Length of bytes left to process in sequence */
+ size_t nseq; /* Number of sequences generated */
+ size_t curr_seq; /* Current sequence being processed */
+ size_t nelem; /* Number of elements used in sequences */
+ size_t ret_value = nelmts; /* Number of elements gathered */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_gather_mem)
+
+ /* Check args */
+ HDassert(buf);
+ HDassert(space);
+ HDassert(iter);
+ HDassert(nelmts > 0);
+ HDassert(tgath_buf);
+
+ /* Allocate the vector I/O arrays */
+ if(dxpl_cache->vec_size > H5D_IO_VECTOR_SIZE) {
+ if(NULL == (len = H5FL_SEQ_MALLOC(size_t, dxpl_cache->vec_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate I/O length vector array")
+ if(NULL == (off = H5FL_SEQ_MALLOC(hsize_t, dxpl_cache->vec_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate I/O offset vector array")
+ } /* end if */
+ else {
+ len = _len;
+ off = _off;
+ } /* end else */
+
+ /* Loop until all elements are written */
+ while(nelmts > 0) {
+ /* Get list of sequences for selection to write */
+ if(H5S_SELECT_GET_SEQ_LIST(space, 0, iter, dxpl_cache->vec_size, nelmts, &nseq, &nelem, off, len) < 0)
+ HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, 0, "sequence length generation failed")
+
+ /* Loop, while sequences left to process */
+ for(curr_seq = 0; curr_seq < nseq; curr_seq++) {
+ /* Get the number of bytes in sequence */
+ curr_len = len[curr_seq];
+
+ HDmemcpy(tgath_buf, buf + off[curr_seq], curr_len);
+
+ /* Advance offset in gather buffer */
+ tgath_buf += curr_len;
+ } /* end for */
+
+ /* Decrement number of elements left to process */
+ nelmts -= nelem;
+ } /* end while */
+
+done:
+ /* Release resources, if allocated */
+ if(len && len != _len)
+ H5FL_SEQ_FREE(size_t, len);
+ if(off && off != _off)
+ H5FL_SEQ_FREE(hsize_t, off);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D_gather_mem() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_scatgath_read
+ *
+ * Purpose: Perform scatter/gather ead from a contiguous [piece of a] dataset.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, March 6, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_scatgath_read(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space)
+{
+ const H5D_dxpl_cache_t *dxpl_cache = io_info->dxpl_cache; /* Local pointer to dataset transfer info */
+ void *buf = io_info->u.rbuf; /* Local pointer to application buffer */
+ H5S_sel_iter_t mem_iter; /*memory selection iteration info*/
+ hbool_t mem_iter_init = FALSE; /*memory selection iteration info has been initialized */
+ H5S_sel_iter_t bkg_iter; /*background iteration info*/
+ hbool_t bkg_iter_init = FALSE; /*background iteration info has been initialized */
+ H5S_sel_iter_t file_iter; /*file selection iteration info*/
+ hbool_t file_iter_init = FALSE; /*file selection iteration info has been initialized */
+ hsize_t smine_start; /*strip mine start loc */
+ size_t smine_nelmts; /*elements per strip */
+ herr_t ret_value = SUCCEED; /*return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_scatgath_read)
+
+ /* Sanity check */
+ HDassert(io_info);
+ HDassert(type_info);
+ HDassert(mem_space);
+ HDassert(file_space);
+ HDassert(buf);
+
+ /* Check for NOOP read */
+ if(nelmts == 0)
+ HGOTO_DONE(SUCCEED)
+
+ /* Figure out the strip mine size. */
+ if(H5S_select_iter_init(&file_iter, file_space, type_info->src_type_size) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize file selection information")
+ file_iter_init = TRUE; /*file selection iteration info has been initialized */
+ if(H5S_select_iter_init(&mem_iter, mem_space, type_info->dst_type_size) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize memory selection information")
+ mem_iter_init = TRUE; /*file selection iteration info has been initialized */
+ if(H5S_select_iter_init(&bkg_iter, mem_space, type_info->dst_type_size) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize background selection information")
+ bkg_iter_init = TRUE; /*file selection iteration info has been initialized */
+
+ /* Start strip mining... */
+ for(smine_start = 0; smine_start < nelmts; smine_start += smine_nelmts) {
+ size_t n; /* Elements operated on */
+
+ /* Go figure out how many elements to read from the file */
+ HDassert(H5S_SELECT_ITER_NELMTS(&file_iter) == (nelmts - smine_start));
+ smine_nelmts = (size_t)MIN(type_info->request_nelmts, (nelmts - smine_start));
+
+ /*
+ * Gather the data from disk into the datatype conversion
+ * buffer. Also gather data from application to background buffer
+ * if necessary.
+ */
+
+ /*
+ * Gather data
+ */
+ n = H5D_gather_file(io_info, file_space, &file_iter, smine_nelmts,
+ type_info->tconv_buf/*out*/);
+ if(n != smine_nelmts)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file gather failed")
+
+ /* If the source and destination are compound types and subset of each other
+ * and no conversion is needed, copy the data directly into user's buffer and
+ * bypass the rest of steps.
+ */
+ if(type_info->cmpd_subset && H5T_SUBSET_FALSE != type_info->cmpd_subset->subset) {
+ if(H5D_compound_opt_read(smine_nelmts, mem_space, &mem_iter, dxpl_cache,
+ type_info, buf /*out*/) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
+ } /* end if */
+ else {
+ if(H5T_BKG_YES == type_info->need_bkg) {
+ n = H5D_gather_mem(buf, mem_space, &bkg_iter, smine_nelmts,
+ dxpl_cache, type_info->bkg_buf/*out*/);
+ if(n != smine_nelmts)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "mem gather failed")
+ } /* end if */
+
+ /*
+ * Perform datatype conversion.
+ */
+ if(H5T_convert(type_info->tpath, type_info->src_type_id, type_info->dst_type_id,
+ smine_nelmts, (size_t)0, (size_t)0, type_info->tconv_buf,
+ type_info->bkg_buf, io_info->dxpl_id) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "datatype conversion failed")
+
+ /* Do the data transform after the conversion (since we're using type mem_type) */
+ if(!type_info->is_xform_noop)
+ if(H5Z_xform_eval(dxpl_cache->data_xform_prop, type_info->tconv_buf, smine_nelmts, type_info->mem_type) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Error performing data transform")
+
+ /*
+ * Scatter the data into memory.
+ */
+ if(H5D_scatter_mem(type_info->tconv_buf, mem_space, &mem_iter,
+ smine_nelmts, dxpl_cache, buf/*out*/) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "scatter failed")
+ } /* end else */
+ } /* end for */
+
+done:
+ /* Release selection iterators */
+ if(file_iter_init) {
+ if(H5S_SELECT_ITER_RELEASE(&file_iter) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
+ } /* end if */
+ if(mem_iter_init) {
+ if(H5S_SELECT_ITER_RELEASE(&mem_iter) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
+ } /* end if */
+ if(bkg_iter_init) {
+ if(H5S_SELECT_ITER_RELEASE(&bkg_iter) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_scatgath_read() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_scatgath_write
+ *
+ * Purpose: Perform scatter/gather write to a contiguous [piece of a] dataset.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, March 6, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_scatgath_write(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space)
+{
+ const H5D_dxpl_cache_t *dxpl_cache = io_info->dxpl_cache; /* Local pointer to dataset transfer info */
+ const void *buf = io_info->u.wbuf; /* Local pointer to application buffer */
+ H5S_sel_iter_t mem_iter; /*memory selection iteration info*/
+ hbool_t mem_iter_init = FALSE; /*memory selection iteration info has been initialized */
+ H5S_sel_iter_t bkg_iter; /*background iteration info*/
+ hbool_t bkg_iter_init = FALSE; /*background iteration info has been initialized */
+ H5S_sel_iter_t file_iter; /*file selection iteration info*/
+ hbool_t file_iter_init = FALSE; /*file selection iteration info has been initialized */
+ hsize_t smine_start; /*strip mine start loc */
+ size_t smine_nelmts; /*elements per strip */
+ herr_t ret_value = SUCCEED; /*return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_scatgath_write)
+
+ /* Sanity check */
+ HDassert(io_info);
+ HDassert(type_info);
+ HDassert(mem_space);
+ HDassert(file_space);
+ HDassert(buf);
+
+ /* Check for NOOP write */
+ if(nelmts == 0)
+ HGOTO_DONE(SUCCEED)
+
+ /* Figure out the strip mine size. */
+ if(H5S_select_iter_init(&file_iter, file_space, type_info->dst_type_size) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize file selection information")
+ file_iter_init = TRUE; /*file selection iteration info has been initialized */
+ if(H5S_select_iter_init(&mem_iter, mem_space, type_info->src_type_size) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize memory selection information")
+ mem_iter_init = TRUE; /*file selection iteration info has been initialized */
+ if(H5S_select_iter_init(&bkg_iter, file_space, type_info->dst_type_size) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize background selection information")
+ bkg_iter_init = TRUE; /*file selection iteration info has been initialized */
+
+ /* Start strip mining... */
+ for(smine_start = 0; smine_start < nelmts; smine_start += smine_nelmts) {
+ size_t n; /* Elements operated on */
+
+ /* Go figure out how many elements to read from the file */
+ HDassert(H5S_SELECT_ITER_NELMTS(&file_iter) == (nelmts - smine_start));
+ smine_nelmts = (size_t)MIN(type_info->request_nelmts, (nelmts - smine_start));
+
+ /*
+ * Gather data from application buffer into the datatype conversion
+ * buffer. Also gather data from the file into the background buffer
+ * if necessary.
+ */
+ n = H5D_gather_mem(buf, mem_space, &mem_iter, smine_nelmts,
+ dxpl_cache, type_info->tconv_buf/*out*/);
+ if(n != smine_nelmts)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "mem gather failed")
+
+ /* If the source and destination are compound types and the destination is
+ * is a subset of the source and no conversion is needed, copy the data
+ * directly into user's buffer and bypass the rest of steps. If the source
+ * is a subset of the destination, the optimization is done in conversion
+ * function H5T_conv_struct_opt to protect the background data.
+ */
+ if(type_info->cmpd_subset && H5T_SUBSET_DST == type_info->cmpd_subset->subset
+ && type_info->dst_type_size == type_info->cmpd_subset->copy_size) {
+ if(H5D_compound_opt_write(smine_nelmts, type_info) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "datatype conversion failed")
+ } /* end if */
+ else {
+ if(H5T_BKG_YES == type_info->need_bkg) {
+ n = H5D_gather_file(io_info, file_space, &bkg_iter, smine_nelmts,
+ type_info->bkg_buf/*out*/);
+ if(n != smine_nelmts)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file gather failed")
+ } /* end if */
+
+ /*
+ * Perform datatype conversion.
+ */
+ if(H5T_convert(type_info->tpath, type_info->src_type_id, type_info->dst_type_id,
+ smine_nelmts, (size_t)0, (size_t)0, type_info->tconv_buf,
+ type_info->bkg_buf, io_info->dxpl_id) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "datatype conversion failed")
+
+ /* Do the data transform after the type conversion (since we're using dataset->shared->type). */
+ if(!type_info->is_xform_noop)
+ if(H5Z_xform_eval(dxpl_cache->data_xform_prop, type_info->tconv_buf, smine_nelmts, type_info->dset_type) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Error performing data transform")
+ } /* end else */
+
+ /*
+ * Scatter the data out to the file.
+ */
+ if(H5D_scatter_file(io_info, file_space, &file_iter, smine_nelmts,
+ type_info->tconv_buf) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "scatter failed")
+ } /* end for */
+
+done:
+ /* Release selection iterators */
+ if(file_iter_init) {
+ if(H5S_SELECT_ITER_RELEASE(&file_iter) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
+ } /* end if */
+ if(mem_iter_init) {
+ if(H5S_SELECT_ITER_RELEASE(&mem_iter) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
+ } /* end if */
+ if(bkg_iter_init) {
+ if(H5S_SELECT_ITER_RELEASE(&bkg_iter) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_scatgath_write() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_compound_opt_read
+ *
+ * Purpose: A special optimization case when the source and
+ * destination members are a subset of each other, and
+ * the order is the same, and no conversion is needed.
+ * For example:
+ * struct source { struct destination {
+ * TYPE1 A; --> TYPE1 A;
+ * TYPE2 B; --> TYPE2 B;
+ * TYPE3 C; --> TYPE3 C;
+ * }; TYPE4 D;
+ * TYPE5 E;
+ * };
+ * or
+ * struct destination { struct source {
+ * TYPE1 A; <-- TYPE1 A;
+ * TYPE2 B; <-- TYPE2 B;
+ * TYPE3 C; <-- TYPE3 C;
+ * }; TYPE4 D;
+ * TYPE5 E;
+ * };
+ * The optimization is simply moving data to the appropriate
+ * places in the buffer.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Raymond Lu
+ * 11 June 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_compound_opt_read(size_t nelmts, const H5S_t *space,
+ H5S_sel_iter_t *iter, const H5D_dxpl_cache_t *dxpl_cache,
+ const H5D_type_info_t *type_info, void *user_buf/*out*/)
+{
+ uint8_t *ubuf = (uint8_t *)user_buf; /* Cast for pointer arithmetic */
+ uint8_t *xdbuf; /* Pointer into dataset buffer */
+ hsize_t _off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets */
+ hsize_t *off = NULL; /* Pointer to sequence offsets */
+ size_t _len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths */
+ size_t *len = NULL; /* Pointer to sequence lengths */
+ size_t src_stride, dst_stride, copy_size;
+ herr_t ret_value = SUCCEED; /*return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_compound_opt_read)
+
+ /* Check args */
+ HDassert(nelmts > 0);
+ HDassert(space);
+ HDassert(iter);
+ HDassert(dxpl_cache);
+ HDassert(type_info);
+ HDassert(type_info->cmpd_subset);
+ HDassert(H5T_SUBSET_SRC == type_info->cmpd_subset->subset ||
+ H5T_SUBSET_DST == type_info->cmpd_subset->subset);
+ HDassert(user_buf);
+
+ /* Allocate the vector I/O arrays */
+ if(dxpl_cache->vec_size > H5D_IO_VECTOR_SIZE) {
+ if(NULL == (len = H5FL_SEQ_MALLOC(size_t, dxpl_cache->vec_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array")
+ if(NULL == (off = H5FL_SEQ_MALLOC(hsize_t, dxpl_cache->vec_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array")
+ } /* end if */
+ else {
+ len = _len;
+ off = _off;
+ } /* end else */
+
+ /* Get source & destination strides */
+ src_stride = type_info->src_type_size;
+ dst_stride = type_info->dst_type_size;
+
+ /* Get the size, in bytes, to copy for each element */
+ copy_size = type_info->cmpd_subset->copy_size;
+
+ /* Loop until all elements are written */
+ xdbuf = type_info->tconv_buf;
+ while(nelmts > 0) {
+ size_t nseq; /* Number of sequences generated */
+ size_t curr_seq; /* Current sequence being processed */
+ size_t elmtno; /* Element counter */
+
+ /* Get list of sequences for selection to write */
+ if(H5S_SELECT_GET_SEQ_LIST(space, 0, iter, dxpl_cache->vec_size, nelmts, &nseq, &elmtno, off, len) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, 0, "sequence length generation failed")
+
+ /* Loop, while sequences left to process */
+ for(curr_seq = 0; curr_seq < nseq; curr_seq++) {
+ size_t curr_off; /* Offset of bytes left to process in sequence */
+ size_t curr_len; /* Length of bytes left to process in sequence */
+ size_t curr_nelmts; /* Number of elements to process in sequence */
+ uint8_t *xubuf;
+ size_t i; /* Local index variable */
+
+ /* Get the number of bytes and offset in sequence */
+ curr_len = len[curr_seq];
+ H5_CHECK_OVERFLOW(off[curr_seq], hsize_t, size_t);
+ curr_off = (size_t)off[curr_seq];
+
+ /* Decide the number of elements and position in the buffer. */
+ curr_nelmts = curr_len / dst_stride;
+ xubuf = ubuf + curr_off;
+
+ /* Copy the data into the right place. */
+ for(i = 0; i < curr_nelmts; i++) {
+ HDmemmove(xubuf, xdbuf, copy_size);
+
+ /* Update pointers */
+ xdbuf += src_stride;
+ xubuf += dst_stride;
+ } /* end for */
+ } /* end for */
+
+ /* Decrement number of elements left to process */
+ nelmts -= elmtno;
+ } /* end while */
+
+done:
+ /* Release resources, if allocated */
+ if(len && len != _len)
+ H5FL_SEQ_FREE(size_t, len);
+ if(off && off != _off)
+ H5FL_SEQ_FREE(hsize_t, off);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_compound_opt_read() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_compound_opt_write
+ *
+ * Purpose: A special optimization case when the source and
+ * destination members are a subset of each other, and
+ * the order is the same, and no conversion is needed.
+ * For example:
+ * struct source { struct destination {
+ * TYPE1 A; --> TYPE1 A;
+ * TYPE2 B; --> TYPE2 B;
+ * TYPE3 C; --> TYPE3 C;
+ * }; TYPE4 D;
+ * TYPE5 E;
+ * };
+ * or
+ * struct destination { struct source {
+ * TYPE1 A; <-- TYPE1 A;
+ * TYPE2 B; <-- TYPE2 B;
+ * TYPE3 C; <-- TYPE3 C;
+ * }; TYPE4 D;
+ * TYPE5 E;
+ * };
+ * The optimization is simply moving data to the appropriate
+ * places in the buffer.
+ *
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Raymond Lu
+ * 11 June 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_compound_opt_write(size_t nelmts, const H5D_type_info_t *type_info)
+{
+ uint8_t *xsbuf, *xdbuf; /* Source & destination pointers into dataset buffer */
+ size_t src_stride, dst_stride; /* Strides through source & destination datatypes */
+ size_t i; /* Local index variable */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_compound_opt_write)
+
+ /* Check args */
+ HDassert(nelmts > 0);
+ HDassert(type_info);
+
+ /* Initialize values for loop */
+ src_stride = type_info->src_type_size;
+ dst_stride = type_info->dst_type_size;
+
+ /* Loop until all elements are written */
+ xsbuf = (uint8_t *)type_info->tconv_buf;
+ xdbuf = (uint8_t *)type_info->tconv_buf;
+ for(i = 0; i < nelmts; i++) {
+ HDmemmove(xdbuf, xsbuf, dst_stride);
+
+ /* Update pointers */
+ xsbuf += src_stride;
+ xdbuf += dst_stride;
+ } /* end for */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5D_compound_opt_write() */
+
diff --git a/src/H5Dselect.c b/src/H5Dselect.c
index 105b4e5..947c81e 100644
--- a/src/H5Dselect.c
+++ b/src/H5Dselect.c
@@ -34,388 +34,218 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5FLprivate.h" /* Free Lists */
+
/****************/
/* Local Macros */
/****************/
+
/******************/
/* Local Typedefs */
/******************/
+
/********************/
/* Local Prototypes */
/********************/
+
/*********************/
/* Package Variables */
/*********************/
+
/*******************/
/* Local Variables */
/*******************/
/* Declare a free list to manage sequences of size_t */
-H5FL_SEQ_DEFINE_STATIC(size_t);
+H5FL_SEQ_DEFINE(size_t);
/* Declare a free list to manage sequences of hsize_t */
-H5FL_SEQ_DEFINE_STATIC(hsize_t);
+H5FL_SEQ_DEFINE(hsize_t);
+
/*-------------------------------------------------------------------------
- * Function: H5D_select_fscat
+ * Function: H5D_select_io
*
- * Purpose: Scatters dataset elements from the type conversion buffer BUF
- * to the file F where the data points are arranged according to
- * the file dataspace FILE_SPACE and stored according to
- * LAYOUT and EFL. Each element is ELMT_SIZE bytes.
- * The caller is requesting that NELMTS elements are copied.
+ * Purpose: Perform I/O directly from application memory and a file
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
- * Thursday, June 20, 2002
+ * Tuesday, November 27, 2007
*
*-------------------------------------------------------------------------
*/
-herr_t
-H5D_select_fscat (H5D_io_info_t *io_info,
- const H5S_t *space, H5S_sel_iter_t *iter, size_t nelmts,
- haddr_t chunk_addr, void *chunk/*in*/, const void *_buf)
+static herr_t
+H5D_select_io(const H5D_io_info_t *io_info, size_t elmt_size,
+ size_t nelmts, const H5S_t *file_space, const H5S_t *mem_space)
{
- const uint8_t *buf=_buf; /* Alias for pointer arithmetic */
- hsize_t _off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets */
- hsize_t *off=NULL; /* Pointer to sequence offsets */
- hsize_t mem_off; /* Offset in memory */
- size_t mem_curr_seq; /* "Current sequence" in memory */
- size_t dset_curr_seq; /* "Current sequence" in dataset */
- size_t _len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths */
- size_t *len=NULL; /* Array to store sequence lengths */
- size_t orig_mem_len, mem_len; /* Length of sequence in memory */
- size_t nseq; /* Number of sequences generated */
- size_t nelem; /* Number of elements used in sequences */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5D_select_fscat, FAIL);
-
- /* Check args */
- assert (io_info);
- assert (space);
- assert (iter);
- assert (nelmts>0);
- assert (_buf);
- assert(TRUE==H5P_isa_class(io_info->dxpl_id,H5P_DATASET_XFER));
-
- /* Allocate the vector I/O arrays */
- if(io_info->dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
- if((len = H5FL_SEQ_MALLOC(size_t,io_info->dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array");
- if((off = H5FL_SEQ_MALLOC(hsize_t,io_info->dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array");
- } /* end if */
- else {
- len=_len;
- off=_off;
- } /* end else */
-
- /* Loop until all elements are written */
- while(nelmts>0) {
- /* Get list of sequences for selection to write */
- if(H5S_SELECT_GET_SEQ_LIST(space,H5S_GET_SEQ_LIST_SORTED,iter,io_info->dxpl_cache->vec_size,nelmts,&nseq,&nelem,off,len)<0)
- HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed");
-
- /* Reset the current sequence information */
- mem_curr_seq=dset_curr_seq=0;
- orig_mem_len=mem_len=nelem*iter->elmt_size;
- mem_off=0;
-
- /* Write sequence list out */
- if((*io_info->ops.writevv)(io_info, nseq, &dset_curr_seq, len, off, (size_t)1, &mem_curr_seq, &mem_len, &mem_off, chunk_addr, chunk, buf) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error");
-
- /* Update buffer */
- buf += orig_mem_len;
-
- /* Decrement number of elements left to process */
- nelmts -= nelem;
- } /* end while */
+ H5S_sel_iter_t mem_iter; /* Memory selection iteration info */
+ hbool_t mem_iter_init = 0; /* Memory selection iteration info has been initialized */
+ H5S_sel_iter_t file_iter; /* File selection iteration info */
+ hbool_t file_iter_init = 0; /* File selection iteration info has been initialized */
+ hsize_t _mem_off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets in memory */
+ hsize_t *mem_off = NULL; /* Pointer to sequence offsets in memory */
+ hsize_t _file_off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets in the file */
+ hsize_t *file_off = NULL; /* Pointer to sequence offsets in the file */
+ size_t _mem_len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths in memory */
+ size_t *mem_len = NULL; /* Pointer to sequence lengths in memory */
+ size_t _file_len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths in the file */
+ size_t *file_len = NULL; /* Pointer to sequence lengths in the file */
+ size_t curr_mem_seq; /* Current memory sequence to operate on */
+ size_t curr_file_seq; /* Current file sequence to operate on */
+ size_t mem_nseq; /* Number of sequences generated in the file */
+ size_t file_nseq; /* Number of sequences generated in memory */
+ ssize_t tmp_file_len; /* Temporary number of bytes in file sequence */
+ herr_t ret_value = SUCCEED; /* Return value */
-done:
- if(io_info->dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
- if(len!=NULL)
- H5FL_SEQ_FREE(size_t,len);
- if(off!=NULL)
- H5FL_SEQ_FREE(hsize_t,off);
- } /* end if */
- FUNC_LEAVE_NOAPI(ret_value);
-} /* H5D_select_fscat() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_select_fgath
- *
- * Purpose: Gathers data points from file F and accumulates them in the
- * type conversion buffer BUF. The LAYOUT argument describes
- * how the data is stored on disk and EFL describes how the data
- * is organized in external files. ELMT_SIZE is the size in
- * bytes of a datum which this function treats as opaque.
- * FILE_SPACE describes the dataspace of the dataset on disk
- * and the elements that have been selected for reading (via
- * hyperslab, etc). This function will copy at most NELMTS
- * elements.
- *
- * Return: Success: Number of elements copied.
- * Failure: 0
- *
- * Programmer: Quincey Koziol
- * Monday, June 24, 2002
- *
- *-------------------------------------------------------------------------
- */
-size_t
-H5D_select_fgath (H5D_io_info_t *io_info,
- const H5S_t *space, H5S_sel_iter_t *iter, size_t nelmts,
- haddr_t chunk_addr, void *chunk/*in*/, void *_buf/*out*/)
-{
- uint8_t *buf=(uint8_t*)_buf; /* Alias for pointer arithmetic */
- hsize_t _off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets */
- hsize_t *off=NULL; /* Pointer to sequence offsets */
- hsize_t mem_off; /* Offset in memory */
- size_t mem_curr_seq; /* "Current sequence" in memory */
- size_t dset_curr_seq; /* "Current sequence" in dataset */
- size_t _len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths */
- size_t *len=NULL; /* Pointer to sequence lengths */
- size_t orig_mem_len, mem_len; /* Length of sequence in memory */
- size_t nseq; /* Number of sequences generated */
- size_t nelem; /* Number of elements used in sequences */
- size_t ret_value=nelmts; /* Return value */
-
- FUNC_ENTER_NOAPI(H5D_select_fgath, 0);
+ FUNC_ENTER_NOAPI(H5D_select_io, FAIL)
/* Check args */
- assert (io_info);
- assert (io_info->dset);
- assert (io_info->store);
- assert (space);
- assert (iter);
- assert (nelmts>0);
- assert (_buf);
+ HDassert(io_info);
+ HDassert(io_info->dset);
+ HDassert(io_info->store);
+ HDassert(TRUE == H5P_isa_class(io_info->dxpl_id, H5P_DATASET_XFER));
+ HDassert(io_info->u.rbuf);
/* Allocate the vector I/O arrays */
- if(io_info->dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
- if((len = H5FL_SEQ_MALLOC(size_t,io_info->dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate I/O length vector array");
- if((off = H5FL_SEQ_MALLOC(hsize_t,io_info->dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate I/O offset vector array");
+ if(io_info->dxpl_cache->vec_size > H5D_IO_VECTOR_SIZE) {
+ if(NULL == (mem_len = H5FL_SEQ_MALLOC(size_t,io_info->dxpl_cache->vec_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array")
+ if(NULL == (mem_off = H5FL_SEQ_MALLOC(hsize_t,io_info->dxpl_cache->vec_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array")
+ if(NULL == (file_len = H5FL_SEQ_MALLOC(size_t,io_info->dxpl_cache->vec_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array")
+ if(NULL == (file_off = H5FL_SEQ_MALLOC(hsize_t,io_info->dxpl_cache->vec_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array")
} /* end if */
else {
- len=_len;
- off=_off;
+ mem_len = _mem_len;
+ mem_off = _mem_off;
+ file_len = _file_len;
+ file_off = _file_off;
} /* end else */
- /* Loop until all elements are read */
- while(nelmts>0) {
- /* Get list of sequences for selection to read */
- if(H5S_SELECT_GET_SEQ_LIST(space,H5S_GET_SEQ_LIST_SORTED,iter,io_info->dxpl_cache->vec_size,nelmts,&nseq,&nelem,off,len)<0)
- HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, 0, "sequence length generation failed");
-
- /* Reset the current sequence information */
- mem_curr_seq=dset_curr_seq=0;
- orig_mem_len=mem_len=nelem*iter->elmt_size;
- mem_off=0;
-
- /* Read sequence list in */
- if((*io_info->ops.readvv)(io_info, nseq, &dset_curr_seq, len, off, (size_t)1,
- &mem_curr_seq, &mem_len, &mem_off, chunk_addr, chunk, buf) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, 0, "read error");
-
- /* Update buffer */
- buf += orig_mem_len;
+ /* Check for only one element in selection */
+ if(nelmts == 1) {
+ /* Get offset of first element in selections */
+ if(H5S_SELECT_OFFSET(file_space, file_off) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "can't retrieve file selection offset")
+ if(H5S_SELECT_OFFSET(mem_space, mem_off) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "can't retrieve memory selection offset")
+
+ /* Set up necessary information for I/O operation */
+ file_nseq = mem_nseq = 1;
+ curr_mem_seq = curr_file_seq = 0;
+ *file_off *= elmt_size;
+ *mem_off *= elmt_size;
+ *file_len = *mem_len = elmt_size;
+
+ /* Perform I/O on memory and file sequences */
+ if(io_info->op_type == H5D_IO_OP_READ) {
+ if((tmp_file_len = (*io_info->layout_ops.readvv)(io_info,
+ file_nseq, &curr_file_seq, file_len, file_off,
+ mem_nseq, &curr_mem_seq, mem_len, mem_off)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, FAIL, "read error")
+ } /* end if */
+ else {
+ HDassert(io_info->op_type == H5D_IO_OP_WRITE);
+ if((tmp_file_len = (*io_info->layout_ops.writevv)(io_info,
+ file_nseq, &curr_file_seq, file_len, file_off,
+ mem_nseq, &curr_mem_seq, mem_len, mem_off)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error")
+ } /* end else */
/* Decrement number of elements left to process */
- nelmts -= nelem;
- } /* end while */
-
-done:
- if(io_info->dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
- if(len!=NULL)
- H5FL_SEQ_FREE(size_t,len);
- if(off!=NULL)
- H5FL_SEQ_FREE(hsize_t,off);
- } /* end if */
- FUNC_LEAVE_NOAPI(ret_value);
-} /* H5D_select_fgath() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_select_mscat
- *
- * Purpose: Scatters NELMTS data points from the scatter buffer
- * TSCAT_BUF to the application buffer BUF. Each element is
- * ELMT_SIZE bytes and they are organized in application memory
- * according to SPACE.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Monday, July 8, 2002
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5D_select_mscat (const void *_tscat_buf, const H5S_t *space,
- H5S_sel_iter_t *iter, size_t nelmts, const H5D_dxpl_cache_t *dxpl_cache,
- void *_buf/*out*/)
-{
- uint8_t *buf=(uint8_t *)_buf; /* Get local copies for address arithmetic */
- const uint8_t *tscat_buf=(const uint8_t *)_tscat_buf;
- hsize_t _off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets */
- hsize_t *off=NULL; /* Pointer to sequence offsets */
- size_t _len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths */
- size_t *len=NULL; /* Pointer to sequence lengths */
- size_t curr_len; /* Length of bytes left to process in sequence */
- size_t nseq; /* Number of sequences generated */
- size_t curr_seq; /* Current sequence being processed */
- size_t nelem; /* Number of elements used in sequences */
- herr_t ret_value=SUCCEED; /* Number of elements scattered */
-
- FUNC_ENTER_NOAPI(H5D_select_mscat, FAIL);
-
- /* Check args */
- assert (tscat_buf);
- assert (space);
- assert (iter);
- assert (nelmts>0);
- assert (buf);
-
- /* Allocate the vector I/O arrays */
- if(dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
- if((len = H5FL_SEQ_MALLOC(size_t,dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array");
- if((off = H5FL_SEQ_MALLOC(hsize_t,dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array");
+ HDassert((tmp_file_len % elmt_size) == 0);
} /* end if */
else {
- len=_len;
- off=_off;
+ size_t mem_nelem; /* Number of elements used in memory sequences */
+ size_t file_nelem; /* Number of elements used in file sequences */
+
+ /* Initialize file iterator */
+ if(H5S_select_iter_init(&file_iter, file_space, elmt_size) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator")
+ file_iter_init = 1; /* File selection iteration info has been initialized */
+
+ /* Initialize memory iterator */
+ if(H5S_select_iter_init(&mem_iter, mem_space, elmt_size) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator")
+ mem_iter_init = 1; /* Memory selection iteration info has been initialized */
+
+ /* Initialize sequence counts */
+ curr_mem_seq = curr_file_seq = 0;
+ mem_nseq = file_nseq = 0;
+
+ /* Loop, until all bytes are processed */
+ while(nelmts > 0) {
+ /* Check if more file sequences are needed */
+ if(curr_file_seq >= file_nseq) {
+ /* Get sequences for file selection */
+ if(H5S_SELECT_GET_SEQ_LIST(file_space, H5S_GET_SEQ_LIST_SORTED, &file_iter, io_info->dxpl_cache->vec_size, nelmts, &file_nseq, &file_nelem, file_off, file_len) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed")
+
+ /* Start at the beginning of the sequences again */
+ curr_file_seq = 0;
+ } /* end if */
+
+ /* Check if more memory sequences are needed */
+ if(curr_mem_seq >= mem_nseq) {
+ /* Get sequences for memory selection */
+ if(H5S_SELECT_GET_SEQ_LIST(mem_space, 0, &mem_iter, io_info->dxpl_cache->vec_size, nelmts, &mem_nseq, &mem_nelem, mem_off, mem_len) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed")
+
+ /* Start at the beginning of the sequences again */
+ curr_mem_seq = 0;
+ } /* end if */
+
+ /* Perform I/O on memory and file sequences */
+ if(io_info->op_type == H5D_IO_OP_READ) {
+ if((tmp_file_len = (*io_info->layout_ops.readvv)(io_info,
+ file_nseq, &curr_file_seq, file_len, file_off,
+ mem_nseq, &curr_mem_seq, mem_len, mem_off)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, FAIL, "read error")
+ } /* end if */
+ else {
+ HDassert(io_info->op_type == H5D_IO_OP_WRITE);
+ if((tmp_file_len = (*io_info->layout_ops.writevv)(io_info,
+ file_nseq, &curr_file_seq, file_len, file_off,
+ mem_nseq, &curr_mem_seq, mem_len, mem_off)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error")
+ } /* end else */
+
+ /* Decrement number of elements left to process */
+ HDassert((tmp_file_len % elmt_size) == 0);
+ nelmts -= (tmp_file_len / elmt_size);
+ } /* end while */
} /* end else */
- /* Loop until all elements are written */
- while(nelmts>0) {
- /* Get list of sequences for selection to write */
- if(H5S_SELECT_GET_SEQ_LIST(space,0,iter,dxpl_cache->vec_size,nelmts,&nseq,&nelem,off,len)<0)
- HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, 0, "sequence length generation failed");
-
- /* Loop, while sequences left to process */
- for(curr_seq=0; curr_seq<nseq; curr_seq++) {
- /* Get the number of bytes in sequence */
- curr_len=len[curr_seq];
-
- HDmemcpy(buf+off[curr_seq],tscat_buf,curr_len);
-
- /* Advance offset in destination buffer */
- tscat_buf+=curr_len;
- } /* end for */
-
- /* Decrement number of elements left to process */
- nelmts -= nelem;
- } /* end while */
-
done:
- if(dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
- if(len!=NULL)
- H5FL_SEQ_FREE(size_t,len);
- if(off!=NULL)
- H5FL_SEQ_FREE(hsize_t,off);
- } /* end if */
- FUNC_LEAVE_NOAPI(ret_value);
-} /* H5D_select_mscat() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5D_select_mgath
- *
- * Purpose: Gathers dataset elements from application memory BUF and
- * copies them into the gather buffer TGATH_BUF.
- * Each element is ELMT_SIZE bytes and arranged in application
- * memory according to SPACE.
- * The caller is requesting that at most NELMTS be gathered.
- *
- * Return: Success: Number of elements copied.
- * Failure: 0
- *
- * Programmer: Quincey Koziol
- * Monday, June 24, 2002
- *
- *-------------------------------------------------------------------------
- */
-size_t
-H5D_select_mgath (const void *_buf, const H5S_t *space,
- H5S_sel_iter_t *iter, size_t nelmts, const H5D_dxpl_cache_t *dxpl_cache,
- void *_tgath_buf/*out*/)
-{
- const uint8_t *buf=(const uint8_t *)_buf; /* Get local copies for address arithmetic */
- uint8_t *tgath_buf=(uint8_t *)_tgath_buf;
- hsize_t _off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets */
- hsize_t *off=NULL; /* Pointer to sequence offsets */
- size_t _len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths */
- size_t *len=NULL; /* Pointer to sequence lengths */
- size_t curr_len; /* Length of bytes left to process in sequence */
- size_t nseq; /* Number of sequences generated */
- size_t curr_seq; /* Current sequence being processed */
- size_t nelem; /* Number of elements used in sequences */
- size_t ret_value=nelmts; /* Number of elements gathered */
-
- FUNC_ENTER_NOAPI(H5D_select_mgath, 0);
-
- /* Check args */
- assert (buf);
- assert (space);
- assert (iter);
- assert (nelmts>0);
- assert (tgath_buf);
-
- /* Allocate the vector I/O arrays */
- if(dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
- if((len = H5FL_SEQ_MALLOC(size_t,dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate I/O length vector array");
- if((off = H5FL_SEQ_MALLOC(hsize_t,dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate I/O offset vector array");
- } /* end if */
- else {
- len=_len;
- off=_off;
- } /* end else */
-
- /* Loop until all elements are written */
- while(nelmts>0) {
- /* Get list of sequences for selection to write */
- if(H5S_SELECT_GET_SEQ_LIST(space,0,iter,dxpl_cache->vec_size,nelmts,&nseq,&nelem,off,len)<0)
- HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, 0, "sequence length generation failed");
-
- /* Loop, while sequences left to process */
- for(curr_seq=0; curr_seq<nseq; curr_seq++) {
- /* Get the number of bytes in sequence */
- curr_len=len[curr_seq];
-
- HDmemcpy(tgath_buf,buf+off[curr_seq],curr_len);
-
- /* Advance offset in gather buffer */
- tgath_buf+=curr_len;
- } /* end for */
-
- /* Decrement number of elements left to process */
- nelmts -= nelem;
- } /* end while */
+ /* Release file selection iterator */
+ if(file_iter_init)
+ if(H5S_SELECT_ITER_RELEASE(&file_iter) < 0)
+ HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator")
-done:
- if(dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
- if(len!=NULL)
- H5FL_SEQ_FREE(size_t,len);
- if(off!=NULL)
- H5FL_SEQ_FREE(hsize_t,off);
- } /* end if */
- FUNC_LEAVE_NOAPI(ret_value);
-} /* H5D_select_mgath() */
+ /* Release memory selection iterator */
+ if(mem_iter_init)
+ if(H5S_SELECT_ITER_RELEASE(&mem_iter) < 0)
+ HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator")
+
+ /* Release vector arrays, if allocated */
+ if(file_len && file_len != _file_len)
+ H5FL_SEQ_FREE(size_t, file_len);
+ if(file_off && file_off != _file_off)
+ H5FL_SEQ_FREE(hsize_t, file_off);
+ if(mem_len && mem_len != _mem_len)
+ H5FL_SEQ_FREE(size_t, mem_len);
+ if(mem_off && mem_off != _mem_off)
+ H5FL_SEQ_FREE(hsize_t, mem_off);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_select_io() */
/*-------------------------------------------------------------------------
@@ -431,134 +261,21 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5D_select_read(H5D_io_info_t *io_info,
- size_t nelmts, size_t elmt_size,
- const H5S_t *file_space, const H5S_t *mem_space,
- haddr_t addr, void *chunk/*in*/,
- void *buf/*out*/)
+H5D_select_read(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space)
{
- H5S_sel_iter_t mem_iter; /* Memory selection iteration info */
- hbool_t mem_iter_init=0; /* Memory selection iteration info has been initialized */
- H5S_sel_iter_t file_iter; /* File selection iteration info */
- hbool_t file_iter_init=0; /* File selection iteration info has been initialized */
- hsize_t _mem_off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets in memory */
- hsize_t *mem_off=NULL; /* Pointer to sequence offsets in memory */
- hsize_t _file_off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets in the file */
- hsize_t *file_off=NULL; /* Pointer to sequence offsets in the file */
- size_t _mem_len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths in memory */
- size_t *mem_len=NULL; /* Pointer to sequence lengths in memory */
- size_t _file_len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths in the file */
- size_t *file_len=NULL; /* Pointer to sequence lengths in the file */
- size_t mem_nseq; /* Number of sequences generated in the file */
- size_t file_nseq; /* Number of sequences generated in memory */
- size_t mem_nelem; /* Number of elements used in memory sequences */
- size_t file_nelem; /* Number of elements used in file sequences */
- size_t curr_mem_seq; /* Current memory sequence to operate on */
- size_t curr_file_seq; /* Current file sequence to operate on */
- ssize_t tmp_file_len; /* Temporary number of bytes in file sequence */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5D_select_read, FAIL);
+ herr_t ret_value = SUCCEED; /* Return value */
- /* Check args */
- assert(io_info);
- assert(io_info->dset);
- assert(io_info->dxpl_cache);
- assert(io_info->store);
- assert(buf);
- assert(TRUE==H5P_isa_class(io_info->dxpl_id,H5P_DATASET_XFER));
-
- /* Initialize file iterator */
- if (H5S_select_iter_init(&file_iter, file_space, elmt_size)<0)
- HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator");
- file_iter_init=1; /* File selection iteration info has been initialized */
-
- /* Initialize memory iterator */
- if (H5S_select_iter_init(&mem_iter, mem_space, elmt_size)<0)
- HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator");
- mem_iter_init=1; /* Memory selection iteration info has been initialized */
-
- /* Allocate the vector I/O arrays */
- if(io_info->dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
- if((mem_len = H5FL_SEQ_MALLOC(size_t,io_info->dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array");
- if((mem_off = H5FL_SEQ_MALLOC(hsize_t,io_info->dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array");
- if((file_len = H5FL_SEQ_MALLOC(size_t,io_info->dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array");
- if((file_off = H5FL_SEQ_MALLOC(hsize_t,io_info->dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array");
- } /* end if */
- else {
- mem_len=_mem_len;
- mem_off=_mem_off;
- file_len=_file_len;
- file_off=_file_off;
- } /* end else */
-
- /* Initialize sequence counts */
- curr_mem_seq=curr_file_seq=0;
- mem_nseq=file_nseq=0;
-
- /* Loop, until all bytes are processed */
- while(nelmts>0) {
- /* Check if more file sequences are needed */
- if(curr_file_seq>=file_nseq) {
- /* Get sequences for file selection */
- if(H5S_SELECT_GET_SEQ_LIST(file_space,H5S_GET_SEQ_LIST_SORTED,&file_iter,io_info->dxpl_cache->vec_size,nelmts,&file_nseq,&file_nelem,file_off,file_len)<0)
- HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed");
-
- /* Start at the beginning of the sequences again */
- curr_file_seq=0;
- } /* end if */
-
- /* Check if more memory sequences are needed */
- if(curr_mem_seq>=mem_nseq) {
- /* Get sequences for memory selection */
- if(H5S_SELECT_GET_SEQ_LIST(mem_space,0,&mem_iter,io_info->dxpl_cache->vec_size,nelmts,&mem_nseq,&mem_nelem,mem_off,mem_len)<0)
- HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed");
-
- /* Start at the beginning of the sequences again */
- curr_mem_seq=0;
- } /* end if */
+ FUNC_ENTER_NOAPI(H5D_select_read, FAIL)
- /* Read file sequences into current memory sequence */
- if ((tmp_file_len=(*io_info->ops.readvv)(io_info,
- file_nseq, &curr_file_seq, file_len, file_off,
- mem_nseq, &curr_mem_seq, mem_len, mem_off,
- addr, chunk, buf))<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, FAIL, "read error");
-
- /* Decrement number of elements left to process */
- assert((tmp_file_len%elmt_size)==0);
- nelmts-=(tmp_file_len/elmt_size);
- } /* end while */
+ /* Call generic selection operation */
+ H5_CHECK_OVERFLOW(nelmts, hsize_t, size_t);
+ if(H5D_select_io(io_info, type_info->src_type_size, (size_t)nelmts,
+ file_space, mem_space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, FAIL, "read error")
done:
- /* Release file selection iterator */
- if(file_iter_init) {
- if (H5S_SELECT_ITER_RELEASE(&file_iter)<0)
- HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator");
- } /* end if */
-
- /* Release memory selection iterator */
- if(mem_iter_init) {
- if (H5S_SELECT_ITER_RELEASE(&mem_iter)<0)
- HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator");
- } /* end if */
-
- /* Free vector arrays */
- if(io_info->dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
- if(file_len!=NULL)
- H5FL_SEQ_FREE(size_t,file_len);
- if(file_off!=NULL)
- H5FL_SEQ_FREE(hsize_t,file_off);
- if(mem_len!=NULL)
- H5FL_SEQ_FREE(size_t,mem_len);
- if(mem_off!=NULL)
- H5FL_SEQ_FREE(hsize_t,mem_off);
- } /* end if */
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_select_read() */
@@ -575,133 +292,20 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5D_select_write(H5D_io_info_t *io_info,
- size_t nelmts, size_t elmt_size,
- const H5S_t *file_space, const H5S_t *mem_space,
- haddr_t addr, void *chunk/*in*/,
- const void *buf/*out*/)
+H5D_select_write(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
+ hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space)
{
- H5S_sel_iter_t mem_iter; /* Memory selection iteration info */
- hbool_t mem_iter_init=0; /* Memory selection iteration info has been initialized */
- H5S_sel_iter_t file_iter; /* File selection iteration info */
- hbool_t file_iter_init=0; /* File selection iteration info has been initialized */
- hsize_t _mem_off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets in memory */
- hsize_t *mem_off=NULL; /* Pointer to sequence offsets in memory */
- hsize_t _file_off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets in the file */
- hsize_t *file_off=NULL; /* Pointer to sequence offsets in the file */
- size_t _mem_len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths in memory */
- size_t *mem_len=NULL; /* Pointer to sequence lengths in memory */
- size_t _file_len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths in the file */
- size_t *file_len=NULL; /* Pointer to sequence lengths in the file */
- size_t mem_nseq; /* Number of sequences generated in the file */
- size_t file_nseq; /* Number of sequences generated in memory */
- size_t mem_nelem; /* Number of elements used in memory sequences */
- size_t file_nelem; /* Number of elements used in file sequences */
- size_t curr_mem_seq; /* Current memory sequence to operate on */
- size_t curr_file_seq; /* Current file sequence to operate on */
- ssize_t tmp_file_len; /* Temporary number of bytes in file sequence */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5D_select_write, FAIL);
+ herr_t ret_value = SUCCEED; /* Return value */
- /* Check args */
- assert(io_info);
- assert(io_info->dset);
- assert(io_info->store);
- assert(TRUE==H5P_isa_class(io_info->dxpl_id,H5P_DATASET_XFER));
- assert(buf);
-
- /* Allocate the vector I/O arrays */
- if(io_info->dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
- if((mem_len = H5FL_SEQ_MALLOC(size_t,io_info->dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array");
- if((mem_off = H5FL_SEQ_MALLOC(hsize_t,io_info->dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array");
- if((file_len = H5FL_SEQ_MALLOC(size_t,io_info->dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array");
- if((file_off = H5FL_SEQ_MALLOC(hsize_t,io_info->dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array");
- } /* end if */
- else {
- mem_len=_mem_len;
- mem_off=_mem_off;
- file_len=_file_len;
- file_off=_file_off;
- } /* end else */
-
- /* Initialize file iterator */
- if (H5S_select_iter_init(&file_iter, file_space, elmt_size)<0)
- HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator");
- file_iter_init=1; /* File selection iteration info has been initialized */
-
- /* Initialize memory iterator */
- if (H5S_select_iter_init(&mem_iter, mem_space, elmt_size)<0)
- HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator");
- mem_iter_init=1; /* Memory selection iteration info has been initialized */
-
- /* Initialize sequence counts */
- curr_mem_seq=curr_file_seq=0;
- mem_nseq=file_nseq=0;
-
- /* Loop, until all bytes are processed */
- while(nelmts>0) {
- /* Check if more file sequences are needed */
- if(curr_file_seq>=file_nseq) {
- /* Get sequences for file selection */
- if(H5S_SELECT_GET_SEQ_LIST(file_space,H5S_GET_SEQ_LIST_SORTED,&file_iter,io_info->dxpl_cache->vec_size,nelmts,&file_nseq,&file_nelem,file_off,file_len)<0)
- HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed");
-
- /* Start at the beginning of the sequences again */
- curr_file_seq=0;
- } /* end if */
-
- /* Check if more memory sequences are needed */
- if(curr_mem_seq>=mem_nseq) {
- /* Get sequences for memory selection */
- if(H5S_SELECT_GET_SEQ_LIST(mem_space,0,&mem_iter,io_info->dxpl_cache->vec_size,nelmts,&mem_nseq,&mem_nelem,mem_off,mem_len)<0)
- HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed");
-
- /* Start at the beginning of the sequences again */
- curr_mem_seq=0;
- } /* end if */
+ FUNC_ENTER_NOAPI(H5D_select_write, FAIL)
- /* Write memory sequences into file sequences */
- if ((tmp_file_len=(*io_info->ops.writevv)(io_info,
- file_nseq, &curr_file_seq, file_len, file_off,
- mem_nseq, &curr_mem_seq, mem_len, mem_off,
- addr, chunk, buf))<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error");
-
- /* Decrement number of elements left to process */
- assert((tmp_file_len%elmt_size)==0);
- nelmts-=(tmp_file_len/elmt_size);
- } /* end while */
+ /* Call generic selection operation */
+ H5_CHECK_OVERFLOW(nelmts, hsize_t, size_t);
+ if(H5D_select_io(io_info, type_info->dst_type_size, (size_t)nelmts,
+ file_space, mem_space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error")
done:
- /* Release file selection iterator */
- if(file_iter_init) {
- if (H5S_SELECT_ITER_RELEASE(&file_iter)<0)
- HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator");
- } /* end if */
-
- /* Release memory selection iterator */
- if(mem_iter_init) {
- if (H5S_SELECT_ITER_RELEASE(&mem_iter)<0)
- HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator");
- } /* end if */
-
- /* Free vector arrays */
- if(io_info->dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
- if(file_len!=NULL)
- H5FL_SEQ_FREE(size_t,file_len);
- if(file_off!=NULL)
- H5FL_SEQ_FREE(hsize_t,file_off);
- if(mem_len!=NULL)
- H5FL_SEQ_FREE(size_t,mem_len);
- if(mem_off!=NULL)
- H5FL_SEQ_FREE(hsize_t,mem_off);
- } /* end if */
-
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_select_write() */
diff --git a/src/H5Dtest.c b/src/H5Dtest.c
index cf4d5b6..f7124f0 100644
--- a/src/H5Dtest.c
+++ b/src/H5Dtest.c
@@ -79,19 +79,19 @@ herr_t
H5D_layout_version_test(hid_t did, unsigned *version)
{
H5D_t *dset; /* Pointer to dataset to query */
- herr_t ret_value=SUCCEED; /* return value */
+ herr_t ret_value = SUCCEED; /* return value */
- FUNC_ENTER_NOAPI(H5D_layout_version_test, FAIL);
+ FUNC_ENTER_NOAPI(H5D_layout_version_test, FAIL)
/* Check args */
- if (NULL==(dset=H5I_object_verify(did, H5I_DATASET)))
+ if(NULL == (dset = (H5D_t *)H5I_object_verify(did, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
if(version)
- *version=dset->shared->layout.version;
+ *version = dset->shared->layout.version;
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* H5D_layout_version_test() */
@@ -118,20 +118,20 @@ herr_t
H5D_layout_contig_size_test(hid_t did, hsize_t *size)
{
H5D_t *dset; /* Pointer to dataset to query */
- herr_t ret_value=SUCCEED; /* return value */
+ herr_t ret_value = SUCCEED; /* return value */
- FUNC_ENTER_NOAPI(H5D_layout_contig_size_test, FAIL);
+ FUNC_ENTER_NOAPI(H5D_layout_contig_size_test, FAIL)
/* Check args */
- if (NULL==(dset=H5I_object_verify(did, H5I_DATASET)))
+ if(NULL == (dset = (H5D_t *)H5I_object_verify(did, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
if(size) {
- assert(dset->shared->layout.type==H5D_CONTIGUOUS);
- *size=dset->shared->layout.u.contig.size;
+ HDassert(dset->shared->layout.type == H5D_CONTIGUOUS);
+ *size = dset->shared->layout.u.contig.size;
} /* end if */
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* H5D_layout_contig_size_test() */
diff --git a/src/H5E.c b/src/H5E.c
index 72f0619..6eb7768 100644
--- a/src/H5E.c
+++ b/src/H5E.c
@@ -230,7 +230,7 @@ H5E_init_interface(void)
HDsnprintf(lib_vers, sizeof(lib_vers), "%u.%u.%u%s", H5_VERS_MAJOR, H5_VERS_MINOR, H5_VERS_RELEASE, (HDstrlen(H5_VERS_SUBRELEASE) > 0 ? "-"H5_VERS_SUBRELEASE : ""));
if(NULL == (cls = H5E_register_class(H5E_CLS_NAME, H5E_CLS_LIB_NAME, lib_vers)))
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "class initialization failed")
- if((H5E_ERR_CLS_g = H5I_register(H5I_ERROR_CLASS, cls)) < 0)
+ if((H5E_ERR_CLS_g = H5I_register(H5I_ERROR_CLASS, cls, FALSE)) < 0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error class")
/* Include the automatically generated error code initialization */
@@ -275,11 +275,11 @@ H5E_term_interface(void)
if(n > 0) {
/* Clear any outstanding error stacks */
if(nstk > 0)
- H5I_clear_type(H5I_ERROR_STACK, FALSE);
+ H5I_clear_type(H5I_ERROR_STACK, FALSE, FALSE);
/* Clear all the error classes */
if(ncls > 0) {
- H5I_clear_type(H5I_ERROR_CLASS, FALSE);
+ H5I_clear_type(H5I_ERROR_CLASS, FALSE, FALSE);
/* Reset the HDF5 error class, if its been closed */
if(H5I_nmembers(H5I_ERROR_CLASS) == 0)
@@ -288,7 +288,7 @@ H5E_term_interface(void)
/* Clear all the error messages */
if(nmsg > 0) {
- H5I_clear_type(H5I_ERROR_MSG, FALSE);
+ H5I_clear_type(H5I_ERROR_MSG, FALSE, FALSE);
/* Reset the HDF5 error messages, if they've been closed */
if(H5I_nmembers(H5I_ERROR_MSG) == 0) {
@@ -390,7 +390,7 @@ H5Eregister_class(const char *cls_name, const char *lib_name, const char *versio
HGOTO_ERROR(H5E_ERROR, H5E_CANTCREATE, FAIL, "can't create error class")
/* Register the new error class to get an ID for it */
- if((ret_value = H5I_register(H5I_ERROR_CLASS, cls)) < 0)
+ if((ret_value = H5I_register(H5I_ERROR_CLASS, cls, TRUE)) < 0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error class")
done:
@@ -471,7 +471,7 @@ H5Eunregister_class(hid_t class_id)
* Decrement the counter on the dataset. It will be freed if the count
* reaches zero.
*/
- if(H5I_dec_ref(class_id) < 0)
+ if(H5I_dec_ref(class_id, TRUE) < 0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTDEC, FAIL, "unable to decrement ref count on error class")
done:
@@ -501,7 +501,7 @@ H5E_unregister_class(H5E_cls_t *cls)
/* Iterate over all the messages and delete those in this error class */
/* (Ignore return value, since callback isn't designed to return a particular object) */
- (void)H5I_search(H5I_ERROR_MSG, H5E_close_msg_cb, cls);
+ (void)H5I_search(H5I_ERROR_MSG, H5E_close_msg_cb, cls, FALSE);
/* Free error class structure */
if(cls->cls_name)
@@ -510,7 +510,7 @@ H5E_unregister_class(H5E_cls_t *cls)
H5MM_xfree((void*)cls->lib_name);
if(cls->lib_vers)
H5MM_xfree((void*)cls->lib_vers);
- H5FL_FREE(H5E_cls_t, cls);
+ (void)H5FL_FREE(H5E_cls_t, cls);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5E_unregister_class() */
@@ -539,7 +539,7 @@ H5Eget_class_name(hid_t class_id, char *name, size_t size)
H5TRACE3("Zs", "i*sz", class_id, name, size);
/* Get the error class */
- if(NULL == (cls = H5I_object_verify(class_id, H5I_ERROR_CLASS)))
+ if(NULL == (cls = (H5E_cls_t *)H5I_object_verify(class_id, H5I_ERROR_CLASS)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error class ID")
/* Retrieve the class name */
@@ -615,9 +615,12 @@ H5E_close_msg_cb(void *obj_ptr, hid_t obj_id, void *key)
HDassert(err_msg);
/* Close the message if it is in the class being closed */
- if(err_msg->cls == cls)
- if(H5I_dec_ref(obj_id) < 0)
- HGOTO_ERROR(H5E_ERROR, H5E_CANTDEC, FAIL, "unable to decrement ref count on error message")
+ if(err_msg->cls == cls) {
+ if(H5E_close_msg(err_msg) < 0)
+ HGOTO_ERROR(H5E_ERROR, H5E_CANTCLOSEOBJ, FAIL, "unable to close error message")
+ if(NULL == H5I_remove(obj_id))
+ HGOTO_ERROR(H5E_ERROR, H5E_CANTREMOVE, FAIL, "unable to remove error message")
+ } /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -649,7 +652,7 @@ H5Eclose_msg(hid_t err_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an error class")
/* Decrement the counter. It will be freed if the count reaches zero. */
- if(H5I_dec_ref(err_id) < 0)
+ if(H5I_dec_ref(err_id, TRUE) < 0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTDEC, FAIL, "unable to decrement ref count on error message")
done:
@@ -681,7 +684,7 @@ H5E_close_msg(H5E_msg_t *err)
H5MM_xfree((void*)err->msg);
/* Don't free err->cls here */
- H5FL_FREE(H5E_msg_t, err);
+ (void)H5FL_FREE(H5E_msg_t, err);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5E_close_msg() */
@@ -716,7 +719,7 @@ H5Ecreate_msg(hid_t class_id, H5E_type_t msg_type, const char *msg_str)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "message is NULL")
/* Get the error class */
- if(NULL == (cls = H5I_object_verify(class_id, H5I_ERROR_CLASS)))
+ if(NULL == (cls = (H5E_cls_t *)H5I_object_verify(class_id, H5I_ERROR_CLASS)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error class ID")
/* Create the new error message object */
@@ -724,7 +727,7 @@ H5Ecreate_msg(hid_t class_id, H5E_type_t msg_type, const char *msg_str)
HGOTO_ERROR(H5E_ERROR, H5E_CANTCREATE, FAIL, "can't create error message")
/* Register the new error class to get an ID for it */
- if((ret_value = H5I_register(H5I_ERROR_MSG, msg)) < 0)
+ if((ret_value = H5I_register(H5I_ERROR_MSG, msg, TRUE)) < 0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
done:
@@ -797,7 +800,7 @@ H5Eget_msg(hid_t msg_id, H5E_type_t *type, char *msg_str, size_t size)
H5TRACE4("Zs", "i*Et*sz", msg_id, type, msg_str, size);
/* Get the message object */
- if(NULL == (msg = H5I_object_verify(msg_id, H5I_ERROR_MSG)))
+ if(NULL == (msg = (H5E_msg_t *)H5I_object_verify(msg_id, H5I_ERROR_MSG)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error message ID")
/* Get the message's text */
@@ -838,7 +841,7 @@ H5Ecreate_stack(void)
H5E_set_default_auto(stk);
/* Register the stack */
- if((ret_value = H5I_register(H5I_ERROR_STACK, stk)) < 0)
+ if((ret_value = H5I_register(H5I_ERROR_STACK, stk, TRUE)) < 0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't create error stack")
done:
@@ -874,7 +877,7 @@ H5Eget_current_stack(void)
HGOTO_ERROR(H5E_ERROR, H5E_CANTCREATE, FAIL, "can't create error stack")
/* Register the stack */
- if((ret_value = H5I_register(H5I_ERROR_STACK, stk)) < 0)
+ if((ret_value = H5I_register(H5I_ERROR_STACK, stk, TRUE)) < 0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't create error stack")
done:
@@ -905,7 +908,7 @@ H5E_get_current_stack(void)
FUNC_ENTER_NOAPI_NOINIT(H5E_get_current_stack)
/* Get a pointer to the current error stack */
- if(NULL == (current_stack = H5E_get_my_stack ())) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */
+ if(NULL == (current_stack = H5E_get_my_stack())) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */
HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, NULL, "can't get current error stack")
/* Allocate a new error stack */
@@ -922,13 +925,13 @@ H5E_get_current_stack(void)
new_error = &(estack_copy->slot[u]);
/* Increment the IDs to indicate that they are used in this stack */
- if(H5I_inc_ref(current_error->cls_id) < 0)
+ if(H5I_inc_ref(current_error->cls_id, FALSE) < 0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, NULL, "unable to increment ref count on error class")
new_error->cls_id = current_error->cls_id;
- if(H5I_inc_ref(current_error->maj_num) < 0)
+ if(H5I_inc_ref(current_error->maj_num, FALSE) < 0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, NULL, "unable to increment ref count on error message")
new_error->maj_num = current_error->maj_num;
- if(H5I_inc_ref(current_error->min_num) < 0)
+ if(H5I_inc_ref(current_error->min_num, FALSE) < 0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, NULL, "unable to increment ref count on error message")
new_error->min_num = current_error->min_num;
if(NULL == (new_error->func_name = H5MM_xstrdup(current_error->func_name)))
@@ -953,7 +956,7 @@ H5E_get_current_stack(void)
done:
if(ret_value == NULL)
if(estack_copy)
- H5FL_FREE(H5E_t, estack_copy);
+ (void)H5FL_FREE(H5E_t, estack_copy);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5E_get_current_stack() */
@@ -981,7 +984,7 @@ H5Eset_current_stack(hid_t err_stack)
H5TRACE1("e", "i", err_stack);
if(err_stack != H5E_DEFAULT) {
- if(NULL == (estack = H5I_object_verify(err_stack, H5I_ERROR_STACK)))
+ if(NULL == (estack = (H5E_t *)H5I_object_verify(err_stack, H5I_ERROR_STACK)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID")
/* Set the current error stack */
@@ -1035,14 +1038,14 @@ H5E_set_current_stack(H5E_t *estack)
new_error = &(estack->slot[u]);
/* Increment the IDs to indicate that they are used in this stack */
- if(H5I_inc_ref(new_error->cls_id) < 0)
- HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, FAIL, "unable to decrement ref count on error class")
+ if(H5I_inc_ref(new_error->cls_id, FALSE) < 0)
+ HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, FAIL, "unable to increment ref count on error class")
current_error->cls_id = new_error->cls_id;
- if(H5I_inc_ref(new_error->maj_num) < 0)
- HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, FAIL, "unable to decrement ref count on error class")
+ if(H5I_inc_ref(new_error->maj_num, FALSE) < 0)
+ HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, FAIL, "unable to increment ref count on error class")
current_error->maj_num = new_error->maj_num;
- if(H5I_inc_ref(new_error->min_num) < 0)
- HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, FAIL, "unable to decrement ref count on error class")
+ if(H5I_inc_ref(new_error->min_num, FALSE) < 0)
+ HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, FAIL, "unable to increment ref count on error class")
current_error->min_num = new_error->min_num;
if(NULL == (current_error->func_name = H5MM_xstrdup(new_error->func_name)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
@@ -1087,7 +1090,7 @@ H5Eclose_stack(hid_t stack_id)
* Decrement the counter on the error stack. It will be freed if the count
* reaches zero.
*/
- if(H5I_dec_ref(stack_id)<0)
+ if(H5I_dec_ref(stack_id, TRUE)<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTDEC, FAIL, "unable to decrement ref count on error stack")
} /* end if */
@@ -1120,7 +1123,7 @@ H5E_close_stack(H5E_t *estack)
H5E_clear_stack(estack);
/* Free the stack structure */
- H5FL_FREE(H5E_t, estack);
+ (void)H5FL_FREE(H5E_t, estack);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5E_close_stack() */
@@ -1158,7 +1161,7 @@ H5Eget_num(hid_t error_stack_id)
H5E_clear_stack(NULL);
/* Get the error stack to operate on */
- if(NULL == (estack = H5I_object_verify(error_stack_id, H5I_ERROR_STACK)))
+ if(NULL == (estack = (H5E_t *)H5I_object_verify(error_stack_id, H5I_ERROR_STACK)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID")
} /* end else */
@@ -1226,7 +1229,7 @@ H5Epop(hid_t err_stack, size_t count)
H5E_clear_stack(NULL);
/* Get the error stack to operate on */
- if(NULL == (estack = H5I_object_verify(err_stack, H5I_ERROR_STACK)))
+ if(NULL == (estack = (H5E_t *)H5I_object_verify(err_stack, H5I_ERROR_STACK)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID")
} /* end else */
@@ -1289,18 +1292,23 @@ H5Epush2(hid_t err_stack, const char *file, const char *func, unsigned line,
H5E_clear_stack(NULL);
/* Get the error stack to operate on */
- if(NULL == (estack = H5I_object_verify(err_stack, H5I_ERROR_STACK)))
+ if(NULL == (estack = (H5E_t *)H5I_object_verify(err_stack, H5I_ERROR_STACK)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID")
} /* end else */
/* Check for mis-matches in major & minor error classes */
- if(NULL == (maj_ptr = H5I_object_verify(maj_id, H5I_ERROR_MSG)))
+ if(NULL == (maj_ptr = (H5E_msg_t *)H5I_object_verify(maj_id, H5I_ERROR_MSG)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error message ID")
- if(NULL == (min_ptr = H5I_object_verify(min_id, H5I_ERROR_MSG)))
+ if(NULL == (min_ptr = (H5E_msg_t *)H5I_object_verify(min_id, H5I_ERROR_MSG)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error message ID")
if(maj_ptr->cls != min_ptr->cls)
HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "major and minor errors not from same error class")
+/* Note that the variable-argument parsing for the format is identical in
+ * the H5E_printf_stack() routine - correct errors and make changes in both
+ * places. -QAK
+ */
+
/* Format the description */
va_start(ap, fmt);
@@ -1387,7 +1395,7 @@ H5Eclear2(hid_t err_stack)
/* Only clear the error stack if it's not the default stack */
H5E_clear_stack(NULL);
- if(NULL == (estack = H5I_object_verify(err_stack, H5I_ERROR_STACK)))
+ if(NULL == (estack = (H5E_t *)H5I_object_verify(err_stack, H5I_ERROR_STACK)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID")
} /* end else */
@@ -1434,7 +1442,7 @@ H5Eprint2(hid_t err_stack, FILE *stream)
/* Only clear the error stack if it's not the default stack */
H5E_clear_stack(NULL);
- if(NULL == (estack = H5I_object_verify(err_stack, H5I_ERROR_STACK)))
+ if(NULL == (estack = (H5E_t *)H5I_object_verify(err_stack, H5I_ERROR_STACK)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID")
} /* end else */
@@ -1480,7 +1488,7 @@ H5Ewalk2(hid_t err_stack, H5E_direction_t direction, H5E_walk2_t stack_func, voi
/* Only clear the error stack if it's not the default stack */
H5E_clear_stack(NULL);
- if(NULL == (estack = H5I_object_verify(err_stack, H5I_ERROR_STACK)))
+ if(NULL == (estack = (H5E_t *)H5I_object_verify(err_stack, H5I_ERROR_STACK)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID")
} /* end else */
@@ -1525,7 +1533,7 @@ H5Eget_auto2(hid_t estack_id, H5E_auto2_t *func, void **client_data)
HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack")
} /* end if */
else
- if(NULL == (estack = H5I_object_verify(estack_id, H5I_ERROR_STACK)))
+ if(NULL == (estack = (H5E_t *)H5I_object_verify(estack_id, H5I_ERROR_STACK)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID")
/* Get the automatic error reporting information */
@@ -1577,7 +1585,7 @@ H5Eset_auto2(hid_t estack_id, H5E_auto2_t func, void *client_data)
HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack")
} /* end if */
else
- if(NULL == (estack = H5I_object_verify(estack_id, H5I_ERROR_STACK)))
+ if(NULL == (estack = (H5E_t *)H5I_object_verify(estack_id, H5I_ERROR_STACK)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID")
/* Set the automatic error reporting information */
@@ -1620,7 +1628,7 @@ H5Eauto_is_v2(hid_t estack_id, unsigned *is_stack)
HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack")
} /* end if */
else
- if(NULL == (estack = H5I_object_verify(estack_id, H5I_ERROR_STACK)))
+ if(NULL == (estack = (H5E_t *)H5I_object_verify(estack_id, H5I_ERROR_STACK)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID")
/* Check if the error stack reporting function is the "newer" stack type */
diff --git a/src/H5EA.c b/src/H5EA.c
new file mode 100644
index 0000000..eadb9c0
--- /dev/null
+++ b/src/H5EA.c
@@ -0,0 +1,969 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5EA.c
+ * Jun 17 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: Implements an "extensible array" for storing elements
+ * in an array whose high bounds can extend and shrink.
+ *
+ * Please see the documentation in:
+ * doc/html/TechNotes/ExtensibleArray.html for a full
+ * description of how they work, etc.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/**********************/
+/* Module Declaration */
+/**********************/
+
+#define H5EA_MODULE
+
+
+/***********************/
+/* Other Packages Used */
+/***********************/
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5EApkg.h" /* Extensible Arrays */
+#include "H5FLprivate.h" /* Free Lists */
+#include "H5Vprivate.h" /* Vector functions */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+/* HDF5 API Entered variable */
+/* (move to H5.c when new FUNC_ENTER macros in actual use -QAK) */
+hbool_t H5_api_entered_g = FALSE;
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* Declare a free list to manage the H5EA_t struct */
+H5FL_DEFINE_STATIC(H5EA_t);
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA_create
+ *
+ * Purpose: Creates a new empty extensible array in the file.
+ *
+ * Return: Pointer to earray wrapper on success
+ * NULL on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jun 17 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PRIV, ERR,
+H5EA_t *, NULL, NULL,
+H5EA_create(H5F_t *f, hid_t dxpl_id, const H5EA_create_t *cparam))
+
+ /* Local variables */
+ H5EA_t *ea = NULL; /* Pointer to new extensible array */
+ H5EA_hdr_t *hdr = NULL; /* The extensible array header information */
+ haddr_t ea_addr; /* Array header address */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Called\n", FUNC);
+#endif /* QAK */
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(cparam);
+
+ /* Create extensible array header */
+ if(HADDR_UNDEF == (ea_addr = H5EA__hdr_create(f, dxpl_id, cparam)))
+ H5E_THROW(H5E_CANTINIT, "can't create extensible array header")
+
+ /* Allocate extensible array wrapper */
+ if(NULL == (ea = H5FL_MALLOC(H5EA_t)))
+ H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array info")
+
+ /* Lock the array header into memory */
+ if(NULL == (hdr = (H5EA_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_EARRAY_HDR, ea_addr, cparam->cls, NULL, H5AC_WRITE)))
+ H5E_THROW(H5E_CANTPROTECT, "unable to load extensible array header")
+
+ /* Point extensible array wrapper at header and bump it's ref count */
+ ea->hdr = hdr;
+ if(H5EA__hdr_incr(ea->hdr) < 0)
+ H5E_THROW(H5E_CANTINC, "can't increment reference count on shared array header")
+
+ /* Increment # of files using this array header */
+ if(H5EA__hdr_fuse_incr(ea->hdr) < 0)
+ H5E_THROW(H5E_CANTINC, "can't increment file reference count on shared array header")
+
+ /* Set file pointer for this array open context */
+ ea->f = f;
+
+ /* Set the return value */
+ ret_value = ea;
+
+CATCH
+
+ if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_EARRAY_HDR, ea_addr, hdr, H5AC__NO_FLAGS_SET) < 0)
+ H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array header")
+ if(!ret_value)
+ if(ea && H5EA_close(ea, dxpl_id) < 0)
+ H5E_THROW(H5E_CLOSEERROR, "unable to close extensible array")
+
+END_FUNC(PRIV) /* end H5EA_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA_open
+ *
+ * Purpose: Opens an existing extensible array in the file.
+ *
+ * Return: Pointer to array wrapper on success
+ * NULL on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Aug 28 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PRIV, ERR,
+H5EA_t *, NULL, NULL,
+H5EA_open(H5F_t *f, hid_t dxpl_id, haddr_t ea_addr, const H5EA_class_t *cls))
+
+ /* Local variables */
+ H5EA_t *ea = NULL; /* Pointer to new extensible array wrapper */
+ H5EA_hdr_t *hdr = NULL; /* The extensible array header information */
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(H5F_addr_defined(ea_addr));
+ HDassert(cls);
+
+ /* Load the array header into memory */
+#ifdef QAK
+HDfprintf(stderr, "%s: ea_addr = %a\n", FUNC, ea_addr);
+#endif /* QAK */
+ if(NULL == (hdr = (H5EA_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_EARRAY_HDR, ea_addr, cls, NULL, H5AC_READ)))
+ H5E_THROW(H5E_CANTPROTECT, "unable to load extensible array header, address = %llu", (unsigned long_long)ea_addr)
+
+ /* Check for pending array deletion */
+ if(hdr->pending_delete)
+ H5E_THROW(H5E_CANTOPENOBJ, "can't open extensible array pending deletion")
+
+ /* Create fractal heap info */
+ if(NULL == (ea = H5FL_MALLOC(H5EA_t)))
+ H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array info")
+
+ /* Point extensible array wrapper at header */
+ ea->hdr = hdr;
+ if(H5EA__hdr_incr(ea->hdr) < 0)
+ H5E_THROW(H5E_CANTINC, "can't increment reference count on shared array header")
+
+ /* Increment # of files using this array header */
+ if(H5EA__hdr_fuse_incr(ea->hdr) < 0)
+ H5E_THROW(H5E_CANTINC, "can't increment file reference count on shared array header")
+
+ /* Set file pointer for this array open context */
+ ea->f = f;
+
+ /* Set the return value */
+ ret_value = ea;
+
+CATCH
+
+ if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_EARRAY_HDR, ea_addr, hdr, H5AC__NO_FLAGS_SET) < 0)
+ H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array header")
+ if(!ret_value)
+ if(ea && H5EA_close(ea, dxpl_id) < 0)
+ H5E_THROW(H5E_CLOSEERROR, "unable to close extensible array")
+
+END_FUNC(PRIV) /* end H5EA_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA_get_nelmts
+ *
+ * Purpose: Query the current number of elements in array
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Aug 21 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PRIV, NOERR,
+herr_t, SUCCEED, -,
+H5EA_get_nelmts(const H5EA_t *ea, hsize_t *nelmts))
+
+ /* Local variables */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Called\n", FUNC);
+#endif /* QAK */
+
+ /*
+ * Check arguments.
+ */
+ HDassert(ea);
+ HDassert(nelmts);
+
+ /* Retrieve the max. index set */
+ *nelmts = ea->hdr->stats.max_idx_set;
+
+END_FUNC(PRIV) /* end H5EA_get_nelmts() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA_get_addr
+ *
+ * Purpose: Query the address of the array
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Aug 21 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PRIV, NOERR,
+herr_t, SUCCEED, -,
+H5EA_get_addr(const H5EA_t *ea, haddr_t *addr))
+
+ /* Local variables */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Called\n", FUNC);
+#endif /* QAK */
+
+ /*
+ * Check arguments.
+ */
+ HDassert(ea);
+ HDassert(ea->hdr);
+ HDassert(addr);
+
+ /* Retrieve the address of the extensible array's header */
+ *addr = ea->hdr->addr;
+
+END_FUNC(PRIV) /* end H5EA_get_addr() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA_set
+ *
+ * Purpose: Set an element of an extensible array
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 9 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PRIV, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA_set(const H5EA_t *ea, hid_t dxpl_id, hsize_t idx, const void *elmt))
+
+ /* Local variables */
+ H5EA_hdr_t *hdr = ea->hdr; /* Header for EA */
+ H5EA_iblock_t *iblock = NULL; /* Pointer to index block for EA */
+ H5EA_sblock_t *sblock = NULL; /* Pointer to super block for EA */
+ H5EA_dblock_t *dblock = NULL; /* Pointer to data block for EA */
+ H5EA_dblk_page_t *dblk_page = NULL; /* Pointer to data block page for EA */
+ unsigned iblock_cache_flags = H5AC__NO_FLAGS_SET; /* Flags to unprotecting index block */
+ unsigned sblock_cache_flags = H5AC__NO_FLAGS_SET; /* Flags to unprotecting super block */
+ unsigned dblock_cache_flags = H5AC__NO_FLAGS_SET; /* Flags to unprotecting data block */
+ unsigned dblk_page_cache_flags = H5AC__NO_FLAGS_SET; /* Flags to unprotecting data block page */
+ hbool_t hdr_dirty = FALSE; /* Whether header information changed */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Called\n", FUNC);
+HDfprintf(stderr, "%s: Index %Hu\n", FUNC, idx);
+#endif /* QAK */
+
+ /*
+ * Check arguments.
+ */
+ HDassert(ea);
+ HDassert(ea->hdr);
+
+ /* Set the shared array header's file context for this operation */
+ hdr->f = ea->f;
+
+ /* Check if we should create the index block */
+ if(!H5F_addr_defined(hdr->idx_blk_addr)) {
+#ifdef QAK
+HDfprintf(stderr, "%s: Index block address not defined!\n", FUNC, idx);
+#endif /* QAK */
+ /* Create the index block */
+ hdr->idx_blk_addr = H5EA__iblock_create(hdr, dxpl_id);
+ if(!H5F_addr_defined(hdr->idx_blk_addr))
+ H5E_THROW(H5E_CANTCREATE, "unable to create index block")
+
+ /* Increment count of elements "realized" */
+ hdr->stats.nelmts += hdr->cparam.idx_blk_elmts;
+
+ /* Mark the header dirty */
+ hdr_dirty = TRUE;
+ } /* end if */
+#ifdef QAK
+HDfprintf(stderr, "%s: Index block address is: %a\n", FUNC, hdr->idx_blk_addr);
+#endif /* QAK */
+
+ /* Protect index block */
+ if(NULL == (iblock = H5EA__iblock_protect(hdr, dxpl_id, H5AC_WRITE)))
+ H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array index block, address = %llu", (unsigned long_long)hdr->idx_blk_addr)
+
+ /* Check if element is in index block */
+ if(idx < hdr->cparam.idx_blk_elmts) {
+ /* Set element in index block */
+ HDmemcpy(((uint8_t *)iblock->elmts) + (hdr->cparam.cls->nat_elmt_size * idx), elmt, hdr->cparam.cls->nat_elmt_size);
+ iblock_cache_flags |= H5AC__DIRTIED_FLAG;
+ } /* end if */
+ else {
+ unsigned sblk_idx; /* Which superblock does this index fall in? */
+ size_t dblk_idx; /* Data block index */
+ hsize_t elmt_idx; /* Offset of element in super block */
+
+ /* Get super block index where element is located */
+ sblk_idx = H5EA__dblock_sblk_idx(hdr, idx);
+#ifdef QAK
+HDfprintf(stderr, "%s: sblk_idx = %u, iblock->nsblks = %Zu\n", FUNC, sblk_idx, iblock->nsblks);
+#endif /* QAK */
+
+ /* Adjust index to offset in super block */
+ elmt_idx = idx - (hdr->cparam.idx_blk_elmts + hdr->sblk_info[sblk_idx].start_idx);
+#ifdef QAK
+HDfprintf(stderr, "%s: after adjusting for super block elements, elmt_idx = %Hu\n", FUNC, elmt_idx);
+#endif /* QAK */
+
+ /* Check for data block containing element address in the index block */
+ if(sblk_idx < iblock->nsblks) {
+#ifdef QAK
+HDfprintf(stderr, "%s: Element in data block pointed to by address in index block\n", FUNC);
+#endif /* QAK */
+ /* Compute the data block index in index block */
+ dblk_idx = (size_t)(hdr->sblk_info[sblk_idx].start_dblk + (elmt_idx / hdr->sblk_info[sblk_idx].dblk_nelmts));
+#ifdef QAK
+HDfprintf(stderr, "%s: dblk_idx = %u, iblock->ndblk_addrs = %Zu\n", FUNC, dblk_idx, iblock->ndblk_addrs);
+#endif /* QAK */
+ HDassert(dblk_idx < iblock->ndblk_addrs);
+
+ /* Check if the data block has been allocated on disk yet */
+ if(!H5F_addr_defined(iblock->dblk_addrs[dblk_idx])) {
+ haddr_t dblk_addr; /* Address of data block created */
+ hsize_t dblk_off; /* Offset of data block in array */
+
+ /* Create data block */
+ dblk_off = hdr->sblk_info[sblk_idx].start_idx + (dblk_idx * hdr->sblk_info[sblk_idx].dblk_nelmts);
+ dblk_addr = H5EA__dblock_create(hdr, dxpl_id, dblk_off, hdr->sblk_info[sblk_idx].dblk_nelmts);
+ if(!H5F_addr_defined(dblk_addr))
+ H5E_THROW(H5E_CANTCREATE, "unable to create extensible array data block")
+
+ /* Set data block address in index block */
+ iblock->dblk_addrs[dblk_idx] = dblk_addr;
+ iblock_cache_flags |= H5AC__DIRTIED_FLAG;
+
+ /* Increment count of elements "realized" and actual data blocks created */
+ hdr->stats.ndata_blks++;
+ hdr->stats.nelmts += hdr->sblk_info[sblk_idx].dblk_nelmts;
+ hdr_dirty = TRUE;
+ } /* end if */
+
+ /* Protect data block */
+ if(NULL == (dblock = H5EA__dblock_protect(hdr, dxpl_id, iblock->dblk_addrs[dblk_idx], hdr->sblk_info[sblk_idx].dblk_nelmts, H5AC_WRITE)))
+ H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array data block, address = %llu", (unsigned long_long)iblock->dblk_addrs[dblk_idx])
+
+ /* Adjust index to offset in data block */
+ elmt_idx %= hdr->sblk_info[sblk_idx].dblk_nelmts;
+
+ /* Set element in data block */
+ HDmemcpy(((uint8_t *)dblock->elmts) + (hdr->cparam.cls->nat_elmt_size * elmt_idx), elmt, hdr->cparam.cls->nat_elmt_size);
+ dblock_cache_flags |= H5AC__DIRTIED_FLAG;
+ } /* end if */
+ else {
+ unsigned sblk_off; /* Offset of super block in index block array of super blocks */
+ void *elmts; /* Buffer for elements */
+
+ /* Calculate offset of super block in index block's array */
+ sblk_off = sblk_idx - iblock->nsblks;
+
+ /* Check if the super block has been allocated on disk yet */
+ if(!H5F_addr_defined(iblock->sblk_addrs[sblk_off])) {
+ haddr_t sblk_addr; /* Address of data block created */
+
+ /* Create super block */
+ sblk_addr = H5EA__sblock_create(hdr, dxpl_id, sblk_idx);
+#ifdef QAK
+HDfprintf(stderr, "%s: New super block address is: %a\n", FUNC, sblk_addr);
+#endif /* QAK */
+ if(!H5F_addr_defined(sblk_addr))
+ H5E_THROW(H5E_CANTCREATE, "unable to create extensible array super block")
+
+ /* Set super block address in index block */
+ iblock->sblk_addrs[sblk_off] = sblk_addr;
+ iblock_cache_flags |= H5AC__DIRTIED_FLAG;
+
+ /* Increment count of actual super blocks created */
+ hdr->stats.nsuper_blks++;
+ hdr_dirty = TRUE;
+ } /* end if */
+
+ /* Protect super block */
+ if(NULL == (sblock = H5EA__sblock_protect(hdr, dxpl_id, iblock->sblk_addrs[sblk_off], sblk_idx, H5AC_WRITE)))
+ H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array super block, address = %llu", (unsigned long_long)iblock->sblk_addrs[sblk_off])
+
+ /* Compute the data block index in super block */
+ dblk_idx = (size_t)(elmt_idx / sblock->dblk_nelmts);
+#ifdef QAK
+HDfprintf(stderr, "%s: dblk_idx = %u, sblock->ndblks = %Zu\n", FUNC, dblk_idx, sblock->ndblks);
+#endif /* QAK */
+ HDassert(dblk_idx < sblock->ndblks);
+
+ /* Check if the data block has been allocated on disk yet */
+ if(!H5F_addr_defined(sblock->dblk_addrs[dblk_idx])) {
+ haddr_t dblk_addr; /* Address of data block created */
+ hsize_t dblk_off; /* Offset of data block in array */
+
+ /* Create data block */
+ dblk_off = hdr->sblk_info[sblk_idx].start_idx + (dblk_idx * hdr->sblk_info[sblk_idx].dblk_nelmts);
+ dblk_addr = H5EA__dblock_create(hdr, dxpl_id, dblk_off, sblock->dblk_nelmts);
+ if(!H5F_addr_defined(dblk_addr))
+ H5E_THROW(H5E_CANTCREATE, "unable to create extensible array data block")
+
+ /* Set data block address in index block */
+ sblock->dblk_addrs[dblk_idx] = dblk_addr;
+ sblock_cache_flags |= H5AC__DIRTIED_FLAG;
+
+ /* Increment count of elements "realized" and actual data blocks created */
+ hdr->stats.ndata_blks++;
+ hdr->stats.nelmts += hdr->sblk_info[sblk_idx].dblk_nelmts;
+ hdr_dirty = TRUE;
+ } /* end if */
+
+#ifdef QAK
+if(sblock->dblk_npages)
+ HDfprintf(stderr, "%s: Check 1.0: elmt_idx = %Hu\n", FUNC, elmt_idx);
+#endif /* QAK */
+ /* Adjust index to offset in data block */
+ elmt_idx %= sblock->dblk_nelmts;
+#ifdef QAK
+if(sblock->dblk_npages)
+ HDfprintf(stderr, "%s: Check 2.0: elmt_idx = %Hu\n", FUNC, elmt_idx);
+#endif /* QAK */
+
+ /* Check if the data block is paged */
+ if(sblock->dblk_npages) {
+ haddr_t dblk_page_addr; /* Address of data block page */
+ size_t page_idx; /* Index of page within data block */
+ size_t page_init_idx; /* Index of 'page init' bit */
+
+ /* Compute page index */
+ page_idx = (size_t)elmt_idx / hdr->dblk_page_nelmts;
+
+ /* Compute 'page init' index */
+ page_init_idx = (dblk_idx * sblock->dblk_npages) + page_idx;
+
+ /* Adjust index to offset in data block page */
+ elmt_idx %= hdr->dblk_page_nelmts;
+
+ /* Compute data block page address */
+ dblk_page_addr = sblock->dblk_addrs[dblk_idx] +
+ H5EA_DBLOCK_PREFIX_SIZE(sblock) +
+ (page_idx * sblock->dblk_page_size);
+#ifdef QAK
+HDfprintf(stderr, "%s: sblock->addr = %a\n", FUNC, sblock->addr);
+HDfprintf(stderr, "%s: sblock->dblk_addrs[%Zu] = %a\n", FUNC, dblk_idx, sblock->dblk_addrs[dblk_idx]);
+HDfprintf(stderr, "%s: H5EA_DBLOCK_PREFIX_SIZE(sblock) = %u\n", FUNC, (unsigned)H5EA_DBLOCK_PREFIX_SIZE(sblock));
+HDfprintf(stderr, "%s: sblock->page_init[%Zu] = %t\n", FUNC, page_init_idx, H5V_bit_get(sblock->page_init, page_init_idx));
+HDfprintf(stderr, "%s: page_idx = %Zu, elmt_idx = %Hu, dblk_page_addr = %a\n", FUNC, page_idx, elmt_idx, dblk_page_addr);
+HDfprintf(stderr, "%s: sblock->dblk_page_size = %Zu\n", FUNC, sblock->dblk_page_size);
+#endif /* QAK */
+
+ /* Check if page has been initialized yet */
+ if(!H5V_bit_get(sblock->page_init, page_init_idx)) {
+ /* Create the data block page */
+ if(H5EA__dblk_page_create(hdr, dxpl_id, dblk_page_addr) < 0)
+ H5E_THROW(H5E_CANTCREATE, "unable to create data block page")
+
+ /* Mark data block page as initialized in super block */
+ H5V_bit_set(sblock->page_init, page_init_idx, TRUE);
+ sblock_cache_flags |= H5AC__DIRTIED_FLAG;
+ } /* end if */
+
+ /* Protect data block page */
+ if(NULL == (dblk_page = H5EA__dblk_page_protect(hdr, dxpl_id, dblk_page_addr, H5AC_WRITE)))
+ H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array data block page, address = %llu", (unsigned long_long)dblk_page_addr)
+
+ /* Set pointer to elements */
+ elmts = dblk_page->elmts;
+ } /* end if */
+ else {
+ /* Protect data block */
+ if(NULL == (dblock = H5EA__dblock_protect(hdr, dxpl_id, sblock->dblk_addrs[dblk_idx], sblock->dblk_nelmts, H5AC_WRITE)))
+ H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array data block, address = %llu", (unsigned long_long)sblock->dblk_addrs[dblk_idx])
+
+ /* Set pointer to elements */
+ elmts = dblock->elmts;
+ } /* end else */
+
+ /* Set element in data block */
+ HDmemcpy(((uint8_t *)elmts) + (hdr->cparam.cls->nat_elmt_size * elmt_idx), elmt, hdr->cparam.cls->nat_elmt_size);
+
+ /* Mark data block/data block page as dirty now */
+ if(sblock->dblk_npages)
+ dblk_page_cache_flags |= H5AC__DIRTIED_FLAG;
+ else
+ dblock_cache_flags |= H5AC__DIRTIED_FLAG;
+ } /* end else */
+ } /* end else */
+
+ /* Update max. element set in array, if appropriate */
+#ifdef QAK
+HDfprintf(stderr, "%s: idx = %Hu, hdr->stats.max_idx_set = %Hu\n", FUNC, idx, hdr->stats.max_idx_set);
+#endif /* QAK */
+ if(idx >= hdr->stats.max_idx_set) {
+ hdr->stats.max_idx_set = idx + 1;
+ hdr_dirty = TRUE;
+ } /* end if */
+
+CATCH
+ /* Check for header modified */
+ if(hdr_dirty)
+ if(H5EA__hdr_modified(hdr) < 0)
+ H5E_THROW(H5E_CANTMARKDIRTY, "unable to mark extensible array header as modified")
+
+ /* Release resources */
+ if(iblock && H5EA__iblock_unprotect(iblock, dxpl_id, iblock_cache_flags) < 0)
+ H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array index block")
+ if(sblock && H5EA__sblock_unprotect(sblock, dxpl_id, sblock_cache_flags) < 0)
+ H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array super block")
+ if(dblock && H5EA__dblock_unprotect(dblock, dxpl_id, dblock_cache_flags) < 0)
+ H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array data block")
+ if(dblk_page && H5EA__dblk_page_unprotect(dblk_page, dxpl_id, dblk_page_cache_flags) < 0)
+ H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array data block page")
+
+END_FUNC(PRIV) /* end H5EA_set() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA_get
+ *
+ * Purpose: Get an element of an extensible array
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 11 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PRIV, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA_get(const H5EA_t *ea, hid_t dxpl_id, hsize_t idx, void *elmt))
+
+ /* Local variables */
+ H5EA_hdr_t *hdr = ea->hdr; /* Header for EA */
+ H5EA_iblock_t *iblock = NULL; /* Pointer to index block for EA */
+ H5EA_sblock_t *sblock = NULL; /* Pointer to super block for EA */
+ H5EA_dblock_t *dblock = NULL; /* Pointer to data block for EA */
+ H5EA_dblk_page_t *dblk_page = NULL; /* Pointer to data block page for EA */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Called\n", FUNC);
+HDfprintf(stderr, "%s: Index %Hu\n", FUNC, idx);
+#endif /* QAK */
+
+ /*
+ * Check arguments.
+ */
+ HDassert(ea);
+ HDassert(ea->hdr);
+
+ /* Set the shared array header's file context for this operation */
+ hdr->f = ea->f;
+
+ /* Check for element beyond max. element in array */
+ if(idx >= hdr->stats.max_idx_set) {
+#ifdef QAK
+HDfprintf(stderr, "%s: Element beyond max. index set, hdr->stats.max_idx_set = %Hu, idx = %Hu\n", FUNC, hdr->stats.max_idx_set, idx);
+#endif /* QAK */
+ /* Call the class's 'fill' callback */
+ if((hdr->cparam.cls->fill)(elmt, (size_t)1) < 0)
+ H5E_THROW(H5E_CANTSET, "can't set element to class's fill value")
+ } /* end if */
+ else {
+#ifdef QAK
+HDfprintf(stderr, "%s: Index block address is: %a\n", FUNC, hdr->idx_blk_addr);
+#endif /* QAK */
+
+ /* Protect index block */
+ if(NULL == (iblock = H5EA__iblock_protect(hdr, dxpl_id, H5AC_READ)))
+ H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array index block, address = %llu", (unsigned long_long)hdr->idx_blk_addr)
+
+ /* Check if element is in index block */
+ if(idx < hdr->cparam.idx_blk_elmts) {
+ /* Get element from index block */
+ HDmemcpy(elmt, ((uint8_t *)iblock->elmts) + (hdr->cparam.cls->nat_elmt_size * idx), hdr->cparam.cls->nat_elmt_size);
+ } /* end if */
+ else {
+ unsigned sblk_idx; /* Which superblock does this index fall in? */
+ size_t dblk_idx; /* Data block index */
+ hsize_t elmt_idx; /* Offset of element in super block */
+
+ /* Get super block index where element is located */
+ sblk_idx = H5EA__dblock_sblk_idx(hdr, idx);
+
+ /* Adjust index to offset in super block */
+ elmt_idx = idx - (hdr->cparam.idx_blk_elmts + hdr->sblk_info[sblk_idx].start_idx);
+#ifdef QAK
+HDfprintf(stderr, "%s: after adjusting for super block elements, elmt_idx = %Hu\n", FUNC, elmt_idx);
+#endif /* QAK */
+
+ /* Check for data block containing element address in the index block */
+ if(sblk_idx < iblock->nsblks) {
+#ifdef QAK
+HDfprintf(stderr, "%s: Element in data block pointed to by address in index block\n", FUNC);
+#endif /* QAK */
+ /* Compute the data block index in index block */
+ dblk_idx = (size_t)(hdr->sblk_info[sblk_idx].start_dblk + (elmt_idx / hdr->sblk_info[sblk_idx].dblk_nelmts));
+#ifdef QAK
+HDfprintf(stderr, "%s: dblk_idx = %u\n", FUNC, dblk_idx);
+#endif /* QAK */
+ HDassert(dblk_idx < iblock->ndblk_addrs);
+
+ /* Check if the data block has been allocated on disk yet */
+ if(!H5F_addr_defined(iblock->dblk_addrs[dblk_idx])) {
+ /* Call the class's 'fill' callback */
+ if((hdr->cparam.cls->fill)(elmt, (size_t)1) < 0)
+ H5E_THROW(H5E_CANTSET, "can't set element to class's fill value")
+ } /* end if */
+ else {
+ /* Protect data block */
+ if(NULL == (dblock = H5EA__dblock_protect(hdr, dxpl_id, iblock->dblk_addrs[dblk_idx], hdr->sblk_info[sblk_idx].dblk_nelmts, H5AC_READ)))
+ H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array data block, address = %llu", (unsigned long_long)iblock->dblk_addrs[dblk_idx])
+
+ /* Adjust index to offset in data block */
+ elmt_idx %= hdr->sblk_info[sblk_idx].dblk_nelmts;
+
+ /* Retrieve element from data block */
+ HDmemcpy(elmt, ((uint8_t *)dblock->elmts) + (hdr->cparam.cls->nat_elmt_size * elmt_idx), hdr->cparam.cls->nat_elmt_size);
+ } /* end else */
+ } /* end if */
+ else {
+ unsigned sblk_off; /* Offset of super block in index block array of super blocks */
+
+ /* Calculate offset of super block in index block's array */
+ sblk_off = sblk_idx - iblock->nsblks;
+
+ /* Check if the super block has been allocated on disk yet */
+ if(!H5F_addr_defined(iblock->sblk_addrs[sblk_off])) {
+ /* Call the class's 'fill' callback */
+ if((hdr->cparam.cls->fill)(elmt, (size_t)1) < 0)
+ H5E_THROW(H5E_CANTSET, "can't set element to class's fill value")
+ } /* end if */
+ else {
+ /* Protect super block */
+ if(NULL == (sblock = H5EA__sblock_protect(hdr, dxpl_id, iblock->sblk_addrs[sblk_off], sblk_idx, H5AC_READ)))
+ H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array super block, address = %llu", (unsigned long_long)iblock->sblk_addrs[sblk_off])
+
+ /* Compute the data block index in super block */
+ dblk_idx = (size_t)(elmt_idx / sblock->dblk_nelmts);
+#ifdef QAK
+HDfprintf(stderr, "%s: dblk_idx = %u, sblock->ndblks = %Zu\n", FUNC, dblk_idx, sblock->ndblks);
+#endif /* QAK */
+ HDassert(dblk_idx < sblock->ndblks);
+
+ /* Check if the data block has been allocated on disk yet */
+ if(!H5F_addr_defined(sblock->dblk_addrs[dblk_idx])) {
+ /* Call the class's 'fill' callback */
+ if((hdr->cparam.cls->fill)(elmt, (size_t)1) < 0)
+ H5E_THROW(H5E_CANTSET, "can't set element to class's fill value")
+ } /* end if */
+ else {
+ void *elmts; /* Buffer for elements */
+
+#ifdef QAK
+if(sblock->dblk_npages)
+ HDfprintf(stderr, "%s: Check 1.0: elmt_idx = %Hu\n", FUNC, elmt_idx);
+#endif /* QAK */
+ /* Adjust index to offset in data block */
+ elmt_idx %= sblock->dblk_nelmts;
+#ifdef QAK
+if(sblock->dblk_npages)
+ HDfprintf(stderr, "%s: Check 2.0: elmt_idx = %Hu\n", FUNC, elmt_idx);
+#endif /* QAK */
+
+ /* Check if the data block is paged */
+ if(sblock->dblk_npages) {
+ size_t page_idx; /* Index of page within data block */
+ size_t page_init_idx; /* Index of 'page init' bit */
+
+ /* Compute page index */
+ page_idx = (size_t)elmt_idx / hdr->dblk_page_nelmts;
+
+ /* Compute 'page init' index */
+ page_init_idx = (dblk_idx * sblock->dblk_npages) + page_idx;
+
+#ifdef QAK
+HDfprintf(stderr, "%s: sblock->addr = %a\n", FUNC, sblock->addr);
+HDfprintf(stderr, "%s: sblock->dblk_addrs[%Zu] = %a\n", FUNC, dblk_idx, sblock->dblk_addrs[dblk_idx]);
+HDfprintf(stderr, "%s: H5EA_DBLOCK_PREFIX_SIZE(sblock) = %u\n", FUNC, (unsigned)H5EA_DBLOCK_PREFIX_SIZE(sblock));
+HDfprintf(stderr, "%s: sblock->page_init[%Zu] = %t\n", FUNC, page_init_idx, H5V_bit_get(sblock->page_init, page_init_idx));
+HDfprintf(stderr, "%s: page_idx = %Zu\n", FUNC, page_idx);
+HDfprintf(stderr, "%s: sblock->dblk_page_size = %Zu\n", FUNC, sblock->dblk_page_size);
+#endif /* QAK */
+
+ /* Check if page has been initialized yet */
+ if(!H5V_bit_get(sblock->page_init, page_init_idx)) {
+ /* Call the class's 'fill' callback */
+ if((hdr->cparam.cls->fill)(elmt, (size_t)1) < 0)
+ H5E_THROW(H5E_CANTSET, "can't set element to class's fill value")
+
+ /* We've retrieved the value, leave now */
+ H5_LEAVE(SUCCEED)
+ } /* end if */
+ else {
+ haddr_t dblk_page_addr; /* Address of data block page */
+
+ /* Adjust index to offset in data block page */
+ elmt_idx %= hdr->dblk_page_nelmts;
+
+ /* Compute data block page address */
+ dblk_page_addr = sblock->dblk_addrs[dblk_idx] +
+ H5EA_DBLOCK_PREFIX_SIZE(sblock) +
+ (page_idx * sblock->dblk_page_size);
+#ifdef QAK
+HDfprintf(stderr, "%s: elmt_idx = %Hu, dblk_page_addr = %a\n", FUNC, elmt_idx, dblk_page_addr);
+#endif /* QAK */
+
+ /* Protect data block page */
+ if(NULL == (dblk_page = H5EA__dblk_page_protect(hdr, dxpl_id, dblk_page_addr, H5AC_READ)))
+ H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array data block page, address = %llu", (unsigned long_long)dblk_page_addr)
+
+ /* Set pointer to elements */
+ elmts = dblk_page->elmts;
+ } /* end else */
+ } /* end if */
+ else {
+ /* Protect data block */
+ if(NULL == (dblock = H5EA__dblock_protect(hdr, dxpl_id, sblock->dblk_addrs[dblk_idx], sblock->dblk_nelmts, H5AC_READ)))
+ H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array data block, address = %llu", (unsigned long_long)sblock->dblk_addrs[dblk_idx])
+
+ /* Set pointer to elements */
+ elmts = dblock->elmts;
+ } /* end else */
+
+ /* Retrieve element from data block */
+ HDmemcpy(elmt, ((uint8_t *)elmts) + (hdr->cparam.cls->nat_elmt_size * elmt_idx), hdr->cparam.cls->nat_elmt_size);
+ } /* end else */
+ } /* end else */
+ } /* end else */
+ } /* end else */
+ } /* end else */
+
+CATCH
+ if(iblock && H5EA__iblock_unprotect(iblock, dxpl_id, H5AC__NO_FLAGS_SET) < 0)
+ H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array index block")
+ if(sblock && H5EA__sblock_unprotect(sblock, dxpl_id, H5AC__NO_FLAGS_SET) < 0)
+ H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array super block")
+ if(dblock && H5EA__dblock_unprotect(dblock, dxpl_id, H5AC__NO_FLAGS_SET) < 0)
+ H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array data block")
+ if(dblk_page && H5EA__dblk_page_unprotect(dblk_page, dxpl_id, H5AC__NO_FLAGS_SET) < 0)
+ H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array data block page")
+
+END_FUNC(PRIV) /* end H5EA_set() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA_close
+ *
+ * Purpose: Close an extensible array
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Aug 21 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PRIV, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA_close(H5EA_t *ea, hid_t dxpl_id))
+
+ /* Local variables */
+ hbool_t pending_delete = FALSE; /* Whether the array is pending deletion */
+ haddr_t ea_addr = HADDR_UNDEF; /* Address of array (for deletion) */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Called\n", FUNC);
+#endif /* QAK */
+
+ /*
+ * Check arguments.
+ */
+ HDassert(ea);
+
+ /* Decrement file reference & check if this is the last open extensible array using the shared array header */
+ if(0 == H5EA__hdr_fuse_decr(ea->hdr)) {
+ /* Set the shared array header's file context for this operation */
+ ea->hdr->f = ea->f;
+
+ /* Shut down anything that can't be put in the header's 'flush' callback */
+
+ /* Check for pending array deletion */
+ if(ea->hdr->pending_delete) {
+ /* Set local info, so array deletion can occur after decrementing the
+ * header's ref count
+ */
+ pending_delete = TRUE;
+ ea_addr = ea->hdr->addr;
+ } /* end if */
+ } /* end if */
+
+ /* Decrement the reference count on the array header */
+ /* (don't put in H5EA_hdr_fuse_decr() as the array header may be evicted
+ * immediately -QAK)
+ */
+ if(H5EA__hdr_decr(ea->hdr) < 0)
+ H5E_THROW(H5E_CANTDEC, "can't decrement reference count on shared array header")
+
+ /* Check for pending array deletion */
+ if(pending_delete) {
+ H5EA_hdr_t *hdr; /* Another pointer to extensible array header */
+
+ /* Lock the array header into memory */
+ if(NULL == (hdr = (H5EA_hdr_t *)H5AC_protect(ea->f, dxpl_id, H5AC_EARRAY_HDR, ea_addr, NULL, NULL, H5AC_WRITE)))
+ H5E_THROW(H5E_CANTLOAD, "unable to load extensible array header")
+
+ /* Set the shared array header's file context for this operation */
+ hdr->f = ea->f;
+
+ /* Delete array, starting with header (unprotects header) */
+ if(H5EA__hdr_delete(hdr, dxpl_id) < 0)
+ H5E_THROW(H5E_CANTDELETE, "unable to delete extensible array")
+ } /* end if */
+
+ /* Release the extensible array wrapper */
+ (void)H5FL_FREE(H5EA_t, ea);
+
+CATCH
+
+END_FUNC(PRIV) /* end H5EA_close() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA_delete
+ *
+ * Purpose: Delete an extensible array
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Aug 28 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PRIV, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA_delete(H5F_t *f, hid_t dxpl_id, haddr_t ea_addr))
+
+ /* Local variables */
+ H5EA_hdr_t *hdr = NULL; /* The fractal heap header information */
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(H5F_addr_defined(ea_addr));
+
+ /* Lock the array header into memory */
+#ifdef QAK
+HDfprintf(stderr, "%s: ea_addr = %a\n", FUNC, ea_addr);
+#endif /* QAK */
+ if(NULL == (hdr = (H5EA_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_EARRAY_HDR, ea_addr, NULL, NULL, H5AC_WRITE)))
+ H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array header, address = %llu", (unsigned long_long)ea_addr)
+
+ /* Check for files using shared array header */
+ if(hdr->file_rc)
+ hdr->pending_delete = TRUE;
+ else {
+ /* Set the shared array header's file context for this operation */
+ hdr->f = f;
+
+ /* Delete array now, starting with header (unprotects header) */
+ if(H5EA__hdr_delete(hdr, dxpl_id) < 0)
+ H5E_THROW(H5E_CANTDELETE, "unable to delete extensible array")
+ hdr = NULL;
+ } /* end if */
+
+CATCH
+
+ /* Unprotect the header, if an error occurred */
+ if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_EARRAY_HDR, ea_addr, hdr, H5AC__NO_FLAGS_SET) < 0)
+ H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array header")
+
+END_FUNC(PRIV) /* end H5EA_delete() */
+
diff --git a/src/H5EAcache.c b/src/H5EAcache.c
new file mode 100644
index 0000000..a3c9f87
--- /dev/null
+++ b/src/H5EAcache.c
@@ -0,0 +1,1883 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5EAcache.c
+ * Aug 26 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: Implement extensible array metadata cache methods.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/**********************/
+/* Module Declaration */
+/**********************/
+
+#define H5EA_MODULE
+
+
+/***********************/
+/* Other Packages Used */
+/***********************/
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5EApkg.h" /* Extensible Arrays */
+#include "H5MFprivate.h" /* File memory management */
+#include "H5Vprivate.h" /* Vectors and arrays */
+#include "H5WBprivate.h" /* Wrapped Buffers */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+/* Fractal heap format version #'s */
+#define H5EA_HDR_VERSION 0 /* Header */
+#define H5EA_IBLOCK_VERSION 0 /* Index block */
+#define H5EA_SBLOCK_VERSION 0 /* Super block */
+#define H5EA_DBLOCK_VERSION 0 /* Data block */
+
+/* Size of stack buffer for serialization buffers */
+#define H5EA_HDR_BUF_SIZE 512
+#define H5EA_IBLOCK_BUF_SIZE 512
+#define H5EA_SBLOCK_BUF_SIZE 512
+#define H5EA_DBLOCK_BUF_SIZE 512
+#define H5EA_DBLK_PAGE_BUF_SIZE 512
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+/* Metadata cache (H5AC) callbacks */
+static H5EA_hdr_t *H5EA__cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata, void *udata2);
+static herr_t H5EA__cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5EA_hdr_t *hdr, unsigned * flags_ptr);
+static herr_t H5EA__cache_hdr_clear(H5F_t *f, H5EA_hdr_t *hdr, hbool_t destroy);
+static herr_t H5EA__cache_hdr_size(const H5F_t *f, const H5EA_hdr_t *hdr, size_t *size_ptr);
+static herr_t H5EA__cache_hdr_dest(H5F_t *f, H5EA_hdr_t *hdr);
+static H5EA_iblock_t *H5EA__cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata, void *udata2);
+static herr_t H5EA__cache_iblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5EA_iblock_t *iblock, unsigned * flags_ptr);
+static herr_t H5EA__cache_iblock_clear(H5F_t *f, H5EA_iblock_t *iblock, hbool_t destroy);
+static herr_t H5EA__cache_iblock_size(const H5F_t *f, const H5EA_iblock_t *iblock, size_t *size_ptr);
+static herr_t H5EA__cache_iblock_dest(H5F_t *f, H5EA_iblock_t *iblock);
+static H5EA_sblock_t *H5EA__cache_sblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata, void *udata2);
+static herr_t H5EA__cache_sblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5EA_sblock_t *sblock, unsigned * flags_ptr);
+static herr_t H5EA__cache_sblock_clear(H5F_t *f, H5EA_sblock_t *sblock, hbool_t destroy);
+static herr_t H5EA__cache_sblock_size(const H5F_t *f, const H5EA_sblock_t *sblock, size_t *size_ptr);
+static herr_t H5EA__cache_sblock_dest(H5F_t *f, H5EA_sblock_t *sblock);
+static H5EA_dblock_t *H5EA__cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata, void *udata2);
+static herr_t H5EA__cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5EA_dblock_t *dblock, unsigned * flags_ptr);
+static herr_t H5EA__cache_dblock_clear(H5F_t *f, H5EA_dblock_t *dblock, hbool_t destroy);
+static herr_t H5EA__cache_dblock_size(const H5F_t *f, const H5EA_dblock_t *dblock, size_t *size_ptr);
+static herr_t H5EA__cache_dblock_dest(H5F_t *f, H5EA_dblock_t *dblock);
+static H5EA_dblk_page_t *H5EA__cache_dblk_page_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata, void *udata2);
+static herr_t H5EA__cache_dblk_page_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5EA_dblk_page_t *dblk_page, unsigned * flags_ptr);
+static herr_t H5EA__cache_dblk_page_clear(H5F_t *f, H5EA_dblk_page_t *dblk_page, hbool_t destroy);
+static herr_t H5EA__cache_dblk_page_size(const H5F_t *f, const H5EA_dblk_page_t *dblk_page, size_t *size_ptr);
+static herr_t H5EA__cache_dblk_page_dest(H5F_t *f, H5EA_dblk_page_t *dblk_page);
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+/* H5EA header inherits cache-like properties from H5AC */
+const H5AC_class_t H5AC_EARRAY_HDR[1] = {{
+ H5AC_EARRAY_HDR_ID,
+ (H5AC_load_func_t)H5EA__cache_hdr_load,
+ (H5AC_flush_func_t)H5EA__cache_hdr_flush,
+ (H5AC_dest_func_t)H5EA__cache_hdr_dest,
+ (H5AC_clear_func_t)H5EA__cache_hdr_clear,
+ (H5AC_size_func_t)H5EA__cache_hdr_size,
+}};
+
+/* H5EA index block inherits cache-like properties from H5AC */
+const H5AC_class_t H5AC_EARRAY_IBLOCK[1] = {{
+ H5AC_EARRAY_IBLOCK_ID,
+ (H5AC_load_func_t)H5EA__cache_iblock_load,
+ (H5AC_flush_func_t)H5EA__cache_iblock_flush,
+ (H5AC_dest_func_t)H5EA__cache_iblock_dest,
+ (H5AC_clear_func_t)H5EA__cache_iblock_clear,
+ (H5AC_size_func_t)H5EA__cache_iblock_size,
+}};
+
+/* H5EA super block inherits cache-like properties from H5AC */
+const H5AC_class_t H5AC_EARRAY_SBLOCK[1] = {{
+ H5AC_EARRAY_SBLOCK_ID,
+ (H5AC_load_func_t)H5EA__cache_sblock_load,
+ (H5AC_flush_func_t)H5EA__cache_sblock_flush,
+ (H5AC_dest_func_t)H5EA__cache_sblock_dest,
+ (H5AC_clear_func_t)H5EA__cache_sblock_clear,
+ (H5AC_size_func_t)H5EA__cache_sblock_size,
+}};
+
+/* H5EA data block inherits cache-like properties from H5AC */
+const H5AC_class_t H5AC_EARRAY_DBLOCK[1] = {{
+ H5AC_EARRAY_DBLOCK_ID,
+ (H5AC_load_func_t)H5EA__cache_dblock_load,
+ (H5AC_flush_func_t)H5EA__cache_dblock_flush,
+ (H5AC_dest_func_t)H5EA__cache_dblock_dest,
+ (H5AC_clear_func_t)H5EA__cache_dblock_clear,
+ (H5AC_size_func_t)H5EA__cache_dblock_size,
+}};
+
+/* H5EA data block page inherits cache-like properties from H5AC */
+const H5AC_class_t H5AC_EARRAY_DBLK_PAGE[1] = {{
+ H5AC_EARRAY_DBLK_PAGE_ID,
+ (H5AC_load_func_t)H5EA__cache_dblk_page_load,
+ (H5AC_flush_func_t)H5EA__cache_dblk_page_flush,
+ (H5AC_dest_func_t)H5EA__cache_dblk_page_dest,
+ (H5AC_clear_func_t)H5EA__cache_dblk_page_clear,
+ (H5AC_size_func_t)H5EA__cache_dblk_page_size,
+}};
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_hdr_load
+ *
+ * Purpose: Loads an extensible array header from the disk.
+ *
+ * Return: Success: Pointer to a new extensible array
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Aug 26 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, ERR,
+H5EA_hdr_t *, NULL, NULL,
+H5EA__cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_cls,
+ void UNUSED *udata2))
+
+ /* Local variables */
+ const H5EA_class_t *cls = (const H5EA_class_t *)_cls; /* Extensible array class */
+ H5EA_hdr_t *hdr = NULL; /* Extensible array info */
+ size_t size; /* Header size */
+ H5WB_t *wb = NULL; /* Wrapped buffer for header data */
+ uint8_t hdr_buf[H5EA_HDR_BUF_SIZE]; /* Buffer for header */
+ uint8_t *buf; /* Pointer to header buffer */
+ const uint8_t *p; /* Pointer into raw data buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ uint32_t computed_chksum; /* Computed metadata checksum value */
+
+ /* Check arguments */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+
+ /* Allocate space for the extensible array data structure */
+ if(NULL == (hdr = H5EA__hdr_alloc(f, cls)))
+ H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array shared header")
+
+ /* Set the extensible array header's address */
+ hdr->addr = addr;
+
+ /* Wrap the local buffer for serialized info */
+ if(NULL == (wb = H5WB_wrap(hdr_buf, sizeof(hdr_buf))))
+ H5E_THROW(H5E_CANTINIT, "can't wrap buffer")
+
+ /* Compute the 'base' size of the extensible array header on disk */
+ size = H5EA_HEADER_SIZE(hdr);
+
+ /* Get a pointer to a buffer that's large enough for serialized header */
+ if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
+ H5E_THROW(H5E_CANTGET, "can't get actual buffer")
+
+ /* Read header from disk */
+ if(H5F_block_read(f, H5FD_MEM_EARRAY_HDR, addr, size, dxpl_id, buf) < 0)
+ H5E_THROW(H5E_READERROR, "can't read extensible array header")
+
+ /* Get temporary pointer to serialized header */
+ p = buf;
+
+ /* Magic number */
+ if(HDmemcmp(p, H5EA_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ H5E_THROW(H5E_BADVALUE, "wrong extensible array header signature")
+ p += H5_SIZEOF_MAGIC;
+
+ /* Version */
+ if(*p++ != H5EA_HDR_VERSION)
+ H5E_THROW(H5E_VERSION, "wrong extensible array header version")
+
+ /* Extensible array type */
+ if(*p++ != (uint8_t)cls->id)
+ H5E_THROW(H5E_BADTYPE, "incorrect extensible array class")
+
+ /* General array creation/configuration information */
+ hdr->cparam.raw_elmt_size = *p++; /* Element size in file (in bytes) */
+ hdr->cparam.max_nelmts_bits = *p++; /* Log2(Max. # of elements in array) - i.e. # of bits needed to store max. # of elements */
+ hdr->cparam.idx_blk_elmts = *p++; /* # of elements to store in index block */
+ hdr->cparam.data_blk_min_elmts = *p++; /* Min. # of elements per data block */
+ hdr->cparam.sup_blk_min_data_ptrs = *p++; /* Min. # of data block pointers for a super block */
+ hdr->cparam.max_dblk_page_nelmts_bits = *p++; /* Log2(Max. # of elements in data block page) - i.e. # of bits needed to store max. # of elements in data block page */
+
+ /* Array statistics */
+ H5F_DECODE_LENGTH(f, p, hdr->stats.max_idx_set); /* Max. index set (+1) */
+ H5F_DECODE_LENGTH(f, p, hdr->stats.nsuper_blks); /* Number of super blocks created */
+ H5F_DECODE_LENGTH(f, p, hdr->stats.ndata_blks); /* Number of data blocks created */
+ H5F_DECODE_LENGTH(f, p, hdr->stats.nelmts); /* Number of elements 'realized' */
+
+ /* Internal information */
+ H5F_addr_decode(f, &p, &hdr->idx_blk_addr); /* Address of index block */
+
+ /* Sanity check */
+ /* (allow for checksum not decoded yet) */
+ HDassert((size_t)(p - buf) == (size - H5EA_SIZEOF_CHKSUM));
+
+ /* Compute checksum on entire header */
+ /* (including the filter information, if present) */
+ computed_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0);
+
+ /* Metadata checksum */
+ UINT32DECODE(p, stored_chksum);
+
+ /* Sanity check */
+ HDassert((size_t)(p - buf) == size);
+
+ /* Verify checksum */
+ if(stored_chksum != computed_chksum)
+ H5E_THROW(H5E_BADVALUE, "incorrect metadata checksum for extensible array header")
+
+ /* Finish initializing extensible array header */
+ if(H5EA__hdr_init(hdr) < 0)
+ H5E_THROW(H5E_CANTINIT, "initialization failed for extensible array header")
+ HDassert(hdr->size == size);
+
+ /* Set return value */
+ ret_value = hdr;
+
+CATCH
+
+ /* Release resources */
+ if(wb && H5WB_unwrap(wb) < 0)
+ H5E_THROW(H5E_CLOSEERROR, "can't close wrapped buffer")
+ if(!ret_value)
+ if(hdr && H5EA__cache_hdr_dest(f, hdr) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array header")
+
+END_FUNC(STATIC) /* end H5EA__cache_hdr_load() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_hdr_flush
+ *
+ * Purpose: Flushes a dirty extensible array header to disk.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Aug 26 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
+ H5EA_hdr_t *hdr, unsigned UNUSED * flags_ptr))
+
+ H5WB_t *wb = NULL; /* Wrapped buffer for header data */
+ uint8_t hdr_buf[H5EA_HDR_BUF_SIZE]; /* Buffer for header */
+
+ /* check arguments */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(hdr);
+
+ if(hdr->cache_info.is_dirty) {
+ uint8_t *buf; /* Temporary raw data buffer */
+ uint8_t *p; /* Pointer into raw data buffer */
+ size_t size; /* Header size on disk */
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
+
+ /* Wrap the local buffer for serialized header info */
+ if(NULL == (wb = H5WB_wrap(hdr_buf, sizeof(hdr_buf))))
+ H5E_THROW(H5E_CANTINIT, "can't wrap buffer")
+
+ /* Compute the size of the array header on disk */
+ size = hdr->size;
+
+ /* Get a pointer to a buffer that's large enough for serialized header */
+ if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
+ H5E_THROW(H5E_CANTGET, "can't get actual buffer")
+
+ /* Get temporary pointer to serialized header */
+ p = buf;
+
+ /* Magic number */
+ HDmemcpy(p, H5EA_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ p += H5_SIZEOF_MAGIC;
+
+ /* Version # */
+ *p++ = H5EA_HDR_VERSION;
+
+ /* Extensible array type */
+ *p++ = hdr->cparam.cls->id;
+
+ /* General array creation/configuration information */
+ *p++ = hdr->cparam.raw_elmt_size; /* Element size in file (in bytes) */
+ *p++ = hdr->cparam.max_nelmts_bits; /* Log2(Max. # of elements in array) - i.e. # of bits needed to store max. # of elements */
+ *p++ = hdr->cparam.idx_blk_elmts; /* # of elements to store in index block */
+ *p++ = hdr->cparam.data_blk_min_elmts; /* Min. # of elements per data block */
+ *p++ = hdr->cparam.sup_blk_min_data_ptrs; /* Min. # of data block pointers for a super block */
+ *p++ = hdr->cparam.max_dblk_page_nelmts_bits; /* Log2(Max. # of elements in data block page) - i.e. # of bits needed to store max. # of elements in data block page */
+
+ /* Array statistics */
+ H5F_ENCODE_LENGTH(f, p, hdr->stats.max_idx_set); /* Max. index set (+1) */
+ H5F_ENCODE_LENGTH(f, p, hdr->stats.nsuper_blks); /* Number of super blocks created */
+ H5F_ENCODE_LENGTH(f, p, hdr->stats.ndata_blks); /* Number of data blocks created */
+ H5F_ENCODE_LENGTH(f, p, hdr->stats.nelmts); /* Number of elements 'realized' */
+
+ /* Internal information */
+ H5F_addr_encode(f, &p, hdr->idx_blk_addr); /* Address of index block */
+
+ /* Compute metadata checksum */
+ metadata_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0);
+
+ /* Metadata checksum */
+ UINT32ENCODE(p, metadata_chksum);
+
+ /* Write the array header. */
+ HDassert((size_t)(p - buf) == size);
+ if(H5F_block_write(f, H5FD_MEM_EARRAY_HDR, addr, size, dxpl_id, buf) < 0)
+ H5E_THROW(H5E_WRITEERROR, "unable to save extensible array header to disk")
+
+ hdr->cache_info.is_dirty = FALSE;
+ } /* end if */
+
+ if(destroy)
+ if(H5EA__cache_hdr_dest(f, hdr) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array header")
+
+CATCH
+
+ /* Release resources */
+ if(wb && H5WB_unwrap(wb) < 0)
+ H5E_THROW(H5E_CLOSEERROR, "can't close wrapped buffer")
+
+END_FUNC(STATIC) /* end H5EA__cache_hdr_flush() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_hdr_clear
+ *
+ * Purpose: Mark a extensible array header in memory as non-dirty.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Aug 26 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__cache_hdr_clear(H5F_t *f, H5EA_hdr_t *hdr, hbool_t destroy))
+
+ /* Sanity check */
+ HDassert(hdr);
+
+ /* Reset the dirty flag. */
+ hdr->cache_info.is_dirty = FALSE;
+
+ if(destroy)
+ if(H5EA__cache_hdr_dest(f, hdr) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array header")
+
+CATCH
+
+END_FUNC(STATIC) /* end H5EA__cache_hdr_clear() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_hdr_size
+ *
+ * Purpose: Compute the size in bytes of a extensible array header
+ * on disk, and return it in *size_ptr. On failure,
+ * the value of *size_ptr is undefined.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Aug 26 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+BEGIN_FUNC(STATIC, NOERR,
+herr_t, SUCCEED, -,
+H5EA__cache_hdr_size(const H5F_t UNUSED *f, const H5EA_hdr_t *hdr,
+ size_t *size_ptr))
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(hdr);
+ HDassert(size_ptr);
+
+ /* Set size value */
+ *size_ptr = hdr->size;
+
+END_FUNC(STATIC) /* end H5EA__cache_hdr_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_hdr_dest
+ *
+ * Purpose: Destroys an extensible array header in memory.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Aug 26 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+BEGIN_FUNC(STATIC, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__cache_hdr_dest(H5F_t *f, H5EA_hdr_t *hdr))
+
+ /* Check arguments */
+ HDassert(f);
+ HDassert(hdr);
+
+ /* Verify that header is clean */
+ HDassert(hdr->cache_info.is_dirty == FALSE);
+
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!hdr->cache_info.free_file_space_on_destroy || H5F_addr_defined(hdr->cache_info.addr));
+
+ /* Check for freeing file space for extensible array header */
+ if(hdr->cache_info.free_file_space_on_destroy) {
+ /* Sanity check address */
+ HDassert(H5F_addr_eq(hdr->addr, hdr->cache_info.addr));
+
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_EARRAY_HDR, H5AC_dxpl_id, hdr->cache_info.addr, (hsize_t)hdr->size) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to free extensible array header")
+ } /* end if */
+
+ /* Release the extensible array header */
+ if(H5EA__hdr_dest(hdr) < 0)
+ H5E_THROW(H5E_CANTFREE, "can't free extensible array header")
+
+CATCH
+
+END_FUNC(STATIC) /* end H5EA__cache_hdr_dest() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_iblock_load
+ *
+ * Purpose: Loads an extensible array index block from the disk.
+ *
+ * Return: Success: Pointer to a new extensible array index block
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 9 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, ERR,
+H5EA_iblock_t *, NULL, NULL,
+H5EA__cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr,
+ const void UNUSED *udata1, void *_hdr))
+
+ /* Local variables */
+ H5EA_hdr_t *hdr = (H5EA_hdr_t *)_hdr; /* Shared extensible array information */
+ H5EA_iblock_t *iblock = NULL; /* Index block info */
+ size_t size; /* Index block size */
+ H5WB_t *wb = NULL; /* Wrapped buffer for index block data */
+ uint8_t iblock_buf[H5EA_IBLOCK_BUF_SIZE]; /* Buffer for index block */
+ uint8_t *buf; /* Pointer to index block buffer */
+ const uint8_t *p; /* Pointer into raw data buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ uint32_t computed_chksum; /* Computed metadata checksum value */
+ haddr_t arr_addr; /* Address of array header in the file */
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(hdr);
+
+ /* Allocate the extensible array index block */
+ if(NULL == (iblock = H5EA__iblock_alloc(hdr)))
+ H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array index block")
+
+ /* Set the extensible array index block's address */
+ iblock->addr = addr;
+
+ /* Wrap the local buffer for serialized info */
+ if(NULL == (wb = H5WB_wrap(iblock_buf, sizeof(iblock_buf))))
+ H5E_THROW(H5E_CANTINIT, "can't wrap buffer")
+
+ /* Compute the size of the extensible array index block on disk */
+ size = H5EA_IBLOCK_SIZE(iblock);
+
+ /* Get a pointer to a buffer that's large enough for serialized info */
+ if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
+ H5E_THROW(H5E_CANTGET, "can't get actual buffer")
+
+ /* Read index block from disk */
+ if(H5F_block_read(f, H5FD_MEM_EARRAY_IBLOCK, addr, size, dxpl_id, buf) < 0)
+ H5E_THROW(H5E_READERROR, "can't read extensible array index block")
+
+ /* Get temporary pointer to serialized header */
+ p = buf;
+
+ /* Magic number */
+ if(HDmemcmp(p, H5EA_IBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ H5E_THROW(H5E_BADVALUE, "wrong extensible array index block signature")
+ p += H5_SIZEOF_MAGIC;
+
+ /* Version */
+ if(*p++ != H5EA_IBLOCK_VERSION)
+ H5E_THROW(H5E_VERSION, "wrong extensible array index block version")
+
+ /* Address of header for array that owns this block (just for file integrity checks) */
+ H5F_addr_decode(f, &p, &arr_addr);
+ if(H5F_addr_ne(arr_addr, hdr->addr))
+ H5E_THROW(H5E_BADVALUE, "wrong extensible array header address")
+
+ /* Extensible array type */
+ if(*p++ != (uint8_t)hdr->cparam.cls->id)
+ H5E_THROW(H5E_BADTYPE, "incorrect extensible array class")
+
+ /* Internal information */
+
+ /* Decode elements in index block */
+ if(hdr->cparam.idx_blk_elmts > 0) {
+ /* Convert from raw elements on disk into native elements in memory */
+ if((hdr->cparam.cls->decode)(p, iblock->elmts, (size_t)hdr->cparam.idx_blk_elmts) < 0)
+ H5E_THROW(H5E_CANTDECODE, "can't decode extensible array index elements")
+ p += (hdr->cparam.idx_blk_elmts * hdr->cparam.raw_elmt_size);
+ } /* end if */
+
+ /* Decode data block addresses in index block */
+ if(iblock->ndblk_addrs > 0) {
+ size_t u; /* Local index variable */
+
+ /* Decode addresses of data blocks in index block */
+ for(u = 0; u < iblock->ndblk_addrs; u++)
+ H5F_addr_decode(f, &p, &iblock->dblk_addrs[u]);
+ } /* end if */
+
+ /* Decode super block addresses in index block */
+ if(iblock->nsblk_addrs > 0) {
+ size_t u; /* Local index variable */
+
+ /* Decode addresses of super blocks in index block */
+ for(u = 0; u < iblock->nsblk_addrs; u++)
+ H5F_addr_decode(f, &p, &iblock->sblk_addrs[u]);
+ } /* end if */
+
+ /* Sanity check */
+ /* (allow for checksum not decoded yet) */
+ HDassert((size_t)(p - buf) == (size - H5EA_SIZEOF_CHKSUM));
+
+ /* Save the index block's size */
+ iblock->size = size;
+
+ /* Compute checksum on index block */
+ computed_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0);
+
+ /* Metadata checksum */
+ UINT32DECODE(p, stored_chksum);
+
+ /* Sanity check */
+ HDassert((size_t)(p - buf) == iblock->size);
+
+ /* Verify checksum */
+ if(stored_chksum != computed_chksum)
+ H5E_THROW(H5E_BADVALUE, "incorrect metadata checksum for extensible array index block")
+
+ /* Set return value */
+ ret_value = iblock;
+
+CATCH
+
+ /* Release resources */
+ if(wb && H5WB_unwrap(wb) < 0)
+ H5E_THROW(H5E_CLOSEERROR, "can't close wrapped buffer")
+ if(!ret_value)
+ if(iblock && H5EA__cache_iblock_dest(f, iblock) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array index block")
+
+END_FUNC(STATIC) /* end H5EA__cache_iblock_load() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_iblock_flush
+ *
+ * Purpose: Flushes a dirty extensible array index block to disk.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 9 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__cache_iblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
+ H5EA_iblock_t *iblock, unsigned UNUSED * flags_ptr))
+
+ /* Local variables */
+ H5WB_t *wb = NULL; /* Wrapped buffer for serializing data */
+ uint8_t ser_buf[H5EA_IBLOCK_BUF_SIZE]; /* Serialization buffer */
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(iblock);
+ HDassert(iblock->hdr);
+
+ if(iblock->cache_info.is_dirty) {
+ uint8_t *buf; /* Temporary raw data buffer */
+ uint8_t *p; /* Pointer into raw data buffer */
+ size_t size; /* Index block size on disk */
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
+
+ /* Wrap the local buffer for serialized info */
+ if(NULL == (wb = H5WB_wrap(ser_buf, sizeof(ser_buf))))
+ H5E_THROW(H5E_CANTINIT, "can't wrap buffer")
+
+ /* Compute the size of the index block on disk */
+ size = iblock->size;
+
+ /* Get a pointer to a buffer that's large enough for serialized info */
+ if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
+ H5E_THROW(H5E_CANTGET, "can't get actual buffer")
+
+ /* Get temporary pointer to serialized info */
+ p = buf;
+
+ /* Magic number */
+ HDmemcpy(p, H5EA_IBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ p += H5_SIZEOF_MAGIC;
+
+ /* Version # */
+ *p++ = H5EA_IBLOCK_VERSION;
+
+ /* Address of array header for array which owns this block */
+ H5F_addr_encode(f, &p, iblock->hdr->addr);
+
+ /* Extensible array type */
+ *p++ = iblock->hdr->cparam.cls->id;
+
+ /* Internal information */
+
+ /* Encode elements in index block */
+ if(iblock->hdr->cparam.idx_blk_elmts > 0) {
+ /* Convert from native elements in memory into raw elements on disk */
+ if((iblock->hdr->cparam.cls->encode)(p, iblock->elmts, (size_t)iblock->hdr->cparam.idx_blk_elmts) < 0)
+ H5E_THROW(H5E_CANTENCODE, "can't encode extensible array index elements")
+ p += (iblock->hdr->cparam.idx_blk_elmts * iblock->hdr->cparam.raw_elmt_size);
+ } /* end if */
+
+ /* Encode data block addresses in index block */
+ if(iblock->ndblk_addrs > 0) {
+ size_t u; /* Local index variable */
+
+ /* Encode addresses of data blocks in index block */
+ for(u = 0; u < iblock->ndblk_addrs; u++)
+ H5F_addr_encode(f, &p, iblock->dblk_addrs[u]);
+ } /* end if */
+
+ /* Encode data block addresses in index block */
+ if(iblock->nsblk_addrs > 0) {
+ size_t u; /* Local index variable */
+
+ /* Encode addresses of super blocks in index block */
+ for(u = 0; u < iblock->nsblk_addrs; u++)
+ H5F_addr_encode(f, &p, iblock->sblk_addrs[u]);
+ } /* end if */
+
+ /* Compute metadata checksum */
+ metadata_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0);
+
+ /* Metadata checksum */
+ UINT32ENCODE(p, metadata_chksum);
+
+ /* Write the index block */
+ HDassert((size_t)(p - buf) == size);
+ if(H5F_block_write(f, H5FD_MEM_EARRAY_IBLOCK, addr, size, dxpl_id, buf) < 0)
+ H5E_THROW(H5E_WRITEERROR, "unable to save extensible array index block to disk")
+
+ iblock->cache_info.is_dirty = FALSE;
+ } /* end if */
+
+ if(destroy)
+ if(H5EA__cache_iblock_dest(f, iblock) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array index block")
+
+CATCH
+
+ /* Release resources */
+ if(wb && H5WB_unwrap(wb) < 0)
+ H5E_THROW(H5E_CLOSEERROR, "can't close wrapped buffer")
+
+END_FUNC(STATIC) /* end H5EA__cache_iblock_flush() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_iblock_clear
+ *
+ * Purpose: Mark a extensible array index block in memory as non-dirty.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sept 9 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__cache_iblock_clear(H5F_t *f, H5EA_iblock_t *iblock, hbool_t destroy))
+
+ /* Sanity check */
+ HDassert(iblock);
+
+ /* Reset the dirty flag */
+ iblock->cache_info.is_dirty = FALSE;
+
+ if(destroy)
+ if(H5EA__cache_iblock_dest(f, iblock) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array index block")
+
+CATCH
+
+END_FUNC(STATIC) /* end H5EA__cache_iblock_clear() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_iblock_size
+ *
+ * Purpose: Compute the size in bytes of a extensible array index block
+ * on disk, and return it in *size_ptr. On failure,
+ * the value of *size_ptr is undefined.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sept 9 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+BEGIN_FUNC(STATIC, NOERR,
+herr_t, SUCCEED, -,
+H5EA__cache_iblock_size(const H5F_t UNUSED *f, const H5EA_iblock_t *iblock,
+ size_t *size_ptr))
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(iblock);
+ HDassert(size_ptr);
+
+ /* Set size value */
+ *size_ptr = iblock->size;
+
+END_FUNC(STATIC) /* end H5EA__cache_iblock_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_iblock_dest
+ *
+ * Purpose: Destroys an extensible array index block in memory.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 9 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__cache_iblock_dest(H5F_t *f, H5EA_iblock_t *iblock))
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(iblock);
+
+ /* Verify that index block is clean */
+ HDassert(iblock->cache_info.is_dirty == FALSE);
+
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!iblock->cache_info.free_file_space_on_destroy || H5F_addr_defined(iblock->cache_info.addr));
+
+ /* Check for freeing file space for extensible array index block */
+ if(iblock->cache_info.free_file_space_on_destroy) {
+ /* Sanity check address */
+ HDassert(H5F_addr_eq(iblock->addr, iblock->cache_info.addr));
+
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_EARRAY_IBLOCK, H5AC_dxpl_id, iblock->cache_info.addr, (hsize_t)iblock->size) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to free extensible array index block")
+ } /* end if */
+
+ /* Release the index block */
+ if(H5EA__iblock_dest(f, iblock) < 0)
+ H5E_THROW(H5E_CANTFREE, "can't free extensible array index block")
+
+CATCH
+
+END_FUNC(STATIC) /* end H5EA__cache_iblock_dest() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_sblock_load
+ *
+ * Purpose: Loads an extensible array super block from the disk.
+ *
+ * Return: Success: Pointer to a new extensible array super block
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 30 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, ERR,
+H5EA_sblock_t *, NULL, NULL,
+H5EA__cache_sblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr,
+ const void *_sblk_idx, void *_hdr))
+
+ /* Local variables */
+ H5EA_hdr_t *hdr = (H5EA_hdr_t *)_hdr; /* Shared extensible array information */
+ const unsigned *sblk_idx = (const unsigned *)_sblk_idx; /* Index of this super block */
+ H5EA_sblock_t *sblock = NULL; /* Super block info */
+ size_t size; /* Super block size */
+ H5WB_t *wb = NULL; /* Wrapped buffer for super block data */
+ uint8_t sblock_buf[H5EA_IBLOCK_BUF_SIZE]; /* Buffer for super block */
+ uint8_t *buf; /* Pointer to super block buffer */
+ const uint8_t *p; /* Pointer into raw data buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ uint32_t computed_chksum; /* Computed metadata checksum value */
+ haddr_t arr_addr; /* Address of array header in the file */
+ size_t u; /* Local index variable */
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(sblk_idx && *sblk_idx > 0);
+ HDassert(hdr);
+
+ /* Allocate the extensible array super block */
+ if(NULL == (sblock = H5EA__sblock_alloc(hdr, *sblk_idx)))
+ H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array super block")
+
+ /* Set the extensible array super block's address */
+ sblock->addr = addr;
+
+ /* Wrap the local buffer for serialized info */
+ if(NULL == (wb = H5WB_wrap(sblock_buf, sizeof(sblock_buf))))
+ H5E_THROW(H5E_CANTINIT, "can't wrap buffer")
+
+ /* Compute the size of the extensible array super block on disk */
+ size = H5EA_SBLOCK_SIZE(sblock);
+
+ /* Get a pointer to a buffer that's large enough for serialized info */
+ if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
+ H5E_THROW(H5E_CANTGET, "can't get actual buffer")
+
+ /* Read super block from disk */
+ if(H5F_block_read(f, H5FD_MEM_EARRAY_SBLOCK, addr, size, dxpl_id, buf) < 0)
+ H5E_THROW(H5E_READERROR, "can't read extensible array super block")
+
+ /* Get temporary pointer to serialized header */
+ p = buf;
+
+ /* Magic number */
+ if(HDmemcmp(p, H5EA_SBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ H5E_THROW(H5E_BADVALUE, "wrong extensible array super block signature")
+ p += H5_SIZEOF_MAGIC;
+
+ /* Version */
+ if(*p++ != H5EA_SBLOCK_VERSION)
+ H5E_THROW(H5E_VERSION, "wrong extensible array super block version")
+
+ /* Address of header for array that owns this block (just for file integrity checks) */
+ H5F_addr_decode(f, &p, &arr_addr);
+ if(H5F_addr_ne(arr_addr, hdr->addr))
+ H5E_THROW(H5E_BADVALUE, "wrong extensible array header address")
+
+ /* Offset of block within the array's address space */
+ UINT64DECODE_VAR(p, sblock->block_off, hdr->arr_off_size);
+
+ /* Extensible array type */
+ if(*p++ != (uint8_t)hdr->cparam.cls->id)
+ H5E_THROW(H5E_BADTYPE, "incorrect extensible array class")
+
+ /* Internal information */
+
+ /* Check for 'page init' bitmasks for this super block */
+ if(sblock->dblk_npages > 0) {
+ size_t tot_page_init_size = sblock->ndblks * sblock->dblk_page_init_size; /* Compute total size of 'page init' buffer */
+
+ /* Retrieve the 'page init' bitmasks */
+ HDmemcpy(sblock->page_init, p, tot_page_init_size);
+ p += tot_page_init_size;
+ } /* end if */
+
+ /* Decode data block addresses */
+ for(u = 0; u < sblock->ndblks; u++)
+ H5F_addr_decode(f, &p, &sblock->dblk_addrs[u]);
+
+ /* Sanity check */
+ /* (allow for checksum not decoded yet) */
+ HDassert((size_t)(p - buf) == (size - H5EA_SIZEOF_CHKSUM));
+
+ /* Save the super block's size */
+ sblock->size = size;
+
+ /* Compute checksum on super block */
+ computed_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0);
+
+ /* Metadata checksum */
+ UINT32DECODE(p, stored_chksum);
+
+ /* Sanity check */
+ HDassert((size_t)(p - buf) == sblock->size);
+
+ /* Verify checksum */
+ if(stored_chksum != computed_chksum)
+ H5E_THROW(H5E_BADVALUE, "incorrect metadata checksum for extensible array super block")
+
+ /* Set return value */
+ ret_value = sblock;
+
+CATCH
+
+ /* Release resources */
+ if(wb && H5WB_unwrap(wb) < 0)
+ H5E_THROW(H5E_CLOSEERROR, "can't close wrapped buffer")
+ if(!ret_value)
+ if(sblock && H5EA__cache_sblock_dest(f, sblock) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array super block")
+
+END_FUNC(STATIC) /* end H5EA__cache_sblock_load() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_sblock_flush
+ *
+ * Purpose: Flushes a dirty extensible array super block to disk.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 30 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__cache_sblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
+ H5EA_sblock_t *sblock, unsigned UNUSED * flags_ptr))
+
+ /* Local variables */
+ H5WB_t *wb = NULL; /* Wrapped buffer for serializing data */
+ uint8_t ser_buf[H5EA_SBLOCK_BUF_SIZE]; /* Serialization buffer */
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(sblock);
+ HDassert(sblock->hdr);
+
+ if(sblock->cache_info.is_dirty) {
+ uint8_t *buf; /* Temporary raw data buffer */
+ uint8_t *p; /* Pointer into raw data buffer */
+ size_t size; /* Index block size on disk */
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
+ size_t u; /* Local index variable */
+
+ /* Wrap the local buffer for serialized info */
+ if(NULL == (wb = H5WB_wrap(ser_buf, sizeof(ser_buf))))
+ H5E_THROW(H5E_CANTINIT, "can't wrap buffer")
+
+ /* Compute the size of the super block on disk */
+ size = sblock->size;
+
+ /* Get a pointer to a buffer that's large enough for serialized info */
+ if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
+ H5E_THROW(H5E_CANTGET, "can't get actual buffer")
+
+ /* Get temporary pointer to serialized info */
+ p = buf;
+
+ /* Magic number */
+ HDmemcpy(p, H5EA_SBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ p += H5_SIZEOF_MAGIC;
+
+ /* Version # */
+ *p++ = H5EA_SBLOCK_VERSION;
+
+ /* Address of array header for array which owns this block */
+ H5F_addr_encode(f, &p, sblock->hdr->addr);
+
+ /* Offset of block in array */
+ UINT64ENCODE_VAR(p, sblock->block_off, sblock->hdr->arr_off_size);
+
+ /* Extensible array type */
+ *p++ = sblock->hdr->cparam.cls->id;
+
+ /* Internal information */
+
+ /* Check for 'page init' bitmasks for this super block */
+ if(sblock->dblk_npages > 0) {
+ size_t tot_page_init_size = sblock->ndblks * sblock->dblk_page_init_size; /* Compute total size of 'page init' buffer */
+
+ /* Store the 'page init' bitmasks */
+ HDmemcpy(p, sblock->page_init, tot_page_init_size);
+ p += tot_page_init_size;
+ } /* end if */
+
+ /* Encode addresses of data blocks in super block */
+ for(u = 0; u < sblock->ndblks; u++)
+ H5F_addr_encode(f, &p, sblock->dblk_addrs[u]);
+
+ /* Compute metadata checksum */
+ metadata_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0);
+
+ /* Metadata checksum */
+ UINT32ENCODE(p, metadata_chksum);
+
+ /* Write the super block */
+ HDassert((size_t)(p - buf) == size);
+ if(H5F_block_write(f, H5FD_MEM_EARRAY_SBLOCK, addr, size, dxpl_id, buf) < 0)
+ H5E_THROW(H5E_WRITEERROR, "unable to save extensible array super block to disk")
+
+ sblock->cache_info.is_dirty = FALSE;
+ } /* end if */
+
+ if(destroy)
+ if(H5EA__cache_sblock_dest(f, sblock) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array super block")
+
+CATCH
+
+ /* Release resources */
+ if(wb && H5WB_unwrap(wb) < 0)
+ H5E_THROW(H5E_CLOSEERROR, "can't close wrapped buffer")
+
+END_FUNC(STATIC) /* end H5EA__cache_sblock_flush() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_sblock_clear
+ *
+ * Purpose: Mark a extensible array super block in memory as non-dirty.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sept 30 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__cache_sblock_clear(H5F_t *f, H5EA_sblock_t *sblock, hbool_t destroy))
+
+ /* Sanity check */
+ HDassert(sblock);
+
+ /* Reset the dirty flag */
+ sblock->cache_info.is_dirty = FALSE;
+
+ if(destroy)
+ if(H5EA__cache_sblock_dest(f, sblock) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array super block")
+
+CATCH
+
+END_FUNC(STATIC) /* end H5EA__cache_sblock_clear() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_sblock_size
+ *
+ * Purpose: Compute the size in bytes of a extensible array super block
+ * on disk, and return it in *size_ptr. On failure,
+ * the value of *size_ptr is undefined.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sept 30 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+BEGIN_FUNC(STATIC, NOERR,
+herr_t, SUCCEED, -,
+H5EA__cache_sblock_size(const H5F_t UNUSED *f, const H5EA_sblock_t *sblock,
+ size_t *size_ptr))
+
+ /* Sanity check */
+ HDassert(sblock);
+ HDassert(size_ptr);
+
+ /* Set size value */
+ *size_ptr = sblock->size;
+
+END_FUNC(STATIC) /* end H5EA__cache_sblock_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_sblock_dest
+ *
+ * Purpose: Destroys an extensible array super block in memory.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 30 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__cache_sblock_dest(H5F_t *f, H5EA_sblock_t *sblock))
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(sblock);
+
+ /* Verify that super block is clean */
+ HDassert(sblock->cache_info.is_dirty == FALSE);
+
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!sblock->cache_info.free_file_space_on_destroy || H5F_addr_defined(sblock->cache_info.addr));
+
+ /* Check for freeing file space for extensible array super block */
+ if(sblock->cache_info.free_file_space_on_destroy) {
+ /* Sanity check address */
+ HDassert(H5F_addr_eq(sblock->addr, sblock->cache_info.addr));
+
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_EARRAY_SBLOCK, H5AC_dxpl_id, sblock->cache_info.addr, (hsize_t)sblock->size) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to free extensible array super block")
+ } /* end if */
+
+ /* Release the super block */
+ if(H5EA__sblock_dest(f, sblock) < 0)
+ H5E_THROW(H5E_CANTFREE, "can't free extensible array super block")
+
+CATCH
+
+END_FUNC(STATIC) /* end H5EA__cache_sblock_dest() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_dblock_load
+ *
+ * Purpose: Loads an extensible array data block from the disk.
+ *
+ * Return: Success: Pointer to a new extensible array data block
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 16 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, ERR,
+H5EA_dblock_t *, NULL, NULL,
+H5EA__cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr,
+ const void *_nelmts, void *_hdr))
+
+ /* Local variables */
+ H5EA_hdr_t *hdr = (H5EA_hdr_t *)_hdr; /* Shared extensible array information */
+ const size_t *nelmts = (const size_t *)_nelmts; /* Number of elements in data block */
+ H5EA_dblock_t *dblock = NULL; /* Data block info */
+ size_t size; /* Data block size */
+ H5WB_t *wb = NULL; /* Wrapped buffer for data block data */
+ uint8_t dblock_buf[H5EA_DBLOCK_BUF_SIZE]; /* Buffer for data block */
+ uint8_t *buf; /* Pointer to data block buffer */
+ const uint8_t *p; /* Pointer into raw data buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ uint32_t computed_chksum; /* Computed metadata checksum value */
+ haddr_t arr_addr; /* Address of array header in the file */
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(nelmts && *nelmts > 0);
+ HDassert(hdr);
+
+ /* Allocate the extensible array data block */
+ if(NULL == (dblock = H5EA__dblock_alloc(hdr, *nelmts)))
+ H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array data block")
+
+ /* Set the extensible array data block's information */
+ dblock->addr = addr;
+
+ /* Wrap the local buffer for serialized info */
+ if(NULL == (wb = H5WB_wrap(dblock_buf, sizeof(dblock_buf))))
+ H5E_THROW(H5E_CANTINIT, "can't wrap buffer")
+
+ /* Compute the size of the extensible array data block on disk */
+ if(!dblock->npages)
+ size = H5EA_DBLOCK_SIZE(dblock);
+ else
+ size = H5EA_DBLOCK_PREFIX_SIZE(dblock);
+
+ /* Get a pointer to a buffer that's large enough for serialized info */
+ if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
+ H5E_THROW(H5E_CANTGET, "can't get actual buffer")
+
+ /* Read data block from disk */
+ if(H5F_block_read(f, H5FD_MEM_EARRAY_DBLOCK, addr, size, dxpl_id, buf) < 0)
+ H5E_THROW(H5E_READERROR, "can't read extensible array data block")
+
+ /* Get temporary pointer to serialized header */
+ p = buf;
+
+ /* Magic number */
+ if(HDmemcmp(p, H5EA_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ H5E_THROW(H5E_BADVALUE, "wrong extensible array data block signature")
+ p += H5_SIZEOF_MAGIC;
+
+ /* Version */
+ if(*p++ != H5EA_DBLOCK_VERSION)
+ H5E_THROW(H5E_VERSION, "wrong extensible array data block version")
+
+ /* Address of header for array that owns this block (just for file integrity checks) */
+ H5F_addr_decode(f, &p, &arr_addr);
+ if(H5F_addr_ne(arr_addr, hdr->addr))
+ H5E_THROW(H5E_BADVALUE, "wrong extensible array header address")
+
+ /* Offset of block within the array's address space */
+ UINT64DECODE_VAR(p, dblock->block_off, hdr->arr_off_size);
+
+ /* Extensible array type */
+ if(*p++ != (uint8_t)hdr->cparam.cls->id)
+ H5E_THROW(H5E_BADTYPE, "incorrect extensible array class")
+
+ /* Internal information */
+
+ /* Only decode elements if the data block is not paged */
+ if(!dblock->npages) {
+ /* Decode elements in data block */
+ /* Convert from raw elements on disk into native elements in memory */
+ if((hdr->cparam.cls->decode)(p, dblock->elmts, *nelmts) < 0)
+ H5E_THROW(H5E_CANTDECODE, "can't decode extensible array data elements")
+ p += (*nelmts * hdr->cparam.raw_elmt_size);
+ } /* end if */
+
+ /* Sanity check */
+ /* (allow for checksum not decoded yet) */
+ HDassert((size_t)(p - buf) == (size - H5EA_SIZEOF_CHKSUM));
+
+ /* Set the data block's size */
+ dblock->size = H5EA_DBLOCK_SIZE(dblock);
+
+ /* Compute checksum on data block */
+ computed_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0);
+
+ /* Metadata checksum */
+ UINT32DECODE(p, stored_chksum);
+
+ /* Sanity check */
+ HDassert((size_t)(p - buf) == size);
+
+ /* Verify checksum */
+ if(stored_chksum != computed_chksum)
+ H5E_THROW(H5E_BADVALUE, "incorrect metadata checksum for extensible array data block")
+
+ /* Set return value */
+ ret_value = dblock;
+
+CATCH
+
+ /* Release resources */
+ if(wb && H5WB_unwrap(wb) < 0)
+ H5E_THROW(H5E_CLOSEERROR, "can't close wrapped buffer")
+ if(!ret_value)
+ if(dblock && H5EA__cache_dblock_dest(f, dblock) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array data block")
+
+END_FUNC(STATIC) /* end H5EA__cache_dblock_load() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_dblock_flush
+ *
+ * Purpose: Flushes a dirty extensible array data block to disk.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 18 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
+ H5EA_dblock_t *dblock, unsigned UNUSED * flags_ptr))
+
+ /* Local variables */
+ H5WB_t *wb = NULL; /* Wrapped buffer for serializing data */
+ uint8_t ser_buf[H5EA_DBLOCK_BUF_SIZE]; /* Serialization buffer */
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(dblock);
+ HDassert(dblock->hdr);
+
+ if(dblock->cache_info.is_dirty) {
+ uint8_t *buf; /* Temporary raw data buffer */
+ uint8_t *p; /* Pointer into raw data buffer */
+ size_t size; /* Index block size on disk */
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
+
+ /* Wrap the local buffer for serialized info */
+ if(NULL == (wb = H5WB_wrap(ser_buf, sizeof(ser_buf))))
+ H5E_THROW(H5E_CANTINIT, "can't wrap buffer")
+
+ /* Compute the size of the data block on disk */
+ if(!dblock->npages)
+ size = dblock->size;
+ else
+ size = H5EA_DBLOCK_PREFIX_SIZE(dblock);
+
+ /* Get a pointer to a buffer that's large enough for serialized info */
+ if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
+ H5E_THROW(H5E_CANTGET, "can't get actual buffer")
+
+ /* Get temporary pointer to serialized info */
+ p = buf;
+
+ /* Magic number */
+ HDmemcpy(p, H5EA_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ p += H5_SIZEOF_MAGIC;
+
+ /* Version # */
+ *p++ = H5EA_DBLOCK_VERSION;
+
+ /* Address of array header for array which owns this block */
+ H5F_addr_encode(f, &p, dblock->hdr->addr);
+
+ /* Offset of block in array */
+ UINT64ENCODE_VAR(p, dblock->block_off, dblock->hdr->arr_off_size);
+
+ /* Extensible array type */
+ *p++ = dblock->hdr->cparam.cls->id;
+
+ /* Internal information */
+
+ /* Only encode elements if the data block is not paged */
+ if(!dblock->npages) {
+ /* Encode elements in data block */
+
+ /* Convert from native elements in memory into raw elements on disk */
+ if((dblock->hdr->cparam.cls->encode)(p, dblock->elmts, dblock->nelmts) < 0)
+ H5E_THROW(H5E_CANTENCODE, "can't encode extensible array data elements")
+ p += (dblock->nelmts * dblock->hdr->cparam.raw_elmt_size);
+ } /* end if */
+
+ /* Compute metadata checksum */
+ metadata_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0);
+
+ /* Metadata checksum */
+ UINT32ENCODE(p, metadata_chksum);
+
+ /* Write the data block */
+ HDassert((size_t)(p - buf) == size);
+ if(H5F_block_write(f, H5FD_MEM_EARRAY_DBLOCK, addr, size, dxpl_id, buf) < 0)
+ H5E_THROW(H5E_WRITEERROR, "unable to save extensible array data block to disk")
+
+ dblock->cache_info.is_dirty = FALSE;
+ } /* end if */
+
+ if(destroy)
+ if(H5EA__cache_dblock_dest(f, dblock) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array data block")
+
+CATCH
+
+ /* Release resources */
+ if(wb && H5WB_unwrap(wb) < 0)
+ H5E_THROW(H5E_CLOSEERROR, "can't close wrapped buffer")
+
+END_FUNC(STATIC) /* end H5EA__cache_dblock_flush() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_dblock_clear
+ *
+ * Purpose: Mark a extensible array data block in memory as non-dirty.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sept 18 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__cache_dblock_clear(H5F_t *f, H5EA_dblock_t *dblock, hbool_t destroy))
+
+ /* Sanity check */
+ HDassert(dblock);
+
+ /* Reset the dirty flag */
+ dblock->cache_info.is_dirty = FALSE;
+
+ if(destroy)
+ if(H5EA__cache_dblock_dest(f, dblock) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array data block")
+
+CATCH
+
+END_FUNC(STATIC) /* end H5EA__cache_dblock_clear() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_dblock_size
+ *
+ * Purpose: Compute the size in bytes of a extensible array data block
+ * on disk, and return it in *size_ptr. On failure,
+ * the value of *size_ptr is undefined.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sept 18 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+BEGIN_FUNC(STATIC, NOERR,
+herr_t, SUCCEED, -,
+H5EA__cache_dblock_size(const H5F_t UNUSED *f, const H5EA_dblock_t *dblock,
+ size_t *size_ptr))
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(dblock);
+ HDassert(size_ptr);
+
+ /* Set size value */
+ if(!dblock->npages)
+ *size_ptr = dblock->size;
+ else
+ *size_ptr = H5EA_DBLOCK_PREFIX_SIZE(dblock);
+
+END_FUNC(STATIC) /* end H5EA__cache_dblock_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_dblock_dest
+ *
+ * Purpose: Destroys an extensible array data block in memory.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 18 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+BEGIN_FUNC(STATIC, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__cache_dblock_dest(H5F_t *f, H5EA_dblock_t *dblock))
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(dblock);
+
+ /* Verify that data block is clean */
+ HDassert(dblock->cache_info.is_dirty == FALSE);
+
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!dblock->cache_info.free_file_space_on_destroy || H5F_addr_defined(dblock->cache_info.addr));
+
+ /* Check for freeing file space for extensible array data block */
+ if(dblock->cache_info.free_file_space_on_destroy) {
+ /* Sanity check address */
+ HDassert(H5F_addr_eq(dblock->addr, dblock->cache_info.addr));
+
+ /* Release the space on disk */
+ /* (Includes space for pages!) */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_EARRAY_DBLOCK, H5AC_dxpl_id, dblock->cache_info.addr, (hsize_t)dblock->size) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to free extensible array data block")
+ } /* end if */
+
+ /* Release the data block */
+ if(H5EA__dblock_dest(f, dblock) < 0)
+ H5E_THROW(H5E_CANTFREE, "can't free extensible array data block")
+
+CATCH
+
+END_FUNC(STATIC) /* end H5EA__cache_dblock_dest() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_dblk_page_load
+ *
+ * Purpose: Loads an extensible array data block page from the disk.
+ *
+ * Return: Success: Pointer to a new extensible array data block page
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Nov 20 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, ERR,
+H5EA_dblk_page_t *, NULL, NULL,
+H5EA__cache_dblk_page_load(H5F_t *f, hid_t dxpl_id, haddr_t addr,
+ const void UNUSED *udata1, void *_hdr))
+
+ /* Local variables */
+ H5EA_hdr_t *hdr = (H5EA_hdr_t *)_hdr; /* Shared extensible array information */
+ H5EA_dblk_page_t *dblk_page = NULL; /* Data block page info */
+ size_t size; /* Data block page size */
+ H5WB_t *wb = NULL; /* Wrapped buffer for data block page data */
+ uint8_t dblk_page_buf[H5EA_DBLK_PAGE_BUF_SIZE]; /* Buffer for data block page */
+ uint8_t *buf; /* Pointer to data block page buffer */
+ const uint8_t *p; /* Pointer into raw data buffer */
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ uint32_t computed_chksum; /* Computed metadata checksum value */
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(hdr);
+#ifdef QAK
+HDfprintf(stderr, "%s: addr = %a\n", FUNC, addr);
+#endif /* QAK */
+
+ /* Allocate the extensible array data block page */
+ if(NULL == (dblk_page = H5EA__dblk_page_alloc(hdr)))
+ H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array data block page")
+
+ /* Set the extensible array data block's information */
+ dblk_page->addr = addr;
+
+ /* Wrap the local buffer for serialized info */
+ if(NULL == (wb = H5WB_wrap(dblk_page_buf, sizeof(dblk_page_buf))))
+ H5E_THROW(H5E_CANTINIT, "can't wrap buffer")
+
+ /* Compute the size of the extensible array data block page on disk */
+ size = H5EA_DBLK_PAGE_SIZE(dblk_page);
+
+ /* Get a pointer to a buffer that's large enough for serialized info */
+ if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
+ H5E_THROW(H5E_CANTGET, "can't get actual buffer")
+
+ /* Read data block page from disk */
+ if(H5F_block_read(f, H5FD_MEM_EARRAY_DBLK_PAGE, addr, size, dxpl_id, buf) < 0)
+ H5E_THROW(H5E_READERROR, "can't read extensible array data block page")
+
+ /* Get temporary pointer to serialized header */
+ p = buf;
+
+ /* Internal information */
+
+ /* Decode elements in data block page */
+ /* Convert from raw elements on disk into native elements in memory */
+ if((hdr->cparam.cls->decode)(p, dblk_page->elmts, hdr->dblk_page_nelmts) < 0)
+ H5E_THROW(H5E_CANTDECODE, "can't decode extensible array data elements")
+ p += (hdr->dblk_page_nelmts * hdr->cparam.raw_elmt_size);
+
+ /* Sanity check */
+ /* (allow for checksum not decoded yet) */
+ HDassert((size_t)(p - buf) == (size - H5EA_SIZEOF_CHKSUM));
+
+ /* Set the data block page's size */
+ dblk_page->size = size;
+
+ /* Compute checksum on data block */
+ computed_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0);
+
+ /* Metadata checksum */
+ UINT32DECODE(p, stored_chksum);
+
+ /* Sanity check */
+ HDassert((size_t)(p - buf) == dblk_page->size);
+
+ /* Verify checksum */
+ if(stored_chksum != computed_chksum)
+{
+HDfprintf(stderr, "%s: stored_chksum = %8x, computed_chksum = %8x\n", FUNC, stored_chksum, computed_chksum);
+ H5E_THROW(H5E_BADVALUE, "incorrect metadata checksum for extensible array data block page")
+}
+
+ /* Set return value */
+ ret_value = dblk_page;
+
+CATCH
+
+ /* Release resources */
+ if(wb && H5WB_unwrap(wb) < 0)
+ H5E_THROW(H5E_CLOSEERROR, "can't close wrapped buffer")
+ if(!ret_value)
+ if(dblk_page && H5EA__cache_dblk_page_dest(f, dblk_page) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array data block page")
+
+END_FUNC(STATIC) /* end H5EA__cache_dblk_page_load() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_dblk_page_flush
+ *
+ * Purpose: Flushes a dirty extensible array data block page to disk.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Nov 20 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__cache_dblk_page_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
+ H5EA_dblk_page_t *dblk_page, unsigned UNUSED * flags_ptr))
+
+ /* Local variables */
+ H5WB_t *wb = NULL; /* Wrapped buffer for serializing data */
+ uint8_t ser_buf[H5EA_DBLK_PAGE_BUF_SIZE]; /* Serialization buffer */
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(dblk_page);
+ HDassert(dblk_page->hdr);
+
+ if(dblk_page->cache_info.is_dirty) {
+ uint8_t *buf; /* Temporary raw data buffer */
+ uint8_t *p; /* Pointer into raw data buffer */
+ size_t size; /* Index block size on disk */
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
+
+ /* Wrap the local buffer for serialized info */
+ if(NULL == (wb = H5WB_wrap(ser_buf, sizeof(ser_buf))))
+ H5E_THROW(H5E_CANTINIT, "can't wrap buffer")
+
+ /* Compute the size of the data block on disk */
+ size = dblk_page->size;
+
+ /* Get a pointer to a buffer that's large enough for serialized info */
+ if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
+ H5E_THROW(H5E_CANTGET, "can't get actual buffer")
+
+ /* Get temporary pointer to serialized info */
+ p = buf;
+
+ /* Internal information */
+
+ /* Encode elements in data block page */
+
+ /* Convert from native elements in memory into raw elements on disk */
+ if((dblk_page->hdr->cparam.cls->encode)(p, dblk_page->elmts, dblk_page->hdr->dblk_page_nelmts) < 0)
+ H5E_THROW(H5E_CANTENCODE, "can't encode extensible array data elements")
+ p += (dblk_page->hdr->dblk_page_nelmts * dblk_page->hdr->cparam.raw_elmt_size);
+
+ /* Compute metadata checksum */
+ metadata_chksum = H5_checksum_metadata(buf, (size_t)(p - buf), 0);
+
+ /* Metadata checksum */
+ UINT32ENCODE(p, metadata_chksum);
+
+ /* Write the data block */
+ HDassert((size_t)(p - buf) == size);
+ if(H5F_block_write(f, H5FD_MEM_EARRAY_DBLK_PAGE, addr, size, dxpl_id, buf) < 0)
+ H5E_THROW(H5E_WRITEERROR, "unable to save extensible array data block page to disk")
+
+ dblk_page->cache_info.is_dirty = FALSE;
+ } /* end if */
+
+ if(destroy)
+ if(H5EA__cache_dblk_page_dest(f, dblk_page) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array data block page")
+
+CATCH
+
+ /* Release resources */
+ if(wb && H5WB_unwrap(wb) < 0)
+ H5E_THROW(H5E_CLOSEERROR, "can't close wrapped buffer")
+
+END_FUNC(STATIC) /* end H5EA__cache_dblk_page_flush() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_dblk_page_clear
+ *
+ * Purpose: Mark a extensible array data block page in memory as non-dirty.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Nov 20 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__cache_dblk_page_clear(H5F_t *f, H5EA_dblk_page_t *dblk_page, hbool_t destroy))
+
+ /* Sanity check */
+ HDassert(dblk_page);
+
+ /* Reset the dirty flag */
+ dblk_page->cache_info.is_dirty = FALSE;
+
+ if(destroy)
+ if(H5EA__cache_dblk_page_dest(f, dblk_page) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array data block page")
+
+CATCH
+
+END_FUNC(STATIC) /* end H5EA__cache_dblk_page_clear() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_dblk_page_size
+ *
+ * Purpose: Compute the size in bytes of a extensible array data block page
+ * on disk, and return it in *size_ptr. On failure,
+ * the value of *size_ptr is undefined.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Nov 20 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+BEGIN_FUNC(STATIC, NOERR,
+herr_t, SUCCEED, -,
+H5EA__cache_dblk_page_size(const H5F_t UNUSED *f, const H5EA_dblk_page_t *dblk_page,
+ size_t *size_ptr))
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(dblk_page);
+ HDassert(size_ptr);
+
+ /* Set size value */
+ *size_ptr = dblk_page->size;
+
+END_FUNC(STATIC) /* end H5EA__cache_dblk_page_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__cache_dblk_page_dest
+ *
+ * Purpose: Destroys an extensible array data block page in memory.
+ *
+ * Note: Does _not_ free the space for the page on disk, that is
+ * handled through the data block that "owns" the page.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Nov 20 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+BEGIN_FUNC(STATIC, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__cache_dblk_page_dest(H5F_t UNUSED *f, H5EA_dblk_page_t *dblk_page))
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(dblk_page);
+
+ /* Verify that data block page is clean */
+ HDassert(dblk_page->cache_info.is_dirty == FALSE);
+
+ /* Release the data block page */
+ if(H5EA__dblk_page_dest(dblk_page) < 0)
+ H5E_THROW(H5E_CANTFREE, "can't free extensible array data block page")
+
+CATCH
+
+END_FUNC(STATIC) /* end H5EA__cache_dblk_page_dest() */
+
diff --git a/src/H5EAdbg.c b/src/H5EAdbg.c
new file mode 100644
index 0000000..0cafe3d
--- /dev/null
+++ b/src/H5EAdbg.c
@@ -0,0 +1,440 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5EAdbg.c
+ * Sep 11 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: Dump debugging information about an extensible array.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/**********************/
+/* Module Declaration */
+/**********************/
+
+#define H5EA_MODULE
+
+
+/***********************/
+/* Other Packages Used */
+/***********************/
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5EApkg.h" /* Extensible Arrays */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__hdr_debug
+ *
+ * Purpose: Prints debugging info about a extensible array header.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 11 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent,
+ int fwidth, const H5EA_class_t *cls))
+
+ /* Local variables */
+ H5EA_hdr_t *hdr = NULL; /* Shared extensible array header */
+
+ /* Check arguments */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(stream);
+ HDassert(indent >= 0);
+ HDassert(fwidth >= 0);
+ HDassert(cls);
+
+ /* Load the extensible array header */
+ if(NULL == (hdr = (H5EA_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_EARRAY_HDR, addr, cls, NULL, H5AC_READ)))
+ H5E_THROW(H5E_CANTPROTECT, "unable to load extensible array header")
+
+ /* Print opening message */
+ HDfprintf(stream, "%*sExtensible Array Header...\n", indent, "");
+
+ /* Print the values */
+ HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
+ "Array class ID:",
+ (hdr->cparam.cls->id == H5EA_CLS_TEST_ID ? "H5EA_CLS_TEST_ID" :
+ "Unknown!"));
+ HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth,
+ "Header size:",
+ hdr->size);
+ HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
+ "Raw Element Size:",
+ (unsigned)hdr->cparam.raw_elmt_size);
+ HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth,
+ "Native Element Size (on this platform):",
+ hdr->cparam.cls->nat_elmt_size);
+ HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
+ "Log2(Max. # of elements in array):",
+ (unsigned)hdr->cparam.max_nelmts_bits);
+ HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
+ "# of elements in index block:",
+ (unsigned)hdr->cparam.idx_blk_elmts);
+ HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
+ "Min. # of elements per data block:",
+ (unsigned)hdr->cparam.data_blk_min_elmts);
+ HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
+ "Min. # of data block pointers for a super block:",
+ (unsigned)hdr->cparam.sup_blk_min_data_ptrs);
+ HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
+ "Log2(Max. # of elements in data block page):",
+ (unsigned)hdr->cparam.max_dblk_page_nelmts_bits);
+ HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
+ "Highest element index stored (+1):",
+ hdr->stats.max_idx_set);
+ HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
+ "Number of super blocks created:",
+ hdr->stats.nsuper_blks);
+ HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
+ "Number of data blocks created:",
+ hdr->stats.ndata_blks);
+ HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
+ "Number of elements 'realized':",
+ hdr->stats.nelmts);
+ HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
+ "Index Block Address:",
+ hdr->idx_blk_addr);
+
+CATCH
+ if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_EARRAY_HDR, addr, hdr, H5AC__NO_FLAGS_SET) < 0)
+ H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array header")
+
+END_FUNC(PKG) /* end H5EA__hdr_debug() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__iblock_debug
+ *
+ * Purpose: Prints debugging info about a extensible array index block.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 11 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent,
+ int fwidth, const H5EA_class_t *cls, haddr_t hdr_addr))
+
+ /* Local variables */
+ H5EA_hdr_t *hdr = NULL; /* Shared extensible array header */
+ H5EA_iblock_t *iblock = NULL; /* Extensible array index block */
+
+ /* Check arguments */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(stream);
+ HDassert(indent >= 0);
+ HDassert(fwidth >= 0);
+ HDassert(cls);
+ HDassert(H5F_addr_defined(hdr_addr));
+
+ /* Load the extensible array header */
+ if(NULL == (hdr = (H5EA_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_EARRAY_HDR, hdr_addr, cls, NULL, H5AC_READ)))
+ H5E_THROW(H5E_CANTPROTECT, "unable to load extensible array header")
+
+ /* Sanity check */
+ HDassert(H5F_addr_eq(hdr->idx_blk_addr, addr));
+
+ /* Protect index block */
+ if(NULL == (iblock = H5EA__iblock_protect(hdr, dxpl_id, H5AC_READ)))
+ H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array index block, address = %llu", (unsigned long_long)hdr->idx_blk_addr)
+
+ /* Print opening message */
+ HDfprintf(stream, "%*sExtensible Array Index Block...\n", indent, "");
+
+ /* Print the values */
+ HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
+ "Array class ID:",
+ (hdr->cparam.cls->id == H5EA_CLS_TEST_ID ? "H5EA_CLS_TEST_ID" :
+ "Unknown!"));
+ HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth,
+ "Index Block size:",
+ iblock->size);
+ HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth,
+ "# of data block addresses in index block:",
+ iblock->ndblk_addrs);
+ HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth,
+ "# of super block addresses in index block:",
+ iblock->nsblk_addrs);
+
+ /* Check if there are any elements in index block */
+ if(hdr->cparam.idx_blk_elmts > 0) {
+ unsigned u; /* Local index variable */
+
+ /* Print the elements in the index block */
+ HDfprintf(stream, "%*sElements in Index Block:\n", indent, "");
+ for(u = 0; u < hdr->cparam.idx_blk_elmts; u++) {
+ /* Call the class's 'debug' callback */
+ if((hdr->cparam.cls->debug)(stream, (indent + 3), MAX(0, (fwidth - 3)),
+ (hsize_t)u,
+ ((uint8_t *)iblock->elmts) + (hdr->cparam.cls->nat_elmt_size * u)) < 0)
+ H5E_THROW(H5E_CANTGET, "can't get element for debugging")
+ } /* end for */
+ } /* end if */
+
+ /* Check if there are any data block addresses in index block */
+ if(iblock->ndblk_addrs > 0) {
+ char temp_str[128]; /* Temporary string, for formatting */
+ unsigned u; /* Local index variable */
+
+ /* Print the data block addresses in the index block */
+ HDfprintf(stream, "%*sData Block Addresses in Index Block:\n", indent, "");
+ for(u = 0; u < iblock->ndblk_addrs; u++) {
+ /* Print address */
+ sprintf(temp_str, "Address #%u:", u);
+ HDfprintf(stream, "%*s%-*s %a\n", (indent + 3), "", MAX(0, (fwidth - 3)),
+ temp_str,
+ iblock->dblk_addrs[u]);
+ } /* end for */
+ } /* end if */
+
+ /* Check if there are any super block addresses in index block */
+ if(iblock->nsblk_addrs > 0) {
+ char temp_str[128]; /* Temporary string, for formatting */
+ unsigned u; /* Local index variable */
+
+ /* Print the super block addresses in the index block */
+ HDfprintf(stream, "%*sSuper Block Addresses in Index Block:\n", indent, "");
+ for(u = 0; u < iblock->nsblk_addrs; u++) {
+ /* Print address */
+ sprintf(temp_str, "Address #%u:", u);
+ HDfprintf(stream, "%*s%-*s %a\n", (indent + 3), "", MAX(0, (fwidth - 3)),
+ temp_str,
+ iblock->sblk_addrs[u]);
+ } /* end for */
+ } /* end if */
+
+CATCH
+ if(iblock && H5EA__iblock_unprotect(iblock, dxpl_id, H5AC__NO_FLAGS_SET) < 0)
+ H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array index block")
+ if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_EARRAY_HDR, hdr_addr, hdr, H5AC__NO_FLAGS_SET) < 0)
+ H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array header")
+
+END_FUNC(PKG) /* end H5EA__iblock_debug() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__sblock_debug
+ *
+ * Purpose: Prints debugging info about a extensible array super block.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 30 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__sblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent,
+ int fwidth, const H5EA_class_t *cls, haddr_t hdr_addr, unsigned sblk_idx))
+
+ /* Local variables */
+ H5EA_hdr_t *hdr = NULL; /* Shared extensible array header */
+ H5EA_sblock_t *sblock = NULL; /* Extensible array super block */
+
+ /* Check arguments */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(stream);
+ HDassert(indent >= 0);
+ HDassert(fwidth >= 0);
+ HDassert(cls);
+ HDassert(H5F_addr_defined(hdr_addr));
+
+ /* Load the extensible array header */
+ if(NULL == (hdr = (H5EA_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_EARRAY_HDR, hdr_addr, cls, NULL, H5AC_READ)))
+ H5E_THROW(H5E_CANTPROTECT, "unable to load extensible array header")
+
+ /* Protect super block */
+ if(NULL == (sblock = H5EA__sblock_protect(hdr, dxpl_id, addr, sblk_idx, H5AC_READ)))
+ H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array super block, address = %llu", (unsigned long_long)addr)
+
+ /* Print opening message */
+ HDfprintf(stream, "%*sExtensible Array Super Block...\n", indent, "");
+
+ /* Print the values */
+ HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
+ "Array class ID:",
+ (hdr->cparam.cls->id == H5EA_CLS_TEST_ID ? "H5EA_CLS_TEST_ID" :
+ "Unknown!"));
+ HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth,
+ "Super Block size:",
+ sblock->size);
+ HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth,
+ "# of data block addresses in super block:",
+ sblock->ndblks);
+ HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth,
+ "# of elements in data blocks from this super block:",
+ sblock->dblk_nelmts);
+
+ /* Check if there are any data block addresses in super block */
+ if(sblock->ndblks > 0) {
+ char temp_str[128]; /* Temporary string, for formatting */
+ unsigned u; /* Local index variable */
+
+ /* Print the data block addresses in the super block */
+ HDfprintf(stream, "%*sData Block Addresses in Super Block:\n", indent, "");
+ for(u = 0; u < sblock->ndblks; u++) {
+ /* Print address */
+ sprintf(temp_str, "Address #%u:", u);
+ HDfprintf(stream, "%*s%-*s %a\n", (indent + 3), "", MAX(0, (fwidth - 3)),
+ temp_str,
+ sblock->dblk_addrs[u]);
+ } /* end for */
+ } /* end if */
+
+CATCH
+ if(sblock && H5EA__sblock_unprotect(sblock, dxpl_id, H5AC__NO_FLAGS_SET) < 0)
+ H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array super block")
+ if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_EARRAY_HDR, hdr_addr, hdr, H5AC__NO_FLAGS_SET) < 0)
+ H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array header")
+
+END_FUNC(PKG) /* end H5EA__sblock_debug() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__dblock_debug
+ *
+ * Purpose: Prints debugging info about a extensible array data block.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 22 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__dblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent,
+ int fwidth, const H5EA_class_t *cls, haddr_t hdr_addr, size_t dblk_nelmts))
+
+ /* Local variables */
+ H5EA_hdr_t *hdr = NULL; /* Shared extensible array header */
+ H5EA_dblock_t *dblock = NULL; /* Extensible array data block */
+ size_t u; /* Local index variable */
+
+ /* Check arguments */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(stream);
+ HDassert(indent >= 0);
+ HDassert(fwidth >= 0);
+ HDassert(cls);
+ HDassert(H5F_addr_defined(hdr_addr));
+ HDassert(dblk_nelmts > 0);
+
+ /* Load the extensible array header */
+ if(NULL == (hdr = (H5EA_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_EARRAY_HDR, hdr_addr, cls, NULL, H5AC_READ)))
+ H5E_THROW(H5E_CANTPROTECT, "unable to load extensible array header")
+
+ /* Protect data block */
+ if(NULL == (dblock = H5EA__dblock_protect(hdr, dxpl_id, addr, dblk_nelmts, H5AC_READ)))
+ H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array data block, address = %llu", (unsigned long_long)addr)
+
+ /* Print opening message */
+ HDfprintf(stream, "%*sExtensible Array data Block...\n", indent, "");
+
+ /* Print the values */
+ HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
+ "Array class ID:",
+ (hdr->cparam.cls->id == H5EA_CLS_TEST_ID ? "H5EA_CLS_TEST_ID" :
+ "Unknown!"));
+ HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth,
+ "Data Block size:",
+ dblock->size);
+
+
+ /* Print the elements in the index block */
+ HDfprintf(stream, "%*sElements:\n", indent, "");
+ for(u = 0; u < dblk_nelmts; u++) {
+ /* Call the class's 'debug' callback */
+ if((hdr->cparam.cls->debug)(stream, (indent + 3), MAX(0, (fwidth - 3)),
+ (hsize_t)u,
+ ((uint8_t *)dblock->elmts) + (hdr->cparam.cls->nat_elmt_size * u)) < 0)
+ H5E_THROW(H5E_CANTGET, "can't get element for debugging")
+ } /* end for */
+
+CATCH
+ if(dblock && H5EA__dblock_unprotect(dblock, dxpl_id, H5AC__NO_FLAGS_SET) < 0)
+ H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array data block")
+ if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_EARRAY_HDR, hdr_addr, hdr, H5AC__NO_FLAGS_SET) < 0)
+ H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array header")
+
+END_FUNC(PKG) /* end H5EA__dblock_debug() */
+
diff --git a/src/H5EAdblkpage.c b/src/H5EAdblkpage.c
new file mode 100644
index 0000000..4b9cc9d
--- /dev/null
+++ b/src/H5EAdblkpage.c
@@ -0,0 +1,313 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5EAdblkpage.c
+ * Nov 20 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: Data block page routines for extensible arrays.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/**********************/
+/* Module Declaration */
+/**********************/
+
+#define H5EA_MODULE
+
+
+/***********************/
+/* Other Packages Used */
+/***********************/
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5EApkg.h" /* Extensible Arrays */
+#include "H5FLprivate.h" /* Free Lists */
+#include "H5Vprivate.h" /* Vectors and arrays */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* Declare a free list to manage the H5EA_dblk_page_t struct */
+H5FL_DEFINE_STATIC(H5EA_dblk_page_t);
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__dblk_page_alloc
+ *
+ * Purpose: Allocate extensible array data block page
+ *
+ * Return: Non-NULL pointer to data block on success/NULL on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Nov 20 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+H5EA_dblk_page_t *, NULL, NULL,
+H5EA__dblk_page_alloc(H5EA_hdr_t *hdr))
+
+ /* Local variables */
+ H5EA_dblk_page_t *dblk_page = NULL; /* Extensible array data block page */
+
+ /* Check arguments */
+ HDassert(hdr);
+
+ /* Allocate memory for the data block */
+ if(NULL == (dblk_page = H5FL_CALLOC(H5EA_dblk_page_t)))
+ H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array data block page")
+
+ /* Share common array information */
+ if(H5EA__hdr_incr(hdr) < 0)
+ H5E_THROW(H5E_CANTINC, "can't increment reference count on shared array header")
+ dblk_page->hdr = hdr;
+
+ /* Set non-zero internal fields */
+ /* <none> */
+
+ /* Allocate buffer for elements in data block page */
+ if(NULL == (dblk_page->elmts = H5EA__hdr_alloc_elmts(hdr, hdr->dblk_page_nelmts)))
+ H5E_THROW(H5E_CANTALLOC, "memory allocation failed for data block page element buffer")
+
+ /* Set the return value */
+ ret_value = dblk_page;
+
+CATCH
+ if(!ret_value)
+ if(dblk_page && H5EA__dblk_page_dest(dblk_page) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array data block page")
+
+END_FUNC(PKG) /* end H5EA__dblk_page_alloc() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__dblk_page_create
+ *
+ * Purpose: Creates a new extensible array data block page in the file
+ *
+ * Return: Valid file address on success/HADDR_UNDEF on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Nov 20 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__dblk_page_create(H5EA_hdr_t *hdr, hid_t dxpl_id, haddr_t addr))
+
+ /* Local variables */
+ H5EA_dblk_page_t *dblk_page = NULL; /* Extensible array data block page */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Called, addr = %a\n", FUNC, addr);
+#endif /* QAK */
+
+ /* Sanity check */
+ HDassert(hdr);
+
+ /* Allocate the data block page */
+ if(NULL == (dblk_page = H5EA__dblk_page_alloc(hdr)))
+ H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array data block page")
+
+ /* Set info about data block page on disk */
+ dblk_page->addr = addr;
+ dblk_page->size = H5EA_DBLK_PAGE_SIZE(dblk_page);
+#ifdef QAK
+HDfprintf(stderr, "%s: dblk_page->size = %Zu\n", FUNC, dblk_page->size);
+#endif /* QAK */
+
+ /* Clear any elements in data block page to fill value */
+ if((hdr->cparam.cls->fill)(dblk_page->elmts, (size_t)hdr->dblk_page_nelmts) < 0)
+ H5E_THROW(H5E_CANTSET, "can't set extensible array data block page elements to class's fill value")
+
+ /* Cache the new extensible array data block page */
+ if(H5AC_set(hdr->f, dxpl_id, H5AC_EARRAY_DBLK_PAGE, dblk_page->addr, dblk_page, H5AC__NO_FLAGS_SET) < 0)
+ H5E_THROW(H5E_CANTINSERT, "can't add extensible array data block page to cache")
+
+CATCH
+ if(ret_value < 0)
+ if(dblk_page) {
+ /* Destroy data block page */
+ if(H5EA__dblk_page_dest(dblk_page) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array data block page")
+ } /* end if */
+
+END_FUNC(PKG) /* end H5EA__dblk_page_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__dblk_page_protect
+ *
+ * Purpose: Convenience wrapper around protecting extensible array data
+ * block page
+ *
+ * Return: Non-NULL pointer to data block page on success/NULL on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Nov 20 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+H5EA_dblk_page_t *, NULL, NULL,
+H5EA__dblk_page_protect(H5EA_hdr_t *hdr, hid_t dxpl_id, haddr_t dblk_page_addr,
+ H5AC_protect_t rw))
+
+ /* Local variables */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Called\n", FUNC);
+#endif /* QAK */
+
+ /* Sanity check */
+ HDassert(hdr);
+ HDassert(H5F_addr_defined(dblk_page_addr));
+
+ /* Protect the data block page */
+ if(NULL == (ret_value = (H5EA_dblk_page_t *)H5AC_protect(hdr->f, dxpl_id, H5AC_EARRAY_DBLK_PAGE, dblk_page_addr, NULL, hdr, rw)))
+ H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array data block page, address = %llu", (unsigned long_long)dblk_page_addr)
+
+CATCH
+
+END_FUNC(PKG) /* end H5EA__dblk_page_protect() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__dblk_page_unprotect
+ *
+ * Purpose: Convenience wrapper around unprotecting extensible array
+ * data block page
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Nov 20 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__dblk_page_unprotect(H5EA_dblk_page_t *dblk_page, hid_t dxpl_id,
+ unsigned cache_flags))
+
+ /* Local variables */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Called\n", FUNC);
+#endif /* QAK */
+
+ /* Sanity check */
+ HDassert(dblk_page);
+
+ /* Unprotect the data block page */
+ if(H5AC_unprotect(dblk_page->hdr->f, dxpl_id, H5AC_EARRAY_DBLK_PAGE, dblk_page->addr, dblk_page, cache_flags) < 0)
+ H5E_THROW(H5E_CANTUNPROTECT, "unable to unprotect extensible array data block page, address = %llu", (unsigned long_long)dblk_page->addr)
+
+CATCH
+
+END_FUNC(PKG) /* end H5EA__dblk_page_unprotect() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__dblk_page_dest
+ *
+ * Purpose: Destroys an extensible array data block page in memory.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Nov 20 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+BEGIN_FUNC(PKG, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__dblk_page_dest(H5EA_dblk_page_t *dblk_page))
+
+ /* Sanity check */
+ HDassert(dblk_page);
+
+ /* Check if header field has been initialized */
+ if(dblk_page->hdr) {
+ /* Check if buffer for data block page elements has been initialized */
+ if(dblk_page->elmts) {
+ /* Free buffer for data block page elements */
+ if(H5EA__hdr_free_elmts(dblk_page->hdr, dblk_page->hdr->dblk_page_nelmts, dblk_page->elmts) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to free extensible array data block element buffer")
+ dblk_page->elmts = NULL;
+ } /* end if */
+
+ /* Decrement reference count on shared info */
+ if(H5EA__hdr_decr(dblk_page->hdr) < 0)
+ H5E_THROW(H5E_CANTDEC, "can't decrement reference count on shared array header")
+ dblk_page->hdr = NULL;
+ } /* end if */
+
+ /* Free the data block page itself */
+ (void)H5FL_FREE(H5EA_dblk_page_t, dblk_page);
+
+CATCH
+
+END_FUNC(PKG) /* end H5EA__dblk_page_dest() */
+
diff --git a/src/H5EAdblock.c b/src/H5EAdblock.c
new file mode 100644
index 0000000..b64cb7d
--- /dev/null
+++ b/src/H5EAdblock.c
@@ -0,0 +1,465 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5EAdblock.c
+ * Sep 11 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: Data block routines for extensible arrays.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/**********************/
+/* Module Declaration */
+/**********************/
+
+#define H5EA_MODULE
+
+
+/***********************/
+/* Other Packages Used */
+/***********************/
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5EApkg.h" /* Extensible Arrays */
+#include "H5FLprivate.h" /* Free Lists */
+#include "H5MFprivate.h" /* File memory management */
+#include "H5Vprivate.h" /* Vectors and arrays */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* Declare a free list to manage the H5EA_dblock_t struct */
+H5FL_DEFINE_STATIC(H5EA_dblock_t);
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__dblock_alloc
+ *
+ * Purpose: Allocate extensible array data block
+ *
+ * Return: Non-NULL pointer to data block on success/NULL on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 11 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+H5EA_dblock_t *, NULL, NULL,
+H5EA__dblock_alloc(H5EA_hdr_t *hdr, size_t nelmts))
+
+ /* Local variables */
+ H5EA_dblock_t *dblock = NULL; /* Extensible array data block */
+
+ /* Check arguments */
+ HDassert(hdr);
+ HDassert(nelmts > 0);
+
+ /* Allocate memory for the data block */
+ if(NULL == (dblock = H5FL_CALLOC(H5EA_dblock_t)))
+ H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array data block")
+
+ /* Share common array information */
+ if(H5EA__hdr_incr(hdr) < 0)
+ H5E_THROW(H5E_CANTINC, "can't increment reference count on shared array header")
+ dblock->hdr = hdr;
+
+ /* Set non-zero internal fields */
+ dblock->nelmts = nelmts;
+
+ /* Check if the data block is not going to be paged */
+ if(nelmts > hdr->dblk_page_nelmts) {
+ /* Set the # of pages in the direct block */
+ dblock->npages = nelmts / hdr->dblk_page_nelmts;
+ HDassert(nelmts == (dblock->npages * hdr->dblk_page_nelmts));
+ } /* end if */
+ else {
+ /* Allocate buffer for elements in data block */
+ if(NULL == (dblock->elmts = H5EA__hdr_alloc_elmts(hdr, nelmts)))
+ H5E_THROW(H5E_CANTALLOC, "memory allocation failed for data block element buffer")
+ } /* end else */
+
+ /* Set the return value */
+ ret_value = dblock;
+
+CATCH
+ if(!ret_value)
+ if(dblock && H5EA__dblock_dest(hdr->f, dblock) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array data block")
+
+END_FUNC(PKG) /* end H5EA__dblock_alloc() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__dblock_create
+ *
+ * Purpose: Creates a new extensible array data block in the file
+ *
+ * Return: Valid file address on success/HADDR_UNDEF on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 9 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+haddr_t, HADDR_UNDEF, HADDR_UNDEF,
+H5EA__dblock_create(H5EA_hdr_t *hdr, hid_t dxpl_id, hsize_t dblk_off, size_t nelmts))
+
+ /* Local variables */
+ H5EA_dblock_t *dblock = NULL; /* Extensible array data block */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Called, hdr->dblk_page_nelmts = %Zu, nelmts = %Zu\n", FUNC, hdr->dblk_page_nelmts, nelmts);
+#endif /* QAK */
+
+ /* Sanity check */
+ HDassert(hdr);
+ HDassert(nelmts > 0);
+
+ /* Allocate the data block */
+ if(NULL == (dblock = H5EA__dblock_alloc(hdr, nelmts)))
+ H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array data block")
+
+ /* Set size of data block on disk */
+ dblock->size = H5EA_DBLOCK_SIZE(dblock);
+#ifdef QAK
+HDfprintf(stderr, "%s: dblock->size = %Zu\n", FUNC, dblock->size);
+#endif /* QAK */
+
+ /* Set offset of block in array's address space */
+ dblock->block_off = dblk_off;
+#ifdef QAK
+HDfprintf(stderr, "%s: dblock->block_off = %Hu\n", FUNC, dblock->block_off);
+#endif /* QAK */
+
+ /* Allocate space for the data block on disk */
+ if(HADDR_UNDEF == (dblock->addr = H5MF_alloc(hdr->f, H5FD_MEM_EARRAY_DBLOCK, dxpl_id, (hsize_t)dblock->size)))
+ H5E_THROW(H5E_CANTALLOC, "file allocation failed for extensible array data block")
+
+ /* Don't initialize elements if paged */
+ if(!dblock->npages)
+ /* Clear any elements in data block to fill value */
+ if((hdr->cparam.cls->fill)(dblock->elmts, (size_t)dblock->nelmts) < 0)
+ H5E_THROW(H5E_CANTSET, "can't set extensible array data block elements to class's fill value")
+
+ /* Cache the new extensible array data block */
+ if(H5AC_set(hdr->f, dxpl_id, H5AC_EARRAY_DBLOCK, dblock->addr, dblock, H5AC__NO_FLAGS_SET) < 0)
+ H5E_THROW(H5E_CANTINSERT, "can't add extensible array data block to cache")
+
+ /* Set address of data block to return */
+ ret_value = dblock->addr;
+
+CATCH
+ if(!H5F_addr_defined(ret_value))
+ if(dblock) {
+ /* Release data block's disk space */
+ if(H5F_addr_defined(dblock->addr) && H5MF_xfree(hdr->f, H5FD_MEM_EARRAY_DBLOCK, dxpl_id, dblock->addr, (hsize_t)dblock->size) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to release extensible array data block")
+
+ /* Destroy data block */
+ if(H5EA__dblock_dest(hdr->f, dblock) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array data block")
+ } /* end if */
+
+END_FUNC(PKG) /* end H5EA__dblock_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__dblock_sblk_idx
+ *
+ * Purpose: Compute the index of the super block where the element is
+ * located.
+ *
+ * Return: Super block index on success/Can't fail
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 11 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, NOERR,
+unsigned, 0, -,
+H5EA__dblock_sblk_idx(const H5EA_hdr_t *hdr, hsize_t idx))
+
+ /* Local variables */
+ unsigned sblk_idx; /* Which superblock does this index fall in? */
+
+ /* Sanity check */
+ HDassert(hdr);
+ HDassert(idx >= hdr->cparam.idx_blk_elmts);
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Entering - idx = %Hu\n", FUNC, idx);
+#endif /* QAK */
+ /* Adjust index for elements in index block */
+ idx -= hdr->cparam.idx_blk_elmts;
+#ifdef QAK
+HDfprintf(stderr, "%s: after adjusting for index block elements, idx = %Hu\n", FUNC, idx);
+#endif /* QAK */
+
+ /* Determine the superblock information for the index */
+ H5_CHECK_OVERFLOW(idx, /*From:*/hsize_t, /*To:*/uint64_t);
+#ifdef QAK
+HDfprintf(stderr, "%s: hdr->cparam.data_blk_min_elmts = %u\n", FUNC, (unsigned)hdr->cparam.data_blk_min_elmts);
+#endif /* QAK */
+ sblk_idx = H5V_log2_gen((uint64_t)((idx / hdr->cparam.data_blk_min_elmts) + 1));
+#ifdef QAK
+HDfprintf(stderr, "%s: sblk_idx = %u\n", FUNC, sblk_idx);
+HDfprintf(stderr, "%s: hdr->sblk_info[%u] = {%Hu, %Zu, %Hu, %Hu}\n", FUNC, sblk_idx, hdr->sblk_info[sblk_idx].ndblks, hdr->sblk_info[sblk_idx].dblk_nelmts, hdr->sblk_info[sblk_idx].start_idx, hdr->sblk_info[sblk_idx].start_dblk);
+#endif /* QAK */
+
+ /* Set return value */
+ ret_value = sblk_idx;
+
+END_FUNC(PKG) /* end H5EA__dblock_sblk_idx() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__dblock_protect
+ *
+ * Purpose: Convenience wrapper around protecting extensible array data block
+ *
+ * Return: Non-NULL pointer to data block on success/NULL on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 18 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+H5EA_dblock_t *, NULL, NULL,
+H5EA__dblock_protect(H5EA_hdr_t *hdr, hid_t dxpl_id, haddr_t dblk_addr,
+ size_t dblk_nelmts, H5AC_protect_t rw))
+
+ /* Local variables */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Called\n", FUNC);
+#endif /* QAK */
+
+ /* Sanity check */
+ HDassert(hdr);
+ HDassert(H5F_addr_defined(dblk_addr));
+ HDassert(dblk_nelmts);
+
+ /* Protect the data block */
+ if(NULL == (ret_value = (H5EA_dblock_t *)H5AC_protect(hdr->f, dxpl_id, H5AC_EARRAY_DBLOCK, dblk_addr, &dblk_nelmts, hdr, rw)))
+ H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array data block, address = %llu", (unsigned long_long)dblk_addr)
+
+CATCH
+
+END_FUNC(PKG) /* end H5EA__dblock_protect() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__dblock_unprotect
+ *
+ * Purpose: Convenience wrapper around unprotecting extensible array data block
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 11 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__dblock_unprotect(H5EA_dblock_t *dblock, hid_t dxpl_id, unsigned cache_flags))
+
+ /* Local variables */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Called\n", FUNC);
+#endif /* QAK */
+
+ /* Sanity check */
+ HDassert(dblock);
+
+ /* Unprotect the data block */
+ if(H5AC_unprotect(dblock->hdr->f, dxpl_id, H5AC_EARRAY_DBLOCK, dblock->addr, dblock, cache_flags) < 0)
+ H5E_THROW(H5E_CANTUNPROTECT, "unable to unprotect extensible array data block, address = %llu", (unsigned long_long)dblock->addr)
+
+CATCH
+
+END_FUNC(PKG) /* end H5EA__dblock_unprotect() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__dblock_delete
+ *
+ * Purpose: Delete a data block
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 22 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__dblock_delete(H5EA_hdr_t *hdr, hid_t dxpl_id, haddr_t dblk_addr,
+ size_t dblk_nelmts))
+
+ /* Local variables */
+ H5EA_dblock_t *dblock = NULL; /* Pointer to data block */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Called\n", FUNC);
+#endif /* QAK */
+
+ /* Sanity check */
+ HDassert(hdr);
+ HDassert(H5F_addr_defined(dblk_addr));
+ HDassert(dblk_nelmts > 0);
+
+ /* Protect data block */
+ if(NULL == (dblock = H5EA__dblock_protect(hdr, dxpl_id, dblk_addr, dblk_nelmts, H5AC_WRITE)))
+ H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array data block, address = %llu", (unsigned long_long)dblk_addr)
+
+ /* Check if this is a paged data block */
+ if(dblk_nelmts > hdr->dblk_page_nelmts) {
+ size_t npages = dblk_nelmts / hdr->dblk_page_nelmts; /* Number of pages in data block */
+ haddr_t dblk_page_addr; /* Address of each data block page */
+ size_t dblk_page_size; /* Size of each data block page */
+ size_t u; /* Local index variable */
+
+ /* Set up initial state */
+ dblk_page_addr = dblk_addr + H5EA_DBLOCK_PREFIX_SIZE(dblock);
+ dblk_page_size = (hdr->dblk_page_nelmts * hdr->cparam.raw_elmt_size)
+ + H5EA_SIZEOF_CHKSUM;
+
+ /* Iterate over pages in data block */
+ for(u = 0; u < npages; u++) {
+#ifdef QAK
+HDfprintf(stderr, "%s: Expunging data block page from cache\n", FUNC);
+#endif /* QAK */
+ /* Evict the data block page from the metadata cache */
+ /* (OK to call if it doesn't exist in the cache) */
+ if(H5AC_expunge_entry(hdr->f, dxpl_id, H5AC_EARRAY_DBLK_PAGE, dblk_page_addr, H5AC__NO_FLAGS_SET) < 0)
+ H5E_THROW(H5E_CANTEXPUNGE, "unable to remove array data block page from metadata cache")
+#ifdef QAK
+HDfprintf(stderr, "%s: Done expunging data block page from cache\n", FUNC);
+#endif /* QAK */
+
+ /* Advance to next page address */
+ dblk_page_addr += dblk_page_size;
+ } /* end for */
+ } /* end if */
+
+CATCH
+ /* Finished deleting data block in metadata cache */
+ if(dblock && H5EA__dblock_unprotect(dblock, dxpl_id, H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0)
+ H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array data block")
+
+END_FUNC(PKG) /* end H5EA__dblock_delete() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__dblock_dest
+ *
+ * Purpose: Destroys an extensible array data block in memory.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 11 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+BEGIN_FUNC(PKG, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__dblock_dest(H5F_t UNUSED *f, H5EA_dblock_t *dblock))
+
+ /* Sanity check */
+ HDassert(dblock);
+
+ /* Check if shared header field has been initialized */
+ if(dblock->hdr) {
+ /* Check if we've got elements in the data block */
+ if(dblock->elmts && !dblock->npages) {
+ /* Free buffer for data block elements */
+ HDassert(dblock->nelmts > 0);
+ if(H5EA__hdr_free_elmts(dblock->hdr, dblock->nelmts, dblock->elmts) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to free extensible array data block element buffer")
+ dblock->elmts = NULL;
+ dblock->nelmts = 0;
+ } /* end if */
+
+ /* Decrement reference count on shared info */
+ if(H5EA__hdr_decr(dblock->hdr) < 0)
+ H5E_THROW(H5E_CANTDEC, "can't decrement reference count on shared array header")
+ dblock->hdr = NULL;
+ } /* end if */
+
+ /* Free the data block itself */
+ (void)H5FL_FREE(H5EA_dblock_t, dblock);
+
+CATCH
+
+END_FUNC(PKG) /* end H5EA__dblock_dest() */
+
diff --git a/src/H5EAhdr.c b/src/H5EAhdr.c
new file mode 100644
index 0000000..afbd6bd
--- /dev/null
+++ b/src/H5EAhdr.c
@@ -0,0 +1,720 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5EAhdr.c
+ * Aug 26 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: Array header routines for extensible arrays.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/**********************/
+/* Module Declaration */
+/**********************/
+
+#define H5EA_MODULE
+
+
+/***********************/
+/* Other Packages Used */
+/***********************/
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5EApkg.h" /* Extensible Arrays */
+#include "H5MFprivate.h" /* File memory management */
+#include "H5Vprivate.h" /* Vectors and arrays */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+/* Max. # of bits for max. nelmts index */
+#define H5EA_MAX_NELMTS_IDX_MAX 64
+
+/* # of elements in a data block for a particular super block */
+#define H5EA_SBLK_DBLK_NELMTS(s, m) \
+ (size_t)H5_EXP2(((s) + 1) / 2) * (m)
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+/* Alias for pointer to factory, for use when allocating sequences of them */
+typedef H5FL_fac_head_t *H5FL_fac_head_ptr_t;
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* Declare a free list to manage the H5EA_hdr_t struct */
+H5FL_DEFINE_STATIC(H5EA_hdr_t);
+
+/* Declare a free list to manage the H5FL_fac_head_ptr_t sequence information */
+H5FL_SEQ_DEFINE_STATIC(H5FL_fac_head_ptr_t);
+
+/* Declare a free list to manage the H5EA_sblk_info_t sequence information */
+H5FL_SEQ_DEFINE_STATIC(H5EA_sblk_info_t);
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__hdr_alloc
+ *
+ * Purpose: Allocate shared extensible array header
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Aug 26 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+H5EA_hdr_t *, NULL, NULL,
+H5EA__hdr_alloc(H5F_t *f, const H5EA_class_t *cls))
+
+ /* Local variables */
+ H5EA_hdr_t *hdr = NULL; /* Shared extensible array header */
+
+ /* Check arguments */
+ HDassert(f);
+ HDassert(cls);
+
+ /* Allocate space for the shared information */
+ if(NULL == (hdr = H5FL_CALLOC(H5EA_hdr_t)))
+ H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array shared header")
+
+ /* Set non-zero internal fields */
+ hdr->addr = HADDR_UNDEF;
+
+ /* Set the internal parameters for the array */
+ hdr->f = f;
+ hdr->sizeof_addr = H5F_SIZEOF_ADDR(f);
+ hdr->sizeof_size = H5F_SIZEOF_SIZE(f);
+
+ /* Set the class of the array */
+ hdr->cparam.cls = cls;
+
+ /* Set the return value */
+ ret_value = hdr;
+
+CATCH
+ if(!ret_value)
+ if(hdr && H5EA__hdr_dest(hdr) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array header")
+
+END_FUNC(PKG) /* end H5EA__hdr_alloc() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__hdr_init
+ *
+ * Purpose: Compute useful information for extensible array, based on
+ * "creation" information.
+ *
+ * Notes: The equations for variables below are based on this information:
+ *
+ * <sblk idx> <# of dblks> <size of dblks> Range of elements in sblk
+ * ========== ============ =============== =========================
+ * 0 1 1 * <dblk min elmts> 0 * <dblk min elmts> <-> 1 * <dblk min elmts> - 1
+ * 1 1 2 * <dblk min elmts> 1 * <dblk min elmts> <-> 3 * <dblk min elmts> - 1
+ * 2 2 2 * <dblk min elmts> 3 * <dblk min elmts> <-> 7 * <dblk min elmts> - 1
+ * 3 2 4 * <dblk min elmts> 7 * <dblk min elmts> <-> 15 * <dblk min elmts> - 1
+ * 4 4 4 * <dblk min elmts> 15 * <dblk min elmts> <-> 31 * <dblk min elmts> - 1
+ * 5 4 8 * <dblk min elmts> 31 * <dblk min elmts> <-> 63 * <dblk min elmts> - 1
+ * 6 8 8 * <dblk min elmts> 63 * <dblk min elmts> <-> 127 * <dblk min elmts> - 1
+ * 7 8 16 * <dblk min elmts> 127 * <dblk min elmts> <-> 255 * <dblk min elmts> - 1
+ * . . . * <dblk min elmts> . * <dblk min elmts> <-> . * <dblk min elmts> - 1
+ * . . . * <dblk min elmts> . * <dblk min elmts> <-> . * <dblk min elmts> - 1
+ * . . . * <dblk min elmts> . * <dblk min elmts> <-> . * <dblk min elmts> - 1
+ *
+ * Therefore:
+ * <sblk idx>(<elmt idx>) = lg2((<elmt idx> / <dblk min elmts>) + 1)
+ * <# of dblks>(<sblk idx>) = 2 ^ (<sblk idx> / 2)
+ * <size of dblk>(<sblk idx>) = 2 ^ ((<sblk idx> + 1) / 2)
+ * <total # of sblks>(<max. # of elmts>) = 1 + (lg2(<max. # of elmts>) - lg2(<dblk min_elmts>))
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 18 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__hdr_init(H5EA_hdr_t *hdr))
+
+ /* Local variables */
+ hsize_t start_idx; /* First element index for each super block */
+ hsize_t start_dblk; /* First data block index for each super block */
+ size_t u; /* Local index variable */
+
+ /* Sanity check */
+ HDassert(hdr);
+ HDassert(hdr->cparam.max_nelmts_bits);
+ HDassert(hdr->cparam.data_blk_min_elmts);
+ HDassert(hdr->cparam.sup_blk_min_data_ptrs);
+
+ /* Compute general information */
+ hdr->nsblks = 1 + (hdr->cparam.max_nelmts_bits - H5V_log2_of2(hdr->cparam.data_blk_min_elmts));
+ hdr->dblk_page_nelmts = (size_t)1 << hdr->cparam.max_dblk_page_nelmts_bits;
+ hdr->arr_off_size = (unsigned char)H5EA_SIZEOF_OFFSET_BITS(hdr->cparam.max_nelmts_bits);
+#ifdef QAK
+HDfprintf(stderr, "%s: hdr->nsblks = %Zu\n", FUNC, hdr->nsblks);
+#endif /* QAK */
+
+ /* Allocate information for each super block */
+ if(NULL == (hdr->sblk_info = H5FL_SEQ_MALLOC(H5EA_sblk_info_t, hdr->nsblks)))
+ H5E_THROW(H5E_CANTALLOC, "memory allocation failed for super block info array")
+
+ /* Compute information about each super block */
+ start_idx = 0;
+ start_dblk = 0;
+ for(u = 0; u < hdr->nsblks; u++) {
+ hdr->sblk_info[u].ndblks = (size_t)H5_EXP2(u / 2);
+ hdr->sblk_info[u].dblk_nelmts = H5EA_SBLK_DBLK_NELMTS(u, hdr->cparam.data_blk_min_elmts);
+ hdr->sblk_info[u].start_idx = start_idx;
+ hdr->sblk_info[u].start_dblk = start_dblk;
+#ifdef QAK
+HDfprintf(stderr, "%s: hdr->sblk_info[%Zu] = {%Zu, %Zu, %Hu, %Hu}\n", FUNC, u, hdr->sblk_info[u].ndblks, hdr->sblk_info[u].dblk_nelmts, hdr->sblk_info[u].start_idx, hdr->sblk_info[u].start_dblk);
+#endif /* QAK */
+
+ /* Advance starting indices for next super block */
+ start_idx += (hsize_t)hdr->sblk_info[u].ndblks * (hsize_t)hdr->sblk_info[u].dblk_nelmts;
+ start_dblk += (hsize_t)hdr->sblk_info[u].ndblks;
+ } /* end for */
+
+ /* Set size of header on disk */
+ hdr->size = H5EA_HEADER_SIZE(hdr);
+
+CATCH
+
+END_FUNC(PKG) /* end H5EA__hdr_init() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__hdr_alloc_elmts
+ *
+ * Purpose: Allocate extensible array data block elements
+ *
+ * Return: Non-NULL pointer to buffer for elements on success/NULL on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 16 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+void *, NULL, NULL,
+H5EA__hdr_alloc_elmts(H5EA_hdr_t *hdr, size_t nelmts))
+
+ /* Local variables */
+ void *elmts = NULL; /* Element buffer allocated */
+ unsigned idx; /* Index of element buffer factory in header */
+
+ /* Check arguments */
+ HDassert(hdr);
+ HDassert(nelmts > 0);
+
+ /* Compute the index of the element buffer factory */
+ H5_CHECK_OVERFLOW(nelmts, /*From:*/size_t, /*To:*/uint32_t);
+ idx = H5V_log2_of2((uint32_t)nelmts) - H5V_log2_of2((uint32_t)hdr->cparam.data_blk_min_elmts);
+#ifdef QAK
+HDfprintf(stderr, "%s: nelmts = %Zu, hdr->data_blk_min_elmts = %u, idx = %u\n", FUNC, nelmts, (unsigned)hdr->data_blk_min_elmts, idx);
+#endif /* QAK */
+
+ /* Check for needing to increase size of array of factories */
+ if(idx >= hdr->elmt_fac.nalloc) {
+ H5FL_fac_head_t **new_fac; /* New array of element factories */
+ size_t new_nalloc = MAX3(1, (idx + 1), (2 * hdr->elmt_fac.nalloc)); /* New number of factories allocated */
+
+ /* Re-allocate array of element factories */
+ if(NULL == (new_fac = H5FL_SEQ_REALLOC(H5FL_fac_head_ptr_t, hdr->elmt_fac.fac, new_nalloc)))
+ H5E_THROW(H5E_CANTALLOC, "memory allocation failed for data block data element buffer factory array")
+
+ /* Zero out new elements allocated */
+ HDmemset(new_fac + hdr->elmt_fac.nalloc, 0, (new_nalloc - hdr->elmt_fac.nalloc) * sizeof(H5FL_fac_head_ptr_t));
+
+ /* Update information about element factories in header */
+ hdr->elmt_fac.nalloc = new_nalloc;
+ hdr->elmt_fac.fac = new_fac;
+ } /* end if */
+
+ /* Check for un-initialized factory at index */
+ if(NULL == hdr->elmt_fac.fac[idx]) {
+ if(NULL == (hdr->elmt_fac.fac[idx] = H5FL_fac_init(nelmts * (size_t)hdr->cparam.cls->nat_elmt_size)))
+ H5E_THROW(H5E_CANTINIT, "can't create data block data element buffer factory")
+ } /* end if */
+
+ /* Allocate buffer for elements in index block */
+ if(NULL == (elmts = H5FL_FAC_MALLOC(hdr->elmt_fac.fac[idx])))
+ H5E_THROW(H5E_CANTALLOC, "memory allocation failed for data block data element buffer")
+
+ /* Set the return value */
+ ret_value = elmts;
+
+CATCH
+ if(!ret_value)
+ if(elmts)
+ (void)H5FL_FAC_FREE(hdr->elmt_fac.fac[idx], elmts);
+
+END_FUNC(PKG) /* end H5EA__hdr_alloc_elmts() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__hdr_free_elmts
+ *
+ * Purpose: Free extensible array data block elements
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 18 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, NOERR,
+herr_t, SUCCEED, -,
+H5EA__hdr_free_elmts(H5EA_hdr_t *hdr, size_t nelmts, void *elmts))
+
+ /* Local variables */
+ unsigned idx; /* Index of element buffer factory in header */
+
+ /* Check arguments */
+ HDassert(hdr);
+ HDassert(nelmts > 0);
+ HDassert(elmts);
+
+ /* Compute the index of the element buffer factory */
+ H5_CHECK_OVERFLOW(nelmts, /*From:*/size_t, /*To:*/uint32_t);
+ idx = H5V_log2_of2((uint32_t)nelmts) - H5V_log2_of2((uint32_t)hdr->cparam.data_blk_min_elmts);
+#ifdef QAK
+HDfprintf(stderr, "%s: nelmts = %Zu, hdr->data_blk_min_elmts = %u, idx = %u\n", FUNC, nelmts, (unsigned)hdr->data_blk_min_elmts, idx);
+#endif /* QAK */
+
+ /* Free buffer for elements in index block */
+ HDassert(idx < hdr->elmt_fac.nalloc);
+ HDassert(hdr->elmt_fac.fac[idx]);
+ (void)H5FL_FAC_FREE(hdr->elmt_fac.fac[idx], elmts);
+
+END_FUNC(PKG) /* end H5EA__hdr_free_elmts() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__hdr_create
+ *
+ * Purpose: Creates a new extensible array header in the file
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jun 17 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+haddr_t, HADDR_UNDEF, HADDR_UNDEF,
+H5EA__hdr_create(H5F_t *f, hid_t dxpl_id, const H5EA_create_t *cparam))
+
+ /* Local variables */
+ H5EA_hdr_t *hdr = NULL; /* Extensible array header */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Called\n", FUNC);
+#endif /* QAK */
+
+ /* Check arguments */
+ HDassert(f);
+ HDassert(cparam);
+
+#ifndef NDEBUG
+{
+ unsigned sblk_idx; /* Super block index for first "actual" super block */
+ size_t dblk_nelmts; /* Number of data block elements */
+ size_t dblk_page_nelmts; /* Number of elements in a data block page */
+
+ /* Check for valid parameters */
+ if(cparam->raw_elmt_size == 0)
+ H5E_THROW(H5E_BADVALUE, "element size must be greater than zero")
+ if(cparam->max_nelmts_bits == 0)
+ H5E_THROW(H5E_BADVALUE, "max. # of elements bits must be greater than zero")
+ if(cparam->max_nelmts_bits > H5EA_MAX_NELMTS_IDX_MAX)
+ H5E_THROW(H5E_BADVALUE, "max. # of elements bits must be <= %u", (unsigned)H5EA_MAX_NELMTS_IDX_MAX)
+ if(cparam->sup_blk_min_data_ptrs < 2)
+ H5E_THROW(H5E_BADVALUE, "min # of data block pointers in super block must be >= two")
+ if(!POWER_OF_TWO(cparam->sup_blk_min_data_ptrs))
+ H5E_THROW(H5E_BADVALUE, "min # of data block pointers in super block must be power of two")
+ if(!POWER_OF_TWO(cparam->data_blk_min_elmts))
+ H5E_THROW(H5E_BADVALUE, "min # of elements per data block must be power of two")
+ dblk_page_nelmts = (size_t)1 << cparam->max_dblk_page_nelmts_bits;
+ if(dblk_page_nelmts < cparam->idx_blk_elmts)
+ H5E_THROW(H5E_BADVALUE, "# of elements per data block page must be greater than # of elements in index block")
+
+ /* Compute the number of elements in data blocks for first actual super block */
+ sblk_idx = H5EA_SBLK_FIRST_IDX(cparam->sup_blk_min_data_ptrs);
+ dblk_nelmts = H5EA_SBLK_DBLK_NELMTS(sblk_idx, cparam->data_blk_min_elmts);
+ if(dblk_page_nelmts < dblk_nelmts)
+ H5E_THROW(H5E_BADVALUE, "max. # of elements per data block page bits must be > # of elements in first data block from super block")
+
+ if(cparam->max_dblk_page_nelmts_bits > cparam->max_nelmts_bits)
+ H5E_THROW(H5E_BADVALUE, "max. # of elements per data block page bits must be <= max. # of elements bits")
+}
+#endif /* NDEBUG */
+
+ /* Allocate space for the shared information */
+ if(NULL == (hdr = H5EA__hdr_alloc(f, cparam->cls)))
+ H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array shared header")
+
+ /* Set the internal parameters for the array */
+ hdr->idx_blk_addr = HADDR_UNDEF;
+
+ /* Set the creation parameters for the array */
+ HDmemcpy(&hdr->cparam, cparam, sizeof(hdr->cparam));
+
+ /* Finish initializing extensible array header */
+ if(H5EA__hdr_init(hdr) < 0)
+ H5E_THROW(H5E_CANTINIT, "initialization failed for extensible array header")
+
+ /* Allocate space for the header on disk */
+ if(HADDR_UNDEF == (hdr->addr = H5MF_alloc(f, H5FD_MEM_EARRAY_HDR, dxpl_id, (hsize_t)hdr->size)))
+ H5E_THROW(H5E_CANTALLOC, "file allocation failed for extensible array header")
+
+ /* Cache the new extensible array header */
+ if(H5AC_set(f, dxpl_id, H5AC_EARRAY_HDR, hdr->addr, hdr, H5AC__NO_FLAGS_SET) < 0)
+ H5E_THROW(H5E_CANTINSERT, "can't add extensible array header to cache")
+
+ /* Set address of array header to return */
+ ret_value = hdr->addr;
+
+CATCH
+ if(!H5F_addr_defined(ret_value))
+ if(hdr) {
+ /* Release header's disk space */
+ if(H5F_addr_defined(hdr->addr) && H5MF_xfree(f, H5FD_MEM_EARRAY_HDR, dxpl_id, hdr->addr, (hsize_t)hdr->size) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to free extensible array header")
+
+ /* Destroy header */
+ if(H5EA__hdr_dest(hdr) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array header")
+ } /* end if */
+
+END_FUNC(PKG) /* end H5EA__hdr_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__hdr_incr
+ *
+ * Purpose: Increment component reference count on shared array header
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Aug 26 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__hdr_incr(H5EA_hdr_t *hdr))
+
+ /* Sanity check */
+ HDassert(hdr);
+
+ /* Mark header as un-evictable when something is depending on it */
+ if(hdr->rc == 0)
+ if(H5AC_pin_protected_entry(hdr->f, hdr) < 0)
+ H5E_THROW(H5E_CANTPIN, "unable to pin extensible array header")
+
+ /* Increment reference count on shared header */
+ hdr->rc++;
+
+CATCH
+
+END_FUNC(PKG) /* end H5EA__hdr_incr() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__hdr_decr
+ *
+ * Purpose: Decrement component reference count on shared array header
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Aug 26 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__hdr_decr(H5EA_hdr_t *hdr))
+
+ /* Sanity check */
+ HDassert(hdr);
+ HDassert(hdr->rc);
+
+ /* Decrement reference count on shared header */
+ hdr->rc--;
+
+ /* Mark header as evictable again when nothing depend on it */
+ if(hdr->rc == 0) {
+ HDassert(hdr->file_rc == 0);
+ if(H5AC_unpin_entry(hdr->f, hdr) < 0)
+ H5E_THROW(H5E_CANTUNPIN, "unable to unpin extensible array header")
+ } /* end if */
+
+CATCH
+
+END_FUNC(PKG) /* end H5EA__hdr_decr() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__hdr_fuse_incr
+ *
+ * Purpose: Increment file reference count on shared array header
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Aug 26 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, NOERR,
+herr_t, SUCCEED, -,
+H5EA__hdr_fuse_incr(H5EA_hdr_t *hdr))
+
+ /* Sanity check */
+ HDassert(hdr);
+
+ /* Increment file reference count on shared header */
+ hdr->file_rc++;
+
+END_FUNC(PKG) /* end H5EA__hdr_fuse_incr() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__hdr_fuse_decr
+ *
+ * Purpose: Decrement file reference count on shared array header
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Aug 26 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, NOERR,
+size_t, 0, -,
+H5EA__hdr_fuse_decr(H5EA_hdr_t *hdr))
+
+ /* Sanity check */
+ HDassert(hdr);
+ HDassert(hdr->file_rc);
+
+ /* Decrement file reference count on shared header */
+ hdr->file_rc--;
+
+ /* Set return value */
+ ret_value = hdr->file_rc;
+
+END_FUNC(PKG) /* end H5EA__hdr_fuse_decr() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__hdr_modified
+ *
+ * Purpose: Mark an extensible array as modified
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 9 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__hdr_modified(H5EA_hdr_t *hdr))
+
+ /* Sanity check */
+ HDassert(hdr);
+ HDassert(hdr->f);
+
+ /* Mark header as dirty in cache */
+ if(H5AC_mark_pinned_or_protected_entry_dirty(hdr->f, hdr) < 0)
+ H5E_THROW(H5E_CANTMARKDIRTY, "unable to mark extensible array header as dirty")
+
+CATCH
+
+END_FUNC(PKG) /* end H5EA__hdr_modified() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__hdr_delete
+ *
+ * Purpose: Delete an extensible array, starting with the header
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Aug 26 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__hdr_delete(H5EA_hdr_t *hdr, hid_t dxpl_id))
+
+ /* Sanity check */
+ HDassert(hdr);
+ HDassert(!hdr->file_rc);
+
+#ifndef NDEBUG
+{
+ unsigned hdr_status = 0; /* Array header's status in the metadata cache */
+
+ /* Check the array header's status in the metadata cache */
+ if(H5AC_get_entry_status(hdr->f, hdr->addr, &hdr_status) < 0)
+ H5E_THROW(H5E_CANTGET, "unable to check metadata cache status for array header")
+
+ /* Sanity checks on array header */
+ HDassert(hdr_status & H5AC_ES__IN_CACHE);
+ HDassert(hdr_status & H5AC_ES__IS_PROTECTED);
+} /* end block */
+#endif /* NDEBUG */
+
+ /* Check for index block */
+ if(H5F_addr_defined(hdr->idx_blk_addr)) {
+#ifdef QAK
+HDfprintf(stderr, "%s: hdr->idx_blk_addr = %a\n", FUNC, hdr->idx_blk_addr);
+#endif /* QAK */
+ /* Delete index block */
+ if(H5EA__iblock_delete(hdr, dxpl_id) < 0)
+ H5E_THROW(H5E_CANTDELETE, "unable to delete extensible array index block")
+ } /* end if */
+
+ /* Finished deleting header */
+ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_EARRAY_HDR, hdr->addr, hdr, H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0)
+ H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array header")
+ hdr = NULL;
+
+CATCH
+
+ /* Unprotect the header, if an error occurred */
+ if(hdr && H5AC_unprotect(hdr->f, dxpl_id, H5AC_EARRAY_HDR, hdr->addr, hdr, H5AC__NO_FLAGS_SET) < 0)
+ H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array header")
+
+END_FUNC(PKG) /* end H5EA__hdr_delete() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__hdr_dest
+ *
+ * Purpose: Destroys an extensible array header in memory.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 11 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__hdr_dest(H5EA_hdr_t *hdr))
+
+ /* Check arguments */
+ HDassert(hdr);
+ HDassert(hdr->rc == 0);
+
+ /* Check for data block element buffer factory info to free */
+ if(hdr->elmt_fac.fac) {
+ unsigned u; /* Local index variable */
+
+ /* Sanity check */
+ HDassert(hdr->elmt_fac.nalloc > 0);
+
+ /* Iterate over factories, shutting them down */
+ for(u = 0; u < hdr->elmt_fac.nalloc; u++) {
+ /* Check if this factory has been initialized */
+ if(hdr->elmt_fac.fac[u]) {
+ if(H5FL_fac_term(hdr->elmt_fac.fac[u]) < 0)
+ H5E_THROW(H5E_CANTRELEASE, "unable to destroy extensible array header factory")
+ hdr->elmt_fac.fac[u] = NULL;
+ } /* end if */
+ } /* end for */
+
+ /* Free factory array */
+ hdr->elmt_fac.fac = (H5FL_fac_head_t **)H5FL_SEQ_FREE(H5FL_fac_head_ptr_t, hdr->elmt_fac.fac);
+ } /* end if */
+
+ /* Free the super block info array */
+ if(hdr->sblk_info)
+ hdr->sblk_info = (H5EA_sblk_info_t *)H5FL_SEQ_FREE(H5EA_sblk_info_t, hdr->sblk_info);
+
+ /* Free the shared info itself */
+ (void)H5FL_FREE(H5EA_hdr_t, hdr);
+
+CATCH
+
+END_FUNC(PKG) /* end H5EA__hdr_dest() */
+
diff --git a/src/H5EAiblock.c b/src/H5EAiblock.c
new file mode 100644
index 0000000..dcb75d1
--- /dev/null
+++ b/src/H5EAiblock.c
@@ -0,0 +1,468 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5EAiblock.c
+ * Sep 9 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: Index block routines for extensible arrays.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/**********************/
+/* Module Declaration */
+/**********************/
+
+#define H5EA_MODULE
+
+
+/***********************/
+/* Other Packages Used */
+/***********************/
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5EApkg.h" /* Extensible Arrays */
+#include "H5FLprivate.h" /* Free Lists */
+#include "H5MFprivate.h" /* File memory management */
+#include "H5Vprivate.h" /* Vectors and arrays */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* Declare a free list to manage the H5EA_iblock_t struct */
+H5FL_DEFINE_STATIC(H5EA_iblock_t);
+
+/* Declare a free list to manage the index block elements */
+H5FL_BLK_DEFINE_STATIC(idx_blk_elmt_buf);
+
+/* Declare a free list to manage the haddr_t sequence information */
+H5FL_SEQ_DEFINE_STATIC(haddr_t);
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__iblock_alloc
+ *
+ * Purpose: Allocate extensible array index block
+ *
+ * Return: Non-NULL pointer to index block on success/NULL on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 9 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+H5EA_iblock_t *, NULL, NULL,
+H5EA__iblock_alloc(H5EA_hdr_t *hdr))
+
+ /* Local variables */
+ H5EA_iblock_t *iblock = NULL; /* Extensible array index block */
+
+ /* Check arguments */
+ HDassert(hdr);
+
+ /* Allocate memory for the index block */
+ if(NULL == (iblock = H5FL_CALLOC(H5EA_iblock_t)))
+ H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array index block")
+
+ /* Share common array information */
+ if(H5EA__hdr_incr(hdr) < 0)
+ H5E_THROW(H5E_CANTINC, "can't increment reference count on shared array header")
+ iblock->hdr = hdr;
+
+ /* Set non-zero internal fields */
+ iblock->addr = HADDR_UNDEF;
+
+ /* Compute information */
+ iblock->nsblks = H5EA_SBLK_FIRST_IDX(hdr->cparam.sup_blk_min_data_ptrs);
+ iblock->ndblk_addrs = 2 * ((size_t)hdr->cparam.sup_blk_min_data_ptrs - 1);
+ iblock->nsblk_addrs = hdr->nsblks - iblock->nsblks;
+#ifdef QAK
+HDfprintf(stderr, "%s: iblock->nsblks = %u\n", FUNC, iblock->nsblks);
+HDfprintf(stderr, "%s: iblock->ndblk_addrs = %Zu\n", FUNC, iblock->ndblk_addrs);
+HDfprintf(stderr, "%s: iblock->nsblk_addrs = %Zu\n", FUNC, iblock->nsblk_addrs);
+#endif /* QAK */
+
+ /* Allocate buffer for elements in index block */
+ if(hdr->cparam.idx_blk_elmts > 0)
+ if(NULL == (iblock->elmts = H5FL_BLK_MALLOC(idx_blk_elmt_buf, (size_t)(hdr->cparam.idx_blk_elmts * hdr->cparam.cls->nat_elmt_size))))
+ H5E_THROW(H5E_CANTALLOC, "memory allocation failed for index block data element buffer")
+
+ /* Allocate buffer for data block addresses in index block */
+ if(iblock->ndblk_addrs > 0)
+ if(NULL == (iblock->dblk_addrs = H5FL_SEQ_MALLOC(haddr_t, iblock->ndblk_addrs)))
+ H5E_THROW(H5E_CANTALLOC, "memory allocation failed for index block data block addresses")
+
+ /* Allocate buffer for super block addresses in index block */
+ if(iblock->nsblk_addrs > 0)
+ if(NULL == (iblock->sblk_addrs = H5FL_SEQ_MALLOC(haddr_t, iblock->nsblk_addrs)))
+ H5E_THROW(H5E_CANTALLOC, "memory allocation failed for index block super block addresses")
+
+ /* Set the return value */
+ ret_value = iblock;
+
+CATCH
+ if(!ret_value)
+ if(iblock && H5EA__iblock_dest(hdr->f, iblock) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array index block")
+
+END_FUNC(PKG) /* end H5EA__iblock_alloc() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__iblock_create
+ *
+ * Purpose: Creates a new extensible array index block in the file
+ *
+ * Return: Valid file address on success/HADDR_UNDEF on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 9 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+haddr_t, HADDR_UNDEF, HADDR_UNDEF,
+H5EA__iblock_create(H5EA_hdr_t *hdr, hid_t dxpl_id))
+
+ /* Local variables */
+ H5EA_iblock_t *iblock = NULL; /* Extensible array index block */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Called\n", FUNC);
+#endif /* QAK */
+
+ /* Sanity check */
+ HDassert(hdr);
+
+ /* Allocate the index block */
+ if(NULL == (iblock = H5EA__iblock_alloc(hdr)))
+ H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array index block")
+
+ /* Set size of index block on disk */
+ iblock->size = H5EA_IBLOCK_SIZE(iblock);
+#ifdef QAK
+HDfprintf(stderr, "%s: iblock->size = %Zu\n", FUNC, iblock->size);
+#endif /* QAK */
+
+ /* Allocate space for the index block on disk */
+ if(HADDR_UNDEF == (iblock->addr = H5MF_alloc(hdr->f, H5FD_MEM_EARRAY_IBLOCK, dxpl_id, (hsize_t)iblock->size)))
+ H5E_THROW(H5E_CANTALLOC, "file allocation failed for extensible array index block")
+
+ /* Clear any elements in index block to fill value */
+ if(hdr->cparam.idx_blk_elmts > 0) {
+ /* Call the class's 'fill' callback */
+ if((hdr->cparam.cls->fill)(iblock->elmts, (size_t)hdr->cparam.idx_blk_elmts) < 0)
+ H5E_THROW(H5E_CANTSET, "can't set extensible array index block elements to class's fill value")
+ } /* end if */
+
+ /* Reset any data block addresses in the index block */
+ if(iblock->ndblk_addrs > 0) {
+ haddr_t tmp_addr = HADDR_UNDEF; /* Address value to fill data block addresses with */
+
+ /* Set all the data block addresses to "undefined" address value */
+ H5V_array_fill(iblock->dblk_addrs, &tmp_addr, sizeof(haddr_t), iblock->ndblk_addrs);
+ } /* end if */
+
+ /* Reset any super block addresses in the index block */
+ if(iblock->nsblk_addrs > 0) {
+ haddr_t tmp_addr = HADDR_UNDEF; /* Address value to fill super block addresses with */
+
+ /* Set all the super block addresses to "undefined" address value */
+ H5V_array_fill(iblock->sblk_addrs, &tmp_addr, sizeof(haddr_t), iblock->nsblk_addrs);
+ } /* end if */
+
+ /* Cache the new extensible array index block */
+ if(H5AC_set(hdr->f, dxpl_id, H5AC_EARRAY_IBLOCK, iblock->addr, iblock, H5AC__NO_FLAGS_SET) < 0)
+ H5E_THROW(H5E_CANTINSERT, "can't add extensible array index block to cache")
+
+ /* Set address of index block to return */
+ ret_value = iblock->addr;
+
+CATCH
+ if(!H5F_addr_defined(ret_value))
+ if(iblock) {
+ /* Release index block's disk space */
+ if(H5F_addr_defined(iblock->addr) && H5MF_xfree(hdr->f, H5FD_MEM_EARRAY_IBLOCK, dxpl_id, iblock->addr, (hsize_t)iblock->size) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to release extensible array index block")
+
+ /* Destroy index block */
+ if(H5EA__iblock_dest(hdr->f, iblock) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array index block")
+ } /* end if */
+
+END_FUNC(PKG) /* end H5EA__iblock_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__iblock_protect
+ *
+ * Purpose: Convenience wrapper around protecting extensible array index block
+ *
+ * Return: Non-NULL pointer to index block on success/NULL on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 9 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+H5EA_iblock_t *, NULL, NULL,
+H5EA__iblock_protect(H5EA_hdr_t *hdr, hid_t dxpl_id, H5AC_protect_t rw))
+
+ /* Local variables */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Called\n", FUNC);
+#endif /* QAK */
+
+ /* Sanity check */
+ HDassert(hdr);
+
+ /* Protect the index block */
+ if(NULL == (ret_value = (H5EA_iblock_t *)H5AC_protect(hdr->f, dxpl_id, H5AC_EARRAY_IBLOCK, hdr->idx_blk_addr, NULL, hdr, rw)))
+ H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array index block, address = %llu", (unsigned long_long)hdr->idx_blk_addr)
+
+CATCH
+
+END_FUNC(PKG) /* end H5EA__iblock_protect() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__iblock_unprotect
+ *
+ * Purpose: Convenience wrapper around unprotecting extensible array index block
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 9 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__iblock_unprotect(H5EA_iblock_t *iblock, hid_t dxpl_id, unsigned cache_flags))
+
+ /* Local variables */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Called\n", FUNC);
+#endif /* QAK */
+
+ /* Sanity check */
+ HDassert(iblock);
+
+ /* Unprotect the index block */
+ if(H5AC_unprotect(iblock->hdr->f, dxpl_id, H5AC_EARRAY_IBLOCK, iblock->addr, iblock, cache_flags) < 0)
+ H5E_THROW(H5E_CANTUNPROTECT, "unable to unprotect extensible array index block, address = %llu", (unsigned long_long)iblock->addr)
+
+CATCH
+
+END_FUNC(PKG) /* end H5EA__iblock_unprotect() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__iblock_delete
+ *
+ * Purpose: Delete index block
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 9 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__iblock_delete(H5EA_hdr_t *hdr, hid_t dxpl_id))
+
+ /* Local variables */
+ H5EA_iblock_t *iblock = NULL; /* Pointer to index block */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Called\n", FUNC);
+#endif /* QAK */
+
+ /* Sanity check */
+ HDassert(hdr);
+ HDassert(H5F_addr_defined(hdr->idx_blk_addr));
+
+ /* Protect index block */
+ if(NULL == (iblock = H5EA__iblock_protect(hdr, dxpl_id, H5AC_WRITE)))
+ H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array index block, address = %llu", (unsigned long_long)hdr->idx_blk_addr)
+
+ /* Check for index block having data block pointers */
+ if(iblock->ndblk_addrs > 0) {
+ unsigned sblk_idx; /* Current super block index */
+ unsigned dblk_idx; /* Current data block index w/in super block */
+ size_t u; /* Local index variable */
+
+ /* Iterate over data blocks */
+ sblk_idx = dblk_idx = 0;
+ for(u = 0; u < iblock->ndblk_addrs; u++) {
+ /* Check for data block existing */
+ if(H5F_addr_defined(iblock->dblk_addrs[u])) {
+ /* Delete data block */
+ if(H5EA__dblock_delete(hdr, dxpl_id, iblock->dblk_addrs[u], hdr->sblk_info[sblk_idx].dblk_nelmts) < 0)
+ H5E_THROW(H5E_CANTDELETE, "unable to delete extensible array data block")
+ iblock->dblk_addrs[u] = HADDR_UNDEF;
+ } /* end if */
+
+ /* Advance to next data block w/in super block */
+ dblk_idx++;
+
+ /* Check for moving to next super block */
+ if(dblk_idx >= hdr->sblk_info[sblk_idx].ndblks) {
+ sblk_idx++;
+ dblk_idx = 0;
+ } /* end if */
+ } /* end for */
+ } /* end if */
+
+ /* Check for index block having data block pointers (not yet) */
+ if(iblock->nsblk_addrs > 0) {
+ size_t u; /* Local index variable */
+
+ /* Iterate over super blocks */
+ for(u = 0; u < iblock->nsblk_addrs; u++) {
+ /* Check for data block existing */
+ if(H5F_addr_defined(iblock->sblk_addrs[u])) {
+ /* Delete super block */
+ if(H5EA__sblock_delete(hdr, dxpl_id, iblock->sblk_addrs[u], (unsigned)(u + iblock->nsblks)) < 0)
+ H5E_THROW(H5E_CANTDELETE, "unable to delete extensible array super block")
+ iblock->sblk_addrs[u] = HADDR_UNDEF;
+ } /* end if */
+ } /* end for */
+ } /* end if */
+
+CATCH
+ /* Finished deleting index block in metadata cache */
+ if(iblock && H5EA__iblock_unprotect(iblock, dxpl_id, H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0)
+ H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array index block")
+
+END_FUNC(PKG) /* end H5EA__iblock_delete() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__iblock_dest
+ *
+ * Purpose: Destroys an extensible array index block in memory.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 11 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+BEGIN_FUNC(PKG, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__iblock_dest(H5F_t *f, H5EA_iblock_t *iblock))
+
+ /* Sanity check */
+ HDassert(iblock);
+ HDassert(iblock->rc == 0);
+
+ /* Check if shared header field has been initialized */
+ if(iblock->hdr) {
+ /* Set the shared array header's file context for this operation */
+ iblock->hdr->f = f;
+
+ /* Check if we've got elements in the index block */
+ if(iblock->elmts) {
+ /* Free buffer for index block elements */
+ HDassert(iblock->hdr->cparam.idx_blk_elmts > 0);
+ iblock->elmts = H5FL_BLK_FREE(idx_blk_elmt_buf, iblock->elmts);
+ } /* end if */
+
+ /* Check if we've got data block addresses in the index block */
+ if(iblock->dblk_addrs) {
+ /* Free buffer for index block data block addresses */
+ HDassert(iblock->ndblk_addrs > 0);
+ iblock->dblk_addrs = H5FL_SEQ_FREE(haddr_t, iblock->dblk_addrs);
+ iblock->ndblk_addrs = 0;
+ } /* end if */
+
+ /* Check if we've got super block addresses in the index block */
+ if(iblock->sblk_addrs) {
+ /* Free buffer for index block super block addresses */
+ HDassert(iblock->nsblk_addrs > 0);
+ iblock->sblk_addrs = H5FL_SEQ_FREE(haddr_t, iblock->sblk_addrs);
+ iblock->nsblk_addrs = 0;
+ } /* end if */
+
+ /* Decrement reference count on shared info */
+ if(H5EA__hdr_decr(iblock->hdr) < 0)
+ H5E_THROW(H5E_CANTDEC, "can't decrement reference count on shared array header")
+ iblock->hdr = NULL;
+ } /* end if */
+
+ /* Free the index block itself */
+ (void)H5FL_FREE(H5EA_iblock_t, iblock);
+
+CATCH
+
+END_FUNC(PKG) /* end H5EA__iblock_dest() */
+
diff --git a/src/H5EAint.c b/src/H5EAint.c
new file mode 100644
index 0000000..a53d4f9
--- /dev/null
+++ b/src/H5EAint.c
@@ -0,0 +1,81 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5EAint.c
+ * Jun 17 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: Internal routines for extnsible arrays.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/**********************/
+/* Module Declaration */
+/**********************/
+
+#define H5EA_MODULE
+
+
+/***********************/
+/* Other Packages Used */
+/***********************/
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5EApkg.h" /* Extensible Arrays */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
diff --git a/src/H5EApkg.h b/src/H5EApkg.h
new file mode 100644
index 0000000..51305c4
--- /dev/null
+++ b/src/H5EApkg.h
@@ -0,0 +1,698 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Programmer: Quincey Koziol <koziol@hdfgroup.org>
+ * Tuesday, June 17, 2008
+ *
+ * Purpose: This file contains declarations which are visible only within
+ * the H5EA package. Source files outside the H5EA package should
+ * include H5EAprivate.h instead.
+ */
+#if !(defined(H5EA_PACKAGE) | defined(H5EA_MODULE))
+#error "Do not include this file outside the H5EA package!"
+#endif
+
+#ifndef _H5EApkg_H
+#define _H5EApkg_H
+
+/* Get package's private header */
+#include "H5EAprivate.h"
+
+/* Other private headers needed by this file */
+#include "H5ACprivate.h" /* Metadata cache */
+#include "H5FLprivate.h" /* Free Lists */
+
+/************************************************/
+/* Revisions to FUNC_ENTER/LEAVE & Error Macros */
+/************************************************/
+
+#ifndef NDEBUG
+/* `S' is the name of a function which is being tested to check if it's */
+/* a public API function */
+#define H5_IS_PUB(S) (((HDisdigit(S[1]) || HDisupper(S[1])) && HDislower(S[2])) || \
+ ((HDisdigit(S[2]) || HDisupper(S[2])) && HDislower(S[3])) || \
+ (!S[4] || ((HDisdigit(S[3]) || HDisupper(S[3])) && HDislower(S[4]))))
+
+/* `S' is the name of a function which is being tested to check if it's */
+/* a private library function */
+#define H5_IS_PRIV(S) (((HDisdigit(S[1]) || HDisupper(S[1])) && '_' == S[2] && HDislower(S[3])) || \
+ ((HDisdigit(S[2]) || HDisupper(S[2])) && '_' == S[3] && HDislower(S[4])) || \
+ ((HDisdigit(S[3]) || HDisupper(S[3])) && '_' == S[4] && HDislower(S[5])))
+
+/* `S' is the name of a function which is being tested to check if it's */
+/* a package private function */
+#define H5_IS_PKG(S) (((HDisdigit(S[1]) || HDisupper(S[1])) && '_' == S[2] && '_' == S[3] && HDislower(S[4])) || \
+ ((HDisdigit(S[2]) || HDisupper(S[2])) && '_' == S[3] && '_' == S[4] && HDislower(S[5])) || \
+ ((HDisdigit(S[3]) || HDisupper(S[3])) && '_' == S[4] && '_' == S[5] && HDislower(S[6])))
+
+#define FUNC_ENTER_NAME_CHECK(asrt) \
+ { \
+ static hbool_t func_check = FALSE; \
+ \
+ if(!func_check) { \
+ /* Check function naming status */ \
+ HDassert(asrt); \
+ \
+ /* Don't check again */ \
+ func_check = TRUE; \
+ } /* end if */ \
+ } /* end scope */
+#else /* NDEBUG */
+#define FUNC_ENTER_NAME_CHECK(asrt)
+#define H5_IS_PUB(S)
+#define H5_IS_PRIV(S)
+#define H5_IS_PKG(S)
+#endif /* NDEBUG */
+
+/* Macro for referencing package initialization variables */
+#define H5_PACKAGE_INIT_VAR(x) H5_GLUE3(H5_, x, _init_g)
+
+/* Macros to check if a package is initialized */
+#define H5_CHECK_PACKAGE_INIT_REG_YES(asrt) HDassert(H5_PACKAGE_INIT_VAR(pkg));
+#define H5_CHECK_PACKAGE_INIT_REG_NO(asrt)
+#define H5_CHECK_PACKAGE_INIT_INIT_YES(asrt)
+#define H5_CHECK_PACKAGE_INIT_INIT_NO(asrt)
+
+/* Macros to initialize package, if a package initialization routine is defined */
+#define H5_PKG_YES_INIT(pkg) \
+ if(!H5_PACKAGE_INIT_VAR(pkg)) { \
+ if(H5_GLUE(pkg, _pkg_init)() < 0) { \
+ /* (Can't use H5E_THROW here) */ \
+ H5E_PRINTF(H5E_CANTINIT, "interface initialization failed"); \
+ ret_value = fail_value; \
+ goto func_init_failed; \
+ } /* end if */ \
+ } /* end if */
+#define H5_PKG_NO_INIT(pkg)
+
+/* Macros to declare package initialization variable, if a package initialization routine is defined */
+#define H5_PKG_YES_INIT_VAR(pkg) extern hbool_t H5_PACKAGE_INIT_VAR(H5_MY_PKG);
+#define H5_PKG_NO_INIT_VAR(pkg)
+
+/* Declare package initialization variable (if in a package) */
+#define H5_DECLARE_PKG_VAR(pkg_init, pkg) H5_GLUE3(H5_PKG_, pkg_init, _INIT_VAR)(pkg)
+#ifdef H5_MY_PKG
+H5_DECLARE_PKG_VAR(H5_MY_PKG_INIT, H5_MY_PKG)
+#endif /* H5_MY_PKG */
+
+/* API re-entrance variable */
+extern hbool_t H5_api_entered_g; /* Has library already been entered through API? */
+
+/* Use FUNC to safely handle variations of C99 __func__ keyword handling */
+#ifdef H5_HAVE_C99_FUNC
+#define FUNC __func__
+#elif defined(H5_HAVE_FUNCTION)
+#define FUNC __FUNCTION__
+#else
+#error "We need __func__ or __FUNCTION__ to test function names!"
+#endif
+
+/* Macros for entering different scopes of routines */
+#define H5_PACKAGE_ENTER(pkg, pkg_init, init) \
+ FUNC_ENTER_NAME_CHECK(H5_IS_PKG(FUNC)) \
+ \
+ /* The library should be initialized already */ \
+ HDassert(H5_INIT_GLOBAL); \
+ \
+ /* This interface should be initialized already */ \
+ /* (except for package initialization routines :-) */ \
+ H5_GLUE4(H5_CHECK_PACKAGE_INIT_, init, _, pkg_init)(pkg) \
+ \
+ /* Push the name of this function on the function stack */ \
+ H5_PUSH_FUNC(FUNC) \
+ \
+ /* Enter scope for this type of function */ \
+ {
+
+#define H5_PRIVATE_ENTER(pkg, pkg_init) \
+ FUNC_ENTER_NAME_CHECK(H5_IS_PRIV(FUNC)) \
+ \
+ /* The library should be initialized already */ \
+ HDassert(H5_INIT_GLOBAL); \
+ \
+ /* Initialize this interface if desired */ \
+ H5_GLUE3(H5_PKG_, pkg_init, _INIT)(pkg) \
+ \
+ /* Push the name of this function on the function stack */ \
+ H5_PUSH_FUNC(FUNC) \
+ \
+ /* Enter scope for this type of function */ \
+ {{
+
+#define H5_PUBLIC_ENTER(pkg, pkg_init) \
+ FUNC_ENTER_API_VARS(FUNC) \
+ FUNC_ENTER_API_THREADSAFE; \
+ FUNC_ENTER_NAME_CHECK(H5_IS_PUB(FUNC)) \
+ \
+ /* Clear thread error stack when entering public functions */ \
+ H5E_clear_stack(NULL); \
+ \
+ /* Initialize the library or bust */ \
+ if(!(H5_INIT_GLOBAL)) { \
+ H5_INIT_GLOBAL = TRUE; \
+ if(H5_init_library() < 0) { \
+ /* (Can't use H5E_THROW here) */ \
+ H5E_PRINTF(H5E_CANTINIT, "interface initialization failed"); \
+ ret_value = fail_value; \
+ goto func_init_failed; \
+ } /* end if */ \
+ } /* end if */ \
+ \
+ /* Initialize this interface if desired */ \
+ H5_GLUE3(H5_PKG_, pkg_init, _INIT)(pkg) \
+ \
+ /* Check for re-entering API routine */ \
+ HDassert(!H5_api_entered_g); \
+ H5_api_entered_g = TRUE; \
+ \
+ /* Start logging MPI's MPE information */ \
+ BEGIN_MPE_LOG(FUNC) \
+ \
+ /* Push the name of this function on the function stack */ \
+ H5_PUSH_FUNC(FUNC) \
+ \
+ /* Enter scope for this type of function */ \
+ {{{
+
+/* Macros for substituting the package name */
+#define FUNC_ENTER_STATIC H5_PACKAGE_ENTER(H5_MY_PKG, H5_MY_PKG_INIT, REG)
+#define FUNC_ENTER_PKGINIT H5_PACKAGE_ENTER(H5_MY_PKG, H5_MY_PKG_INIT, INIT)
+#define FUNC_ENTER_PKG H5_PACKAGE_ENTER(H5_MY_PKG, H5_MY_PKG_INIT, REG)
+#define FUNC_ENTER_PRIV H5_PRIVATE_ENTER(H5_MY_PKG, H5_MY_PKG_INIT)
+#define FUNC_ENTER_PUB H5_PUBLIC_ENTER(H5_MY_PKG, H5_MY_PKG_INIT)
+
+/* Macros for substituting a function prefix */
+#define FUNC_PREFIX_STATIC static
+#define FUNC_PREFIX_PKGINIT
+#define FUNC_PREFIX_PKG
+#define FUNC_PREFIX_PRIV
+#define FUNC_PREFIX_PUB
+
+/* Macros for declaring error variables */
+#define FUNC_ERR_VAR_ERR(ret_typ, err) \
+ hbool_t past_catch = FALSE; \
+ ret_typ fail_value = err;
+#define FUNC_ERR_VAR_ERRCATCH(ret_typ, err) \
+ hbool_t past_catch = FALSE;
+#define FUNC_ERR_VAR_NOERR(ret_typ, err)
+
+/* Use this macro when entering all functions */
+#define BEGIN_FUNC(scope, use_err, ret_typ, ret_init, err, func) \
+H5_GLUE(FUNC_PREFIX_, scope) \
+ret_typ \
+func \
+/* Open function */ \
+{ \
+ ret_typ ret_value = ret_init; \
+ H5_GLUE(FUNC_ERR_VAR_, use_err)(ret_typ, err) \
+ H5_GLUE(FUNC_ENTER_, scope)
+
+/* Macros for label when a function initialization can fail */
+#define H5_PRIV_YES_FUNC_INIT_FAILED func_init_failed:
+#define H5_PRIV_NO_FUNC_INIT_FAILED
+#define H5_PRIV_FUNC_INIT_FAILED(pkg_init) H5_GLUE3(H5_PRIV_, pkg_init, _FUNC_INIT_FAILED)
+
+/* Macros for leaving different scopes of routines */
+#define FUNC_LEAVE_STATIC \
+ /* Leave scope for this type of function */ \
+ } \
+ \
+ /* Pop the name of this function off the function stack */ \
+ H5_POP_FUNC
+
+#define FUNC_LEAVE_PKG \
+ /* Leave scope for this type of function */ \
+ } \
+ \
+ /* Pop the name of this function off the function stack */ \
+ H5_POP_FUNC
+
+#define FUNC_LEAVE_PRIV \
+ /* Leave scope for this type of function */ \
+ }} \
+ \
+ /* Label for errors during FUNC_ENTER */ \
+ H5_PRIV_FUNC_INIT_FAILED(H5_MY_PKG_INIT) \
+ \
+ /* Pop the name of this function off the function stack */ \
+ H5_POP_FUNC
+
+#define FUNC_LEAVE_PUB \
+ /* Leave scope for this type of function */ \
+ }}} \
+ \
+ /* Label for errors during FUNC_ENTER */ \
+func_init_failed: \
+ \
+ /* Dump error stack if an error occurred during API routine */ \
+ if(ret_value == fail_value) \
+ (void)H5E_dump_api_stack(TRUE); \
+ \
+ /* Finish the API tracing info */ \
+ H5TRACE_RETURN(ret_value); \
+ \
+ /* Pop the name of this function off the function stack */ \
+ H5_POP_FUNC \
+ \
+ /* Finish the MPE tracing info */ \
+ FINISH_MPE_LOG; \
+ \
+ /* Check for leaving API routine */ \
+ HDassert(H5_api_entered_g); \
+ H5_api_entered_g = FALSE; \
+ \
+ /* Release thread-safety semaphore */ \
+ FUNC_LEAVE_API_THREADSAFE
+
+/* Use this macro when leaving all functions */
+#define END_FUNC(scope) \
+ /* Scope-specific function conclusion */ \
+ H5_GLUE(FUNC_LEAVE_, scope) \
+ \
+ /* Leave routine */ \
+ return(ret_value); \
+ \
+ /* Close Function */ \
+}
+
+
+/*
+ * H5E_PRINTF macro, used to facilitate error reporting between a BEGIN_FUNC()
+ * and an END_FUNC() within a function body. The arguments are the minor
+ * error number, a description of the error (as a printf-like format string),
+ * and an optional set of arguments for the printf format arguments.
+ */
+#define H5E_PRINTF(...) H5E_printf_stack(NULL, __FILE__, FUNC, __LINE__, H5E_ERR_CLS_g, H5_MY_PKG_ERR, __VA_ARGS__)
+
+/*
+ * H5_LEAVE macro, used to facilitate control flow between a
+ * BEGIN_FUNC() and an END_FUNC() within a function body. The argument is
+ * the return value.
+ * The return value is assigned to a variable `ret_value' and control branches
+ * to the `catch_except' label, if we're not already past it.
+ */
+#define H5_LEAVE(v) { \
+ ret_value = v; \
+ if(!past_catch) \
+ goto catch_except; \
+}
+
+/*
+ * H5E_THROW macro, used to facilitate error reporting between a
+ * FUNC_ENTER() and a FUNC_LEAVE() within a function body. The arguments are
+ * the minor error number, and an error string.
+ * The return value is assigned to a variable `ret_value' and control branches
+ * to the `catch_except' label, if we're not already past it.
+ */
+#define H5E_THROW(...) { \
+ H5E_PRINTF(__VA_ARGS__); \
+ H5_LEAVE(fail_value) \
+}
+
+/* Macro for "catching" flow of control when an error occurs. Note that the
+ * H5_LEAVE macro won't jump back here once it's past this point.
+ */
+#define CATCH past_catch = TRUE; catch_except:;
+
+
+/**************************/
+/* Package Private Macros */
+/**************************/
+
+/* If this package header is being included in one of the H5EA modules, define
+ * the proper control macros for the generic FUNC_ENTER/LEAVE and error
+ * reporting macros.
+ */
+#ifdef H5EA_MODULE
+#define H5_MY_PKG H5EA
+#define H5_MY_PKG_ERR H5E_EARRAY
+#define H5_MY_PKG_INIT NO
+#endif /* H5EA_MODULE */
+
+/* Fill value for extensible array test class */
+#ifdef H5EA_TESTING
+#define H5EA_TEST_FILL ((uint64_t)ULLONG_MAX)
+#endif /* H5EA_TESTING */
+
+/* Size of checksum information (on disk) */
+#define H5EA_SIZEOF_CHKSUM 4
+
+/* "Standard" size of prefix information for extensible array metadata */
+#define H5EA_METADATA_PREFIX_SIZE(c) ( \
+ H5_SIZEOF_MAGIC /* Signature */ \
+ + 1 /* Version */ \
+ + ((c) ? H5EA_SIZEOF_CHKSUM : 0) /* Metadata checksum */ \
+ )
+
+/* Size of the extensible array header on disk */
+#define H5EA_HEADER_SIZE(h) ( \
+ /* General metadata fields */ \
+ H5EA_METADATA_PREFIX_SIZE(TRUE) \
+ \
+ /* General heap information */ \
+ + 1 /* Array type */ \
+ + 1 /* Element Size */ \
+ + 1 /* Max. # of elements bits */ \
+ + 1 /* # of elements to store in index block */ \
+ + 1 /* Min. # elements per data block */ \
+ + 1 /* Min. # of data block pointers for a super block */ \
+ + 1 /* Log2(Max. # of elements in data block page) - i.e. # of bits needed to store max. # of elements in data block page */ \
+ \
+ /* Extensible Array Header statistics fields */ \
+ + (h)->sizeof_size /* Max. index set */ \
+ + (h)->sizeof_size /* Number of super blocks created */ \
+ + (h)->sizeof_size /* Number of data blocks created */ \
+ + (h)->sizeof_size /* Number of elements 'realized' */ \
+ \
+ /* Extensible Array Header specific fields */ \
+ + (h)->sizeof_addr /* File address of index block */ \
+ )
+
+/* Size of the extensible array index block on disk */
+#define H5EA_IBLOCK_SIZE(i) ( \
+ /* General metadata fields */ \
+ H5EA_METADATA_PREFIX_SIZE(TRUE) \
+ \
+ /* Sanity-checking fields */ \
+ + 1 /* Array type */ \
+ + (i)->hdr->sizeof_addr /* File address of array owning the block */ \
+ \
+ /* Extensible Array Index Block specific fields */ \
+ + ((size_t)(i)->hdr->cparam.idx_blk_elmts * (size_t)(i)->hdr->cparam.raw_elmt_size) /* Elements in index block */ \
+ + ((i)->ndblk_addrs * (i)->hdr->sizeof_addr) /* Data block addresses in index block */ \
+ + ((i)->nsblk_addrs * (i)->hdr->sizeof_addr) /* Super block addresses in index block */ \
+ )
+
+/* Size of the extensible array super block on disk */
+#define H5EA_SBLOCK_SIZE(s) ( \
+ /* General metadata fields */ \
+ H5EA_METADATA_PREFIX_SIZE(TRUE) \
+ \
+ /* Sanity-checking fields */ \
+ + 1 /* Array type */ \
+ + (s)->hdr->sizeof_addr /* File address of array owning the block */ \
+ + (s)->hdr->arr_off_size /* Offset of the block in the array */ \
+ \
+ /* Extensible Array Super Block specific fields */ \
+ + ((s)->ndblks * (s)->dblk_page_init_size) /* Data block 'page init' bitmasks in super block (can be 0 if no pages) */ \
+ + ((s)->ndblks * (s)->hdr->sizeof_addr) /* Data block addresses in super block */ \
+ )
+
+/* Size of the extensible array data block prefix on disk */
+#define H5EA_DBLOCK_PREFIX_SIZE(d) ( \
+ /* General metadata fields */ \
+ H5EA_METADATA_PREFIX_SIZE(TRUE) \
+ \
+ /* Sanity-checking fields */ \
+ + 1 /* Array type */ \
+ + (d)->hdr->sizeof_addr /* File address of array owning the block */ \
+ + (d)->hdr->arr_off_size /* Offset of the block in the array */ \
+ )
+
+/* Size of the extensible array data block on disk */
+#define H5EA_DBLOCK_SIZE(d) ( \
+ /* Data block prefix size */ \
+ H5EA_DBLOCK_PREFIX_SIZE(d) \
+ \
+ /* Extensible Array Data Block specific fields */ \
+ + ((d)->nelmts * (size_t)(d)->hdr->cparam.raw_elmt_size) /* Elements in data block */ \
+ + ((d)->npages * H5EA_SIZEOF_CHKSUM) /* Checksum for each page */ \
+ )
+
+/* Size of the extensible array data block page on disk */
+#define H5EA_DBLK_PAGE_SIZE(p) ( \
+ + ((p)->hdr->dblk_page_nelmts * (size_t)(p)->hdr->cparam.raw_elmt_size) /* Elements in data block page */ \
+ + H5EA_SIZEOF_CHKSUM /* Checksum for each page */ \
+ )
+
+/* Compute the # of bytes required to store an offset into a given buffer size */
+#define H5EA_SIZEOF_OFFSET_BITS(b) (((b) + 7) / 8)
+
+/* Compute the first super block index that will hold a certain # of data block pointers */
+#define H5EA_SBLK_FIRST_IDX(m) (2 * H5V_log2_of2((uint32_t)m))
+
+/****************************/
+/* Package Private Typedefs */
+/****************************/
+
+/* Information for each super block in extensible array */
+typedef struct H5EA_sblk_info_t {
+ size_t ndblks; /* Number of data blocks for a super block */
+ size_t dblk_nelmts; /* Number of elements in each data block for super block */
+ hsize_t start_idx; /* Index of first element in super block */
+ hsize_t start_dblk; /* Index of first data block in super block */
+} H5EA_sblk_info_t;
+
+/* The extensible array header information */
+/* (Each extensible array header has certain information that is shared across
+ * all the blocks in that extensible array)
+ */
+typedef struct H5EA_hdr_t {
+ /* Information for H5AC cache functions, _must_ be first field in structure */
+ H5AC_info_t cache_info;
+
+ /* Extensible array configuration/creation parameters (stored) */
+ H5EA_create_t cparam; /* Creation parameters for extensible array */
+
+ /* Index block information (stored in header) */
+ haddr_t idx_blk_addr; /* Address of index block in header */
+
+ /* Statistics for array (stored in header) */
+ H5EA_stat_t stats; /* Statistics for extensible array */
+
+ /* Data block element buffer factory info (not stored in header) */
+ struct {
+ size_t nalloc; /* Number of factories allocated */
+ H5FL_fac_head_t **fac; /* Array of factories for data block element buffers */
+ } elmt_fac;
+
+ /* Computed/cached values (not stored in header) */
+ size_t rc; /* Reference count of heap's components using heap header */
+ haddr_t addr; /* Address of header in file */
+ size_t size; /* Size of header in file */
+ H5F_t *f; /* Pointer to file for extensible array */
+ size_t file_rc; /* Reference count of files using array header */
+ hbool_t pending_delete; /* Array is pending deletion */
+ size_t sizeof_addr; /* Size of file addresses */
+ size_t sizeof_size; /* Size of file sizes */
+ unsigned char arr_off_size; /* Size of array offsets (in bytes) */
+
+ /* Super block information (not stored) */
+ size_t nsblks; /* Number of superblocks needed for array */
+ H5EA_sblk_info_t *sblk_info; /* Array of information for each super block */
+
+ /* Data block information (not stored) */
+ size_t dblk_page_nelmts; /* # of elements per data block page */
+} H5EA_hdr_t;
+
+/* The extensible array index block information */
+typedef struct H5EA_iblock_t {
+ /* Information for H5AC cache functions, _must_ be first field in structure */
+ H5AC_info_t cache_info;
+
+ /* Extensible array information (stored) */
+ void *elmts; /* Buffer for elements stored in index block */
+ haddr_t *dblk_addrs; /* Buffer for addresses of data blocks in index block */
+ haddr_t *sblk_addrs; /* Buffer for addresses of super blocks in index block */
+
+ /* Internal array information (not stored) */
+ size_t rc; /* Reference count of objects using this block */
+ H5EA_hdr_t *hdr; /* Shared array header info */
+ haddr_t addr; /* Address of this index block on disk */
+ size_t size; /* Size of index block on disk */
+
+ /* Computed/cached values (not stored) */
+ size_t nsblks; /* # of super blocks whose data block addresses are in index block */
+ size_t ndblk_addrs; /* Number of pointers to data blocks in index block */
+ size_t nsblk_addrs; /* Number of pointers to super blocks in index block */
+} H5EA_iblock_t;
+
+/* The extensible array super block information */
+typedef struct H5EA_sblock_t {
+ /* Information for H5AC cache functions, _must_ be first field in structure */
+ H5AC_info_t cache_info;
+
+ /* Extensible array information (stored) */
+ hsize_t block_off; /* Offset of the block within the array's address space */
+ haddr_t *dblk_addrs; /* Addresses of data blocks in super block */
+ uint8_t *page_init; /* Bitmap of whether a data block page is initialized */
+
+ /* Internal array information (not stored) */
+ size_t rc; /* Reference count of objects using this block */
+ H5EA_hdr_t *hdr; /* Shared array header info */
+ haddr_t addr; /* Address of this index block on disk */
+ size_t size; /* Size of index block on disk */
+
+ /* Computed/cached values (not stored) */
+ unsigned idx; /* Super block index within the extensible array */
+ size_t ndblks; /* # of data block addresses that are in super block */
+ size_t dblk_nelmts; /* # of elements for data blocks reachable through this super block */
+ size_t dblk_npages; /* # of pages in each data block */
+ size_t dblk_page_init_size; /* Size of 'page init' bitmask for each data block */
+ size_t dblk_page_size; /* Size of a data block page */
+} H5EA_sblock_t;
+
+/* The extensible array data block information */
+typedef struct H5EA_dblock_t {
+ /* Information for H5AC cache functions, _must_ be first field in structure */
+ H5AC_info_t cache_info;
+
+ /* Extensible array information (stored) */
+ hsize_t block_off; /* Offset of the block within the array's address space */
+ void *elmts; /* Buffer for elements stored in data block */
+
+ /* Internal array information (not stored) */
+ H5EA_hdr_t *hdr; /* Shared array header info */
+ haddr_t addr; /* Address of this data block on disk */
+ size_t size; /* Size of data block on disk */
+
+ /* Computed/cached values (not stored) */
+ size_t nelmts; /* Number of elements in block */
+ size_t npages; /* Nummber of pages in a block (zero if not paged) */
+} H5EA_dblock_t;
+
+/* The extensible array data block page information */
+typedef struct H5EA_dbk_page_t {
+ /* Information for H5AC cache functions, _must_ be first field in structure */
+ H5AC_info_t cache_info;
+
+ /* Extensible array information (stored) */
+ void *elmts; /* Buffer for elements stored in data block page */
+
+ /* Internal array information (not stored) */
+ H5EA_hdr_t *hdr; /* Shared array header info */
+ haddr_t addr; /* Address of this data block page on disk */
+ size_t size; /* Size of data block page on disk */
+
+ /* Computed/cached values (not stored) */
+ /* <none> */
+} H5EA_dblk_page_t;
+
+/* Extensible array */
+struct H5EA_t {
+ H5EA_hdr_t *hdr; /* Pointer to internal extensible array header info */
+ H5F_t *f; /* Pointer to file for extensible array */
+};
+
+
+/*****************************/
+/* Package Private Variables */
+/*****************************/
+
+/* H5EA header inherits cache-like properties from H5AC */
+H5_DLLVAR const H5AC_class_t H5AC_EARRAY_HDR[1];
+
+/* H5EA index block inherits cache-like properties from H5AC */
+H5_DLLVAR const H5AC_class_t H5AC_EARRAY_IBLOCK[1];
+
+/* H5EA index block inherits cache-like properties from H5AC */
+H5_DLLVAR const H5AC_class_t H5AC_EARRAY_SBLOCK[1];
+
+/* H5EA data block inherits cache-like properties from H5AC */
+H5_DLLVAR const H5AC_class_t H5AC_EARRAY_DBLOCK[1];
+
+/* H5EA data block page inherits cache-like properties from H5AC */
+H5_DLLVAR const H5AC_class_t H5AC_EARRAY_DBLK_PAGE[1];
+
+/* Internal extensible array testing class */
+#ifdef H5EA_TESTING
+H5_DLLVAR const H5EA_class_t H5EA_CLS_TEST[1];
+#endif /* H5EA_TESTING */
+
+
+/******************************/
+/* Package Private Prototypes */
+/******************************/
+
+/* Header routines */
+H5_DLL H5EA_hdr_t *H5EA__hdr_alloc(H5F_t *f, const H5EA_class_t *cls);
+H5_DLL herr_t H5EA__hdr_init(H5EA_hdr_t *hdr);
+H5_DLL haddr_t H5EA__hdr_create(H5F_t *f, hid_t dxpl_id, const H5EA_create_t *cparam);
+H5_DLL void *H5EA__hdr_alloc_elmts(H5EA_hdr_t *hdr, size_t nelmts);
+H5_DLL herr_t H5EA__hdr_free_elmts(H5EA_hdr_t *hdr, size_t nelmts, void *elmts);
+H5_DLL herr_t H5EA__hdr_incr(H5EA_hdr_t *hdr);
+H5_DLL herr_t H5EA__hdr_decr(H5EA_hdr_t *hdr);
+H5_DLL herr_t H5EA__hdr_fuse_incr(H5EA_hdr_t *hdr);
+H5_DLL size_t H5EA__hdr_fuse_decr(H5EA_hdr_t *hdr);
+H5_DLL herr_t H5EA__hdr_modified(H5EA_hdr_t *hdr);
+H5_DLL herr_t H5EA__hdr_delete(H5EA_hdr_t *hdr, hid_t dxpl_id);
+H5_DLL herr_t H5EA__hdr_dest(H5EA_hdr_t *hdr);
+
+/* Index block routines */
+H5_DLL H5EA_iblock_t *H5EA__iblock_alloc(H5EA_hdr_t *hdr);
+H5_DLL haddr_t H5EA__iblock_create(H5EA_hdr_t *hdr, hid_t dxpl_id);
+H5_DLL H5EA_iblock_t *H5EA__iblock_protect(H5EA_hdr_t *hdr, hid_t dxpl_id,
+ H5AC_protect_t rw);
+H5_DLL herr_t H5EA__iblock_unprotect(H5EA_iblock_t *iblock, hid_t dxpl_id,
+ unsigned cache_flags);
+H5_DLL herr_t H5EA__iblock_delete(H5EA_hdr_t *hdr, hid_t dxpl_id);
+H5_DLL herr_t H5EA__iblock_dest(H5F_t *f, H5EA_iblock_t *iblock);
+
+/* Super block routines */
+H5_DLL H5EA_sblock_t *H5EA__sblock_alloc(H5EA_hdr_t *hdr, unsigned sblk_idx);
+H5_DLL haddr_t H5EA__sblock_create(H5EA_hdr_t *hdr, hid_t dxpl_id, unsigned sblk_idx);
+H5_DLL H5EA_sblock_t *H5EA__sblock_protect(H5EA_hdr_t *hdr, hid_t dxpl_id,
+ haddr_t sblk_addr, unsigned sblk_idx, H5AC_protect_t rw);
+H5_DLL herr_t H5EA__sblock_unprotect(H5EA_sblock_t *sblock, hid_t dxpl_id,
+ unsigned cache_flags);
+H5_DLL herr_t H5EA__sblock_delete(H5EA_hdr_t *hdr, hid_t dxpl_id,
+ haddr_t sblk_addr, unsigned sblk_idx);
+H5_DLL herr_t H5EA__sblock_dest(H5F_t *f, H5EA_sblock_t *sblock);
+
+/* Data block routines */
+H5_DLL H5EA_dblock_t *H5EA__dblock_alloc(H5EA_hdr_t *hdr, size_t nelmts);
+H5_DLL haddr_t H5EA__dblock_create(H5EA_hdr_t *hdr, hid_t dxpl_id,
+ hsize_t dblk_off, size_t nelmts);
+H5_DLL unsigned H5EA__dblock_sblk_idx(const H5EA_hdr_t *hdr, hsize_t idx);
+H5_DLL H5EA_dblock_t *H5EA__dblock_protect(H5EA_hdr_t *hdr, hid_t dxpl_id,
+ haddr_t dblk_addr, size_t dblk_nelmts, H5AC_protect_t rw);
+H5_DLL herr_t H5EA__dblock_unprotect(H5EA_dblock_t *dblock, hid_t dxpl_id,
+ unsigned cache_flags);
+H5_DLL herr_t H5EA__dblock_delete(H5EA_hdr_t *hdr, hid_t dxpl_id,
+ haddr_t dblk_addr, size_t dblk_nelmts);
+H5_DLL herr_t H5EA__dblock_dest(H5F_t *f, H5EA_dblock_t *dblock);
+
+/* Data block page routines */
+H5_DLL H5EA_dblk_page_t *H5EA__dblk_page_alloc(H5EA_hdr_t *hdr);
+H5_DLL herr_t H5EA__dblk_page_create(H5EA_hdr_t *hdr, hid_t dxpl_id,
+ haddr_t addr);
+H5_DLL H5EA_dblk_page_t *H5EA__dblk_page_protect(H5EA_hdr_t *hdr, hid_t dxpl_id,
+ haddr_t dblk_page_addr, H5AC_protect_t rw);
+H5_DLL herr_t H5EA__dblk_page_unprotect(H5EA_dblk_page_t *dblk_page,
+ hid_t dxpl_id, unsigned cache_flags);
+H5_DLL herr_t H5EA__dblk_page_dest(H5EA_dblk_page_t *dblk_page);
+
+/* Debugging routines for dumping file structures */
+H5_DLL herr_t H5EA__hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr,
+ FILE *stream, int indent, int fwidth, const H5EA_class_t *cls);
+H5_DLL herr_t H5EA__iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr,
+ FILE *stream, int indent, int fwidth, const H5EA_class_t *cls,
+ haddr_t hdr_addr);
+H5_DLL herr_t H5EA__sblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr,
+ FILE *stream, int indent, int fwidth, const H5EA_class_t *cls,
+ haddr_t hdr_addr, unsigned sblk_idx);
+H5_DLL herr_t H5EA__dblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr,
+ FILE *stream, int indent, int fwidth, const H5EA_class_t *cls,
+ haddr_t hdr_addr, size_t dblk_nelmts);
+
+/* Testing routines */
+#ifdef H5EA_TESTING
+H5_DLL herr_t H5EA_get_cparam_test(const H5EA_t *ea, H5EA_create_t *cparam);
+H5_DLL int H5EA_cmp_cparam_test(const H5EA_create_t *cparam1, const H5EA_create_t *cparam2);
+#endif /* H5EA_TESTING */
+
+#endif /* _H5EApkg_H */
+
diff --git a/src/H5EAprivate.h b/src/H5EAprivate.h
new file mode 100644
index 0000000..a1f3221
--- /dev/null
+++ b/src/H5EAprivate.h
@@ -0,0 +1,122 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5EAprivate.h
+ * Jun 17 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: Private header for library accessible extensible
+ * array routines.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef _H5EAprivate_H
+#define _H5EAprivate_H
+
+/* Include package's public header */
+#ifdef NOT_YET
+#include "H5EApublic.h"
+#endif /* NOT_YET */
+
+/* Private headers needed by this file */
+#include "H5Fprivate.h" /* File access */
+
+
+/**************************/
+/* Library Private Macros */
+/**************************/
+
+
+/****************************/
+/* Library Private Typedefs */
+/****************************/
+
+/* Extensible array class IDs */
+typedef enum H5EA_cls_id_t {
+ /* Start real class IDs at 0 -QAK */
+ H5EA_CLS_TEST_ID, /* Extensible array is for testing (do not use for actual data) */
+ H5EA_NUM_CLS_ID /* Number of Extensible Array class IDs (must be last) */
+} H5EA_cls_id_t;
+
+/*
+ * Each type of element that can be stored in an extesible array has a
+ * variable of this type that contains class variables and methods.
+ */
+typedef struct H5EA_class_t {
+ H5EA_cls_id_t id; /* ID of Extensible Array class, as found in file */
+ size_t nat_elmt_size; /* Size of native (memory) element */
+
+ /* Extensible array client callback methods */
+ herr_t (*fill)(void *nat_blk, size_t nelmts); /* Fill array of elements with encoded form of "missing element" value */
+ herr_t (*encode)(void *raw, const void *elmt, size_t nelmts); /* Encode elements from native form to disk storage form */
+ herr_t (*decode)(const void *raw, void *elmt, size_t nelmts); /* Decode elements from disk storage form to native form */
+ herr_t (*debug)(FILE *stream, int indent, int fwidth, hsize_t idx, const void *elmt); /* Print an element for debugging */
+} H5EA_class_t;
+
+/* Extensible array creation parameters */
+typedef struct H5EA_create_t {
+ const H5EA_class_t *cls; /* Class of extensible array to create */
+ uint8_t raw_elmt_size; /* Element size in file (in bytes) */
+ uint8_t max_nelmts_bits; /* Log2(Max. # of elements in array) - i.e. # of bits needed to store max. # of elements */
+ uint8_t idx_blk_elmts; /* # of elements to store in index block */
+ uint8_t data_blk_min_elmts; /* Min. # of elements per data block */
+ uint8_t sup_blk_min_data_ptrs; /* Min. # of data block pointers for a super block */
+ uint8_t max_dblk_page_nelmts_bits; /* Log2(Max. # of elements in data block page) - i.e. # of bits needed to store max. # of elements in data block page */
+} H5EA_create_t;
+
+/* Extensible array metadata statistics info */
+typedef struct H5EA_stat_t {
+ hsize_t max_idx_set; /* Highest element index stored (+1 - i.e. if element 0 has been set, this value with be '1', if no elements have been stored, this value will be '0') */
+ hsize_t nsuper_blks; /* # of super blocks */
+ hsize_t ndata_blks; /* # of data blocks */
+ hsize_t nelmts; /* # of elements "realized" */
+} H5EA_stat_t;
+
+/* Extensible array info (forward decl - defined in H5EApkg.h) */
+typedef struct H5EA_t H5EA_t;
+
+
+/*****************************/
+/* Library-private Variables */
+/*****************************/
+
+
+/***************************************/
+/* Library-private Function Prototypes */
+/***************************************/
+
+/* General routines */
+H5_DLL H5EA_t *H5EA_create(H5F_t *f, hid_t dxpl_id, const H5EA_create_t *cparam);
+H5_DLL H5EA_t *H5EA_open(H5F_t *f, hid_t dxpl_id, haddr_t ea_addr,
+ const H5EA_class_t *cls);
+H5_DLL herr_t H5EA_get_nelmts(const H5EA_t *ea, hsize_t *nelmts);
+H5_DLL herr_t H5EA_get_addr(const H5EA_t *ea, haddr_t *addr);
+H5_DLL herr_t H5EA_set(const H5EA_t *ea, hid_t dxpl_id, hsize_t idx, const void *elmt);
+H5_DLL herr_t H5EA_get(const H5EA_t *ea, hid_t dxpl_id, hsize_t idx, void *elmt);
+H5_DLL herr_t H5EA_close(H5EA_t *ea, hid_t dxpl_id);
+H5_DLL herr_t H5EA_delete(H5F_t *f, hid_t dxpl_id, haddr_t ea_addr);
+
+/* Statistics routines */
+H5_DLL herr_t H5EA_get_stats(const H5EA_t *ea, H5EA_stat_t *stats);
+
+/* Debugging routines */
+#ifdef H5EA_DEBUGGING
+#endif /* H5EA_DEBUGGING */
+
+#endif /* _H5EAprivate_H */
+
diff --git a/src/H5EAsblock.c b/src/H5EAsblock.c
new file mode 100644
index 0000000..3d3d4e3
--- /dev/null
+++ b/src/H5EAsblock.c
@@ -0,0 +1,428 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5EAsblock.c
+ * Sep 30 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: Super block routines for extensible arrays.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/**********************/
+/* Module Declaration */
+/**********************/
+
+#define H5EA_MODULE
+
+
+/***********************/
+/* Other Packages Used */
+/***********************/
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5EApkg.h" /* Extensible Arrays */
+#include "H5FLprivate.h" /* Free Lists */
+#include "H5MFprivate.h" /* File memory management */
+#include "H5Vprivate.h" /* Vectors and arrays */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* Declare a free list to manage the H5EA_iblock_t struct */
+H5FL_DEFINE_STATIC(H5EA_sblock_t);
+
+/* Declare a free list to manage the haddr_t sequence information */
+H5FL_SEQ_DEFINE_STATIC(haddr_t);
+
+/* Declare a free list to manage blocks of 'page init' bitmasks */
+H5FL_BLK_DEFINE(page_init);
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__sblock_alloc
+ *
+ * Purpose: Allocate extensible array super block
+ *
+ * Return: Non-NULL pointer to super block on success/NULL on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 30 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+H5EA_sblock_t *, NULL, NULL,
+H5EA__sblock_alloc(H5EA_hdr_t *hdr, unsigned sblk_idx))
+
+ /* Local variables */
+ H5EA_sblock_t *sblock = NULL; /* Extensible array super block */
+
+ /* Check arguments */
+ HDassert(hdr);
+
+ /* Allocate memory for the index block */
+ if(NULL == (sblock = H5FL_CALLOC(H5EA_sblock_t)))
+ H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array super block")
+
+ /* Share common array information */
+ if(H5EA__hdr_incr(hdr) < 0)
+ H5E_THROW(H5E_CANTINC, "can't increment reference count on shared array header")
+ sblock->hdr = hdr;
+
+ /* Set non-zero internal fields */
+ sblock->addr = HADDR_UNDEF;
+
+ /* Compute/cache information */
+ sblock->idx = sblk_idx;
+ sblock->ndblks = hdr->sblk_info[sblk_idx].ndblks;
+ HDassert(sblock->ndblks);
+ sblock->dblk_nelmts = hdr->sblk_info[sblk_idx].dblk_nelmts;
+#ifdef QAK
+HDfprintf(stderr, "%s: hdr->dblk_page_nelmts = %Zu, sblock->ndblks = %Zu, sblock->dblk_nelmts = %Zu\n", FUNC, hdr->dblk_page_nelmts, sblock->ndblks, sblock->dblk_nelmts);
+#endif /* QAK */
+
+ /* Allocate buffer for data block addresses in super block */
+ if(NULL == (sblock->dblk_addrs = H5FL_SEQ_MALLOC(haddr_t, sblock->ndblks)))
+ H5E_THROW(H5E_CANTALLOC, "memory allocation failed for super block data block addresses")
+
+ /* Check if # of elements in data blocks requires paging */
+ if(sblock->dblk_nelmts > hdr->dblk_page_nelmts) {
+ /* Compute # of pages in each data block from this super block */
+ sblock->dblk_npages = sblock->dblk_nelmts / hdr->dblk_page_nelmts;
+
+ /* Sanity check that we have at least 2 pages in data block */
+ HDassert(sblock->dblk_npages > 1);
+
+ /* Sanity check for integer truncation */
+ HDassert((sblock->dblk_npages * hdr->dblk_page_nelmts) == sblock->dblk_nelmts);
+
+ /* Compute size of buffer for each data block's 'page init' bitmask */
+ sblock->dblk_page_init_size = ((sblock->dblk_npages) + 7) / 8;
+ HDassert(sblock->dblk_page_init_size > 0);
+
+ /* Allocate buffer for all 'page init' bitmasks in super block */
+ if(NULL == (sblock->page_init = H5FL_BLK_CALLOC(page_init, sblock->ndblks * sblock->dblk_page_init_size)))
+ H5E_THROW(H5E_CANTALLOC, "memory allocation failed for super block page init bitmask")
+
+ /* Compute data block page size */
+ sblock->dblk_page_size = (hdr->dblk_page_nelmts * hdr->cparam.raw_elmt_size)
+ + H5EA_SIZEOF_CHKSUM;
+ } /* end if */
+
+ /* Set the return value */
+ ret_value = sblock;
+
+CATCH
+ if(!ret_value)
+ if(sblock && H5EA__sblock_dest(hdr->f, sblock) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array super block")
+
+END_FUNC(PKG) /* end H5EA__sblock_alloc() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__sblock_create
+ *
+ * Purpose: Creates a new extensible array super block in the file
+ *
+ * Return: Valid file address on success/HADDR_UNDEF on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 30 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+haddr_t, HADDR_UNDEF, HADDR_UNDEF,
+H5EA__sblock_create(H5EA_hdr_t *hdr, hid_t dxpl_id, unsigned sblk_idx))
+
+ /* Local variables */
+ H5EA_sblock_t *sblock = NULL; /* Extensible array super block */
+ haddr_t tmp_addr = HADDR_UNDEF; /* Address value to fill data block addresses with */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Called\n", FUNC);
+#endif /* QAK */
+
+ /* Sanity check */
+ HDassert(hdr);
+
+ /* Allocate the super block */
+ if(NULL == (sblock = H5EA__sblock_alloc(hdr, sblk_idx)))
+ H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array super block")
+
+ /* Set size of super block on disk */
+ sblock->size = H5EA_SBLOCK_SIZE(sblock);
+#ifdef QAK
+HDfprintf(stderr, "%s: sblock->size = %Zu\n", FUNC, sblock->size);
+#endif /* QAK */
+
+ /* Set offset of block in array's address space */
+ sblock->block_off = hdr->sblk_info[sblk_idx].start_idx;
+#ifdef QAK
+HDfprintf(stderr, "%s: sblock->block_off = %Hu\n", FUNC, sblock->block_off);
+#endif /* QAK */
+
+ /* Allocate space for the super block on disk */
+ if(HADDR_UNDEF == (sblock->addr = H5MF_alloc(hdr->f, H5FD_MEM_EARRAY_SBLOCK, dxpl_id, (hsize_t)sblock->size)))
+ H5E_THROW(H5E_CANTALLOC, "file allocation failed for extensible array super block")
+
+ /* Reset data block addresses to "undefined" address value */
+ H5V_array_fill(sblock->dblk_addrs, &tmp_addr, sizeof(haddr_t), sblock->ndblks);
+
+ /* Cache the new extensible array super block */
+ if(H5AC_set(hdr->f, dxpl_id, H5AC_EARRAY_SBLOCK, sblock->addr, sblock, H5AC__NO_FLAGS_SET) < 0)
+ H5E_THROW(H5E_CANTINSERT, "can't add extensible array super block to cache")
+
+ /* Set address of super block to return */
+ ret_value = sblock->addr;
+
+CATCH
+ if(!H5F_addr_defined(ret_value))
+ if(sblock) {
+ /* Release super block's disk space */
+ if(H5F_addr_defined(sblock->addr) && H5MF_xfree(hdr->f, H5FD_MEM_EARRAY_SBLOCK, dxpl_id, sblock->addr, (hsize_t)sblock->size) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to release extensible array super block")
+
+ /* Destroy super block */
+ if(H5EA__sblock_dest(hdr->f, sblock) < 0)
+ H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array super block")
+ } /* end if */
+
+END_FUNC(PKG) /* end H5EA__sblock_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__sblock_protect
+ *
+ * Purpose: Convenience wrapper around protecting extensible array super block
+ *
+ * Return: Non-NULL pointer to data block on success/NULL on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 30 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+H5EA_sblock_t *, NULL, NULL,
+H5EA__sblock_protect(H5EA_hdr_t *hdr, hid_t dxpl_id, haddr_t sblk_addr,
+ unsigned sblk_idx, H5AC_protect_t rw))
+
+ /* Local variables */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Called\n", FUNC);
+#endif /* QAK */
+
+ /* Sanity check */
+ HDassert(hdr);
+ HDassert(H5F_addr_defined(sblk_addr));
+
+ /* Protect the super block */
+ if(NULL == (ret_value = (H5EA_sblock_t *)H5AC_protect(hdr->f, dxpl_id, H5AC_EARRAY_SBLOCK, sblk_addr, &sblk_idx, hdr, rw)))
+ H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array super block, address = %llu", (unsigned long_long)sblk_addr)
+
+CATCH
+
+END_FUNC(PKG) /* end H5EA__sblock_protect() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__sblock_unprotect
+ *
+ * Purpose: Convenience wrapper around unprotecting extensible array super block
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 30 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__sblock_unprotect(H5EA_sblock_t *sblock, hid_t dxpl_id, unsigned cache_flags))
+
+ /* Local variables */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Called\n", FUNC);
+#endif /* QAK */
+
+ /* Sanity check */
+ HDassert(sblock);
+
+ /* Unprotect the super block */
+ if(H5AC_unprotect(sblock->hdr->f, dxpl_id, H5AC_EARRAY_SBLOCK, sblock->addr, sblock, cache_flags) < 0)
+ H5E_THROW(H5E_CANTUNPROTECT, "unable to unprotect extensible array super block, address = %llu", (unsigned long_long)sblock->addr)
+
+CATCH
+
+END_FUNC(PKG) /* end H5EA__sblock_unprotect() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__sblock_delete
+ *
+ * Purpose: Delete a super block
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 30 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PKG, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__sblock_delete(H5EA_hdr_t *hdr, hid_t dxpl_id, haddr_t sblk_addr,
+ unsigned sblk_idx))
+
+ /* Local variables */
+ H5EA_sblock_t *sblock = NULL; /* Pointer to super block */
+ size_t u; /* Local index variable */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Called\n", FUNC);
+#endif /* QAK */
+
+ /* Sanity check */
+ HDassert(hdr);
+ HDassert(H5F_addr_defined(sblk_addr));
+
+ /* Protect super block */
+ if(NULL == (sblock = H5EA__sblock_protect(hdr, dxpl_id, sblk_addr, sblk_idx, H5AC_WRITE)))
+ H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array super block, address = %llu", (unsigned long_long)sblk_addr)
+
+ /* Iterate over data blocks */
+ for(u = 0; u < sblock->ndblks; u++) {
+ /* Check for data block existing */
+ if(H5F_addr_defined(sblock->dblk_addrs[u])) {
+ /* Delete data block */
+ if(H5EA__dblock_delete(hdr, dxpl_id, sblock->dblk_addrs[u], sblock->dblk_nelmts) < 0)
+ H5E_THROW(H5E_CANTDELETE, "unable to delete extensible array data block")
+ sblock->dblk_addrs[u] = HADDR_UNDEF;
+ } /* end if */
+ } /* end for */
+
+CATCH
+ /* Finished deleting super block in metadata cache */
+ if(sblock && H5EA__sblock_unprotect(sblock, dxpl_id, H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0)
+ H5E_THROW(H5E_CANTUNPROTECT, "unable to release extensible array super block")
+
+END_FUNC(PKG) /* end H5EA__sblock_delete() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__sblock_dest
+ *
+ * Purpose: Destroys an extensible array super block in memory.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Sep 30 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+BEGIN_FUNC(PKG, ERR,
+herr_t, SUCCEED, FAIL,
+H5EA__sblock_dest(H5F_t *f, H5EA_sblock_t *sblock))
+
+ /* Sanity check */
+ HDassert(sblock);
+ HDassert(sblock->rc == 0);
+#ifdef QAK
+HDfprintf(stderr, "%s: sblock->hdr->dblk_page_nelmts = %Zu, sblock->ndblks = %Zu, sblock->dblk_nelmts = %Zu\n", FUNC, sblock->hdr->dblk_page_nelmts, sblock->ndblks, sblock->dblk_nelmts);
+#endif /* QAK */
+
+ /* Check if shared header field has been initialized */
+ if(sblock->hdr) {
+ /* Set the shared array header's file context for this operation */
+ sblock->hdr->f = f;
+
+ /* Free buffer for super block data block addresses, if there are any */
+ if(sblock->dblk_addrs)
+ sblock->dblk_addrs = H5FL_SEQ_FREE(haddr_t, sblock->dblk_addrs);
+
+ /* Free buffer for super block 'page init' bitmask, if there is one */
+ if(sblock->page_init) {
+ HDassert(sblock->dblk_npages > 0);
+ sblock->page_init = H5FL_BLK_FREE(page_init, sblock->page_init);
+ } /* end if */
+
+ /* Decrement reference count on shared info */
+ if(H5EA__hdr_decr(sblock->hdr) < 0)
+ H5E_THROW(H5E_CANTDEC, "can't decrement reference count on shared array header")
+ sblock->hdr = NULL;
+ } /* end if */
+
+ /* Free the super block itself */
+ (void)H5FL_FREE(H5EA_sblock_t, sblock);
+
+CATCH
+
+END_FUNC(PKG) /* end H5EA__sblock_dest() */
+
diff --git a/src/H5EAstat.c b/src/H5EAstat.c
new file mode 100644
index 0000000..8a26e34
--- /dev/null
+++ b/src/H5EAstat.c
@@ -0,0 +1,116 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5EAstat.c
+ * Sep 11 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: Extensible array metadata statistics functions.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/**********************/
+/* Module Declaration */
+/**********************/
+
+#define H5EA_MODULE
+
+
+/***********************/
+/* Other Packages Used */
+/***********************/
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5EApkg.h" /* Extensible Arrays */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA_get_stats
+ *
+ * Purpose: Query the metadata stats of an array
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Aug 21 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PRIV, NOERR,
+herr_t, SUCCEED, -,
+H5EA_get_stats(const H5EA_t *ea, H5EA_stat_t *stats))
+
+ /* Local variables */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Called\n", FUNC);
+#endif /* QAK */
+
+ /*
+ * Check arguments.
+ */
+ HDassert(ea);
+ HDassert(stats);
+
+ /* Copy extensible array statistics */
+ HDmemcpy(stats, &ea->hdr->stats, sizeof(ea->hdr->stats));
+
+END_FUNC(PRIV) /* end H5EA_get_stats() */
+
diff --git a/src/H5EAtest.c b/src/H5EAtest.c
new file mode 100644
index 0000000..eea69ea
--- /dev/null
+++ b/src/H5EAtest.c
@@ -0,0 +1,325 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/* Programmer: Quincey Koziol <koziol@hdfgroup.org>
+ * Thursday, August 28, 2008
+ *
+ * Purpose: Extensible array testing functions.
+ *
+ */
+
+/**********************/
+/* Module Declaration */
+/**********************/
+
+#define H5EA_MODULE
+#define H5EA_TESTING
+
+
+/***********************/
+/* Other Packages Used */
+/***********************/
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5EApkg.h" /* Extensible Arrays */
+#include "H5Vprivate.h" /* Vector functions */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+/* Extensible array class callbacks */
+static herr_t H5EA__test_fill(void *nat_blk, size_t nelmts);
+static herr_t H5EA__test_encode(void *raw, const void *elmt, size_t nelmts);
+static herr_t H5EA__test_decode(const void *raw, void *elmt, size_t nelmts);
+static herr_t H5EA__test_debug(FILE *stream, int indent, int fwidth,
+ hsize_t idx, const void *elmt);
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+/* Extensible array testing class information */
+const H5EA_class_t H5EA_CLS_TEST[1]={{
+ H5EA_CLS_TEST_ID, /* Type of Extensible array */
+ sizeof(uint64_t), /* Size of native element */
+ H5EA__test_fill, /* Fill block of missing elements callback */
+ H5EA__test_encode, /* Element encoding callback */
+ H5EA__test_decode, /* Element decoding callback */
+ H5EA__test_debug /* Element debugging callback */
+}};
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__test_fill
+ *
+ * Purpose: Fill "missing elements" in block of elements
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, August 28, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, NOERR,
+herr_t, SUCCEED, -,
+H5EA__test_fill(void *nat_blk, size_t nelmts))
+
+ /* Local variables */
+ uint64_t fill_val = H5EA_TEST_FILL; /* Value to fill elements with */
+
+ /* Sanity checks */
+ HDassert(nat_blk);
+ HDassert(nelmts);
+
+ H5V_array_fill(nat_blk, &fill_val, sizeof(uint64_t), nelmts);
+
+END_FUNC(STATIC) /* end H5EA__test_fill() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__test_encode
+ *
+ * Purpose: Encode an element from "native" to "raw" form
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, August 28, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, NOERR,
+herr_t, SUCCEED, -,
+H5EA__test_encode(void *raw, const void *_elmt, size_t nelmts))
+
+ /* Local variables */
+ const uint64_t *elmt = (const uint64_t *)_elmt; /* Convenience pointer to native elements */
+
+ /* Sanity checks */
+ HDassert(raw);
+ HDassert(elmt);
+ HDassert(nelmts);
+
+ /* Encode native elements into raw elements */
+ while(nelmts) {
+ /* Encode element */
+ /* (advances 'raw' pointer */
+ UINT64ENCODE(raw, *elmt);
+
+ /* Advance native element pointer */
+ elmt++;
+
+ /* Decrement # of elements to encode */
+ nelmts--;
+ } /* end while */
+
+END_FUNC(STATIC) /* end H5EA__test_encode() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__test_decode
+ *
+ * Purpose: Decode an element from "raw" to "native" form
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, August 28, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, NOERR,
+herr_t, SUCCEED, -,
+H5EA__test_decode(const void *_raw, void *_elmt, size_t nelmts))
+
+ /* Local variables */
+ uint64_t *elmt = (uint64_t *)_elmt; /* Convenience pointer to native elements */
+ const uint8_t *raw = (const uint8_t *)_raw; /* Convenience pointer to raw elements */
+
+ /* Sanity checks */
+ HDassert(raw);
+ HDassert(elmt);
+ HDassert(nelmts);
+
+ /* Decode raw elements into native elements */
+ while(nelmts) {
+ /* Decode element */
+ /* (advances 'raw' pointer */
+ UINT64DECODE(raw, *elmt);
+
+ /* Advance native element pointer */
+ elmt++;
+
+ /* Decrement # of elements to decode */
+ nelmts--;
+ } /* end while */
+
+END_FUNC(STATIC) /* end H5EA__test_decode() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA__test_debug
+ *
+ * Purpose: Display an element for debugging
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, August 28, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(STATIC, NOERR,
+herr_t, SUCCEED, -,
+H5EA__test_debug(FILE *stream, int indent, int fwidth, hsize_t idx,
+ const void *elmt))
+
+ /* Local variables */
+ char temp_str[128]; /* Temporary string, for formatting */
+
+ /* Sanity checks */
+ HDassert(stream);
+ HDassert(elmt);
+
+ /* Print element */
+ sprintf(temp_str, "Element #%llu:", (unsigned long_long)idx);
+ HDfprintf(stream, "%*s%-*s %llu\n", indent, "", fwidth, temp_str,
+ (unsigned long_long)*(const uint64_t *)elmt);
+
+END_FUNC(STATIC) /* end H5EA__test_debug() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA_get_cparam_test
+ *
+ * Purpose: Retrieve the parameters used to create the extensible array
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, August 28, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PRIV, NOERR,
+herr_t, SUCCEED, -,
+H5EA_get_cparam_test(const H5EA_t *ea, H5EA_create_t *cparam))
+
+ /* Check arguments. */
+ HDassert(ea);
+ HDassert(cparam);
+
+ /* Get extensible array creation parameters */
+ cparam->raw_elmt_size = ea->hdr->cparam.raw_elmt_size;
+ cparam->max_nelmts_bits = ea->hdr->cparam.max_nelmts_bits;
+ cparam->idx_blk_elmts = ea->hdr->cparam.idx_blk_elmts;
+ cparam->sup_blk_min_data_ptrs = ea->hdr->cparam.sup_blk_min_data_ptrs;
+ cparam->data_blk_min_elmts = ea->hdr->cparam.data_blk_min_elmts;
+ cparam->max_dblk_page_nelmts_bits = ea->hdr->cparam.max_dblk_page_nelmts_bits;
+
+END_FUNC(PRIV) /* end H5EA_get_cparam_test() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5EA_cmp_cparam_test
+ *
+ * Purpose: Compare the parameters used to create the extensible array
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, August 28, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+BEGIN_FUNC(PRIV, ERRCATCH,
+int, 0, -,
+H5EA_cmp_cparam_test(const H5EA_create_t *cparam1, const H5EA_create_t *cparam2))
+
+ /* Check arguments. */
+ HDassert(cparam1);
+ HDassert(cparam2);
+
+ /* Compare creation parameters for array */
+ if(cparam1->raw_elmt_size < cparam2->raw_elmt_size)
+ H5_LEAVE(-1)
+ else if(cparam1->raw_elmt_size > cparam2->raw_elmt_size)
+ H5_LEAVE(1)
+ if(cparam1->max_nelmts_bits < cparam2->max_nelmts_bits)
+ H5_LEAVE(-1)
+ else if(cparam1->max_nelmts_bits > cparam2->max_nelmts_bits)
+ H5_LEAVE(1)
+ if(cparam1->idx_blk_elmts < cparam2->idx_blk_elmts)
+ H5_LEAVE(-1)
+ else if(cparam1->idx_blk_elmts > cparam2->idx_blk_elmts)
+ H5_LEAVE(1)
+ if(cparam1->sup_blk_min_data_ptrs < cparam2->sup_blk_min_data_ptrs)
+ H5_LEAVE(-1)
+ else if(cparam1->sup_blk_min_data_ptrs > cparam2->sup_blk_min_data_ptrs)
+ H5_LEAVE(1)
+ if(cparam1->data_blk_min_elmts < cparam2->data_blk_min_elmts)
+ H5_LEAVE(-1)
+ else if(cparam1->data_blk_min_elmts > cparam2->data_blk_min_elmts)
+ H5_LEAVE(1)
+ if(cparam1->max_dblk_page_nelmts_bits < cparam2->max_dblk_page_nelmts_bits)
+ H5_LEAVE(-1)
+ else if(cparam1->max_dblk_page_nelmts_bits > cparam2->max_dblk_page_nelmts_bits)
+ H5_LEAVE(1)
+
+CATCH
+
+END_FUNC(PRIV) /* end H5EA_cmp_cparam_test() */
+
diff --git a/src/H5Edefin.h b/src/H5Edefin.h
index 5638305..612fcb1 100644
--- a/src/H5Edefin.h
+++ b/src/H5Edefin.h
@@ -47,6 +47,7 @@ hid_t H5E_SLIST_g = FAIL; /* Skip Lists */
hid_t H5E_EFL_g = FAIL; /* External file list */
hid_t H5E_TST_g = FAIL; /* Ternary Search Trees */
hid_t H5E_ARGS_g = FAIL; /* Invalid arguments to routine */
+hid_t H5E_EARRAY_g = FAIL; /* Extensible Array */
hid_t H5E_ERROR_g = FAIL; /* Error API */
hid_t H5E_PLINE_g = FAIL; /* Data filters */
hid_t H5E_FSPACE_g = FAIL; /* Free Space Manager */
diff --git a/src/H5Edeprec.c b/src/H5Edeprec.c
index c1a5a21..0997f3c 100644
--- a/src/H5Edeprec.c
+++ b/src/H5Edeprec.c
@@ -130,7 +130,7 @@ H5Eget_major(H5E_major_t maj)
FUNC_ENTER_API_NOCLEAR(H5Eget_major, NULL)
/* Get the message object */
- if(NULL == (msg = H5I_object_verify(maj, H5I_ERROR_MSG)))
+ if(NULL == (msg = (H5E_msg_t *)H5I_object_verify(maj, H5I_ERROR_MSG)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a error message ID")
/* Get the message's text */
@@ -178,7 +178,7 @@ H5Eget_minor(H5E_minor_t min)
FUNC_ENTER_API_NOCLEAR(H5Eget_minor, NULL)
/* Get the message object */
- if(NULL == (msg = H5I_object_verify(min, H5I_ERROR_MSG)))
+ if(NULL == (msg = (H5E_msg_t *)H5I_object_verify(min, H5I_ERROR_MSG)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a error message ID")
/* Get the message's text */
diff --git a/src/H5Einit.h b/src/H5Einit.h
index ac02d48..20e156c 100644
--- a/src/H5Einit.h
+++ b/src/H5Einit.h
@@ -27,152 +27,157 @@
assert(H5E_DATASET_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MAJOR, "Dataset"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_DATASET_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_DATASET_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_FUNC_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MAJOR, "Function entry/exit"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_FUNC_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_FUNC_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_STORAGE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MAJOR, "Data storage"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_STORAGE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_STORAGE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_FILE_g==(-1));
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)
+if((H5E_FILE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<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)
+if((H5E_SOHM_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<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")
-if((H5E_SYM_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_SYM_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_VFL_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MAJOR, "Virtual File Layer"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_VFL_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_VFL_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_INTERNAL_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MAJOR, "Internal error (too specific to document in detail)"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_INTERNAL_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_INTERNAL_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_BTREE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MAJOR, "B-Tree node"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_BTREE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_BTREE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_REFERENCE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MAJOR, "References"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_REFERENCE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_REFERENCE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_DATASPACE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MAJOR, "Dataspace"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_DATASPACE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_DATASPACE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_RESOURCE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MAJOR, "Resource unavailable"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_RESOURCE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_RESOURCE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_PLIST_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MAJOR, "Property lists"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_PLIST_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_PLIST_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_LINK_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MAJOR, "Links"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_LINK_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_LINK_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_DATATYPE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MAJOR, "Datatype"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_DATATYPE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_DATATYPE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_RS_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MAJOR, "Reference Counted Strings"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_RS_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_RS_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_HEAP_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MAJOR, "Heap"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_HEAP_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_HEAP_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_OHDR_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MAJOR, "Object header"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_OHDR_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_OHDR_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_ATOM_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MAJOR, "Object atom"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_ATOM_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_ATOM_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_ATTR_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MAJOR, "Attribute"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_ATTR_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_ATTR_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_NONE_MAJOR_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MAJOR, "No error"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_NONE_MAJOR_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_NONE_MAJOR_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_IO_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MAJOR, "Low-level I/O"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_IO_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_IO_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_SLIST_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MAJOR, "Skip Lists"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_SLIST_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_SLIST_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_EFL_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MAJOR, "External file list"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_EFL_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_EFL_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_TST_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MAJOR, "Ternary Search Trees"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_TST_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_TST_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_ARGS_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MAJOR, "Invalid arguments to routine"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_ARGS_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_ARGS_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
+ HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
+assert(H5E_EARRAY_g==(-1));
+if((msg = H5E_create_msg(cls, H5E_MAJOR, "Extensible Array"))==NULL)
+ HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
+if((H5E_EARRAY_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_ERROR_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MAJOR, "Error API"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_ERROR_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_ERROR_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_PLINE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MAJOR, "Data filters"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_PLINE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_PLINE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_FSPACE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MAJOR, "Free Space Manager"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_FSPACE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_FSPACE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CACHE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MAJOR, "Object cache"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CACHE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CACHE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
/*********************/
@@ -184,610 +189,610 @@ if((H5E_CACHE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
assert(H5E_SEEKERROR_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Seek failed"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_SEEKERROR_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_SEEKERROR_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_READERROR_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Read failed"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_READERROR_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_READERROR_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_WRITEERROR_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Write failed"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_WRITEERROR_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_WRITEERROR_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CLOSEERROR_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Close failed"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CLOSEERROR_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CLOSEERROR_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_OVERFLOW_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Address overflowed"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_OVERFLOW_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_OVERFLOW_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_FCNTL_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "File control (fcntl) failed"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_FCNTL_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_FCNTL_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
/* Resource errors */
assert(H5E_NOSPACE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "No space available for allocation"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_NOSPACE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_NOSPACE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTALLOC_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't allocate space"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTALLOC_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTALLOC_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTCOPY_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to copy object"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTCOPY_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTCOPY_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTFREE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to free object"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTFREE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTFREE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_ALREADYEXISTS_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Object already exists"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_ALREADYEXISTS_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_ALREADYEXISTS_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTLOCK_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to lock object"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTLOCK_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTLOCK_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTUNLOCK_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to unlock object"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTUNLOCK_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTUNLOCK_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTGC_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to garbage collect"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTGC_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTGC_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTGETSIZE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to compute size"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTGETSIZE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTGETSIZE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_OBJOPEN_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Object is already open"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_OBJOPEN_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_OBJOPEN_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
/* Heap errors */
assert(H5E_CANTRESTORE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't restore condition"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTRESTORE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTRESTORE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTCOMPUTE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't compute value"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTCOMPUTE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTCOMPUTE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTEXTEND_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't extend heap's space"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTEXTEND_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTEXTEND_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTATTACH_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't attach object"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTATTACH_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTATTACH_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTUPDATE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't update object"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTUPDATE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTUPDATE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTOPERATE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't operate on object"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTOPERATE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTOPERATE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
/* Function entry/exit interface errors */
assert(H5E_CANTINIT_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to initialize object"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTINIT_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTINIT_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_ALREADYINIT_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Object already initialized"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_ALREADYINIT_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_ALREADYINIT_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTRELEASE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to release object"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTRELEASE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTRELEASE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
/* Property list errors */
assert(H5E_CANTGET_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't get value"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTGET_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTGET_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTSET_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't set value"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTSET_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTSET_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_DUPCLASS_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Duplicate class name in parent class"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_DUPCLASS_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_DUPCLASS_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
/* Free space errors */
assert(H5E_CANTMERGE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't merge objects"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTMERGE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTMERGE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTREVIVE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't revive object"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTREVIVE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTREVIVE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTSHRINK_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't shrink container"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTSHRINK_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTSHRINK_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
/* Object header related errors */
assert(H5E_LINKCOUNT_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Bad object header link count"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_LINKCOUNT_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_LINKCOUNT_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_VERSION_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Wrong version number"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_VERSION_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_VERSION_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_ALIGNMENT_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Alignment error"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_ALIGNMENT_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_ALIGNMENT_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_BADMESG_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unrecognized message"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_BADMESG_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_BADMESG_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTDELETE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't delete message"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTDELETE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTDELETE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_BADITER_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Iteration failed"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_BADITER_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_BADITER_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTPACK_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't pack messages"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTPACK_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTPACK_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTRESET_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't reset object"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTRESET_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTRESET_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
/* System level errors */
assert(H5E_SYSERRSTR_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "System error message"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_SYSERRSTR_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_SYSERRSTR_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
/* I/O pipeline errors */
assert(H5E_NOFILTER_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Requested filter is not available"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_NOFILTER_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_NOFILTER_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CALLBACK_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Callback failed"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CALLBACK_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CALLBACK_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANAPPLY_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Error from filter 'can apply' callback"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANAPPLY_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANAPPLY_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_SETLOCAL_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Error from filter 'set local' callback"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_SETLOCAL_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_SETLOCAL_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_NOENCODER_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Filter present but encoding disabled"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_NOENCODER_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_NOENCODER_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTFILTER_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Filter operation failed"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTFILTER_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTFILTER_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
/* Group related errors */
assert(H5E_CANTOPENOBJ_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't open object"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTOPENOBJ_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTOPENOBJ_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTCLOSEOBJ_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't close object"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTCLOSEOBJ_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTCLOSEOBJ_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_COMPLEN_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Name component is too long"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_COMPLEN_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_COMPLEN_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_PATH_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Problem with path to object"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_PATH_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_PATH_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
/* No error */
assert(H5E_NONE_MINOR_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "No error"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_NONE_MINOR_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_NONE_MINOR_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
/* File accessability errors */
assert(H5E_FILEEXISTS_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "File already exists"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_FILEEXISTS_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_FILEEXISTS_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_FILEOPEN_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "File already open"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_FILEOPEN_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_FILEOPEN_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTCREATE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to create file"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTCREATE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTCREATE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTOPENFILE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to open file"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTOPENFILE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTOPENFILE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTCLOSEFILE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to close file"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTCLOSEFILE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTCLOSEFILE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_NOTHDF5_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Not an HDF5 file"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_NOTHDF5_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_NOTHDF5_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_BADFILE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Bad file ID accessed"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_BADFILE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_BADFILE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_TRUNCATED_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "File has been truncated"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_TRUNCATED_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_TRUNCATED_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_MOUNT_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "File mount error"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_MOUNT_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_MOUNT_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
/* Object atom related errors */
assert(H5E_BADATOM_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to find atom information (already closed?)"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_BADATOM_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_BADATOM_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_BADGROUP_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to find ID group information"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_BADGROUP_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_BADGROUP_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTREGISTER_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to register new atom"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTREGISTER_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTREGISTER_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTINC_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to increment reference count"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTINC_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTINC_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTDEC_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to decrement reference count"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTDEC_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTDEC_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_NOIDS_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Out of IDs for group"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_NOIDS_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_NOIDS_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
/* Cache related errors */
assert(H5E_CANTFLUSH_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to flush data from cache"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTFLUSH_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTFLUSH_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTSERIALIZE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to serialize data from cache"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTSERIALIZE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTSERIALIZE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTLOAD_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to load metadata into cache"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTLOAD_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTLOAD_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_PROTECT_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Protected metadata error"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_PROTECT_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_PROTECT_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_NOTCACHED_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Metadata not currently cached"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_NOTCACHED_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_NOTCACHED_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_SYSTEM_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Internal error detected"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_SYSTEM_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_SYSTEM_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTINS_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to insert metadata into cache"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTINS_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTINS_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTRENAME_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to rename metadata"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTRENAME_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTRENAME_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTPROTECT_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to protect metadata"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTPROTECT_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTPROTECT_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTUNPROTECT_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to unprotect metadata"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTUNPROTECT_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTUNPROTECT_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTPIN_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to pin cache entry"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTPIN_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTPIN_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTUNPIN_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to un-pin cache entry"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTUNPIN_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTUNPIN_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTMARKDIRTY_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to mark a pinned entry as dirty"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTMARKDIRTY_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTMARKDIRTY_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTDIRTY_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to mark metadata as dirty"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTDIRTY_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTDIRTY_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTEXPUNGE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to expunge a metadata cache entry"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTEXPUNGE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTEXPUNGE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTRESIZE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to resize a metadata cache entry"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTRESIZE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTRESIZE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
/* Link related errors */
assert(H5E_TRAVERSE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Link traversal failure"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_TRAVERSE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_TRAVERSE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_NLINKS_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Too many soft links in path"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_NLINKS_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_NLINKS_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_NOTREGISTERED_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Link class not registered"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_NOTREGISTERED_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_NOTREGISTERED_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTMOVE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Move callback returned error"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTMOVE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTMOVE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTSORT_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't sort objects"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTSORT_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTSORT_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
/* Parallel MPI errors */
assert(H5E_MPI_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Some MPI function failed"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_MPI_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_MPI_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_MPIERRSTR_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "MPI Error String"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_MPIERRSTR_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_MPIERRSTR_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTRECV_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't receive data"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTRECV_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTRECV_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
/* Dataspace errors */
assert(H5E_CANTCLIP_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't clip hyperslab region"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTCLIP_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTCLIP_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTCOUNT_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't count elements"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTCOUNT_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTCOUNT_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTSELECT_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't select hyperslab"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTSELECT_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTSELECT_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTNEXT_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't move to next iterator location"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTNEXT_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTNEXT_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_BADSELECT_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Invalid selection"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_BADSELECT_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_BADSELECT_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTCOMPARE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't compare objects"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTCOMPARE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTCOMPARE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<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)
+if((H5E_UNINITIALIZED_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<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)
+if((H5E_UNSUPPORTED_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<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)
+if((H5E_BADTYPE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<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)
+if((H5E_BADRANGE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<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)
+if((H5E_BADVALUE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<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)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_NOTFOUND_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_NOTFOUND_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_EXISTS_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Object already exists"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_EXISTS_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_EXISTS_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTENCODE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to encode value"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTENCODE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTENCODE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTDECODE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to decode value"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTDECODE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTDECODE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTSPLIT_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to split node"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTSPLIT_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTSPLIT_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTREDISTRIBUTE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to redistribute records"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTREDISTRIBUTE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTREDISTRIBUTE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTSWAP_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to swap records"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTSWAP_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTSWAP_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTINSERT_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to insert object"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTINSERT_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTINSERT_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTLIST_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to list node"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTLIST_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTLIST_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTMODIFY_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to modify record"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTMODIFY_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTMODIFY_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_CANTREMOVE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to remove object"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTREMOVE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTREMOVE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<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)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_CANTCONVERT_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_CANTCONVERT_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
assert(H5E_BADSIZE_g==(-1));
if((msg = H5E_create_msg(cls, H5E_MINOR, "Bad size for object"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
-if((H5E_BADSIZE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+if((H5E_BADSIZE_g = H5I_register(H5I_ERROR_MSG, msg, FALSE))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
#endif /* H5Einit_H */
diff --git a/src/H5Eint.c b/src/H5Eint.c
index 66fba91..ba1b1e0 100644
--- a/src/H5Eint.c
+++ b/src/H5Eint.c
@@ -238,8 +238,8 @@ H5E_walk1_cb(int n, H5E_error1_t *err_desc, void *client_data)
stream = eprint->stream;
/* Get descriptions for the major and minor error numbers */
- maj_ptr = H5I_object_verify(err_desc->maj_num, H5I_ERROR_MSG);
- min_ptr = H5I_object_verify(err_desc->min_num, H5I_ERROR_MSG);
+ maj_ptr = (H5E_msg_t *)H5I_object_verify(err_desc->maj_num, H5I_ERROR_MSG);
+ min_ptr = (H5E_msg_t *)H5I_object_verify(err_desc->min_num, H5I_ERROR_MSG);
HDassert(maj_ptr && min_ptr);
if(maj_ptr->msg)
maj_str = maj_ptr->msg;
@@ -275,11 +275,7 @@ H5E_walk1_cb(int n, H5E_error1_t *err_desc, void *client_data)
fprintf(stream, "thread 0");
} /* end block */
#elif defined(H5_HAVE_THREADSAFE)
-#ifdef _WIN32
- fprintf(stream, "some thread: no way to know the thread number from pthread on windows");
-#else
- fprintf(stream, "thread %lu", (unsigned long)pthread_self());
-#endif
+ fprintf(stream, "thread %lu", HDpthread_self_ulong());
#else
fprintf(stream, "thread 0");
#endif
@@ -358,8 +354,8 @@ H5E_walk2_cb(unsigned n, const H5E_error2_t *err_desc, void *client_data)
stream = eprint->stream;
/* Get descriptions for the major and minor error numbers */
- maj_ptr = H5I_object_verify(err_desc->maj_num, H5I_ERROR_MSG);
- min_ptr = H5I_object_verify(err_desc->min_num, H5I_ERROR_MSG);
+ maj_ptr = (H5E_msg_t *)H5I_object_verify(err_desc->maj_num, H5I_ERROR_MSG);
+ min_ptr = (H5E_msg_t *)H5I_object_verify(err_desc->min_num, H5I_ERROR_MSG);
HDassert(maj_ptr && min_ptr);
if(maj_ptr->msg)
maj_str = maj_ptr->msg;
@@ -395,11 +391,7 @@ H5E_walk2_cb(unsigned n, const H5E_error2_t *err_desc, void *client_data)
fprintf(stream, "thread 0");
} /* end block */
#elif defined(H5_HAVE_THREADSAFE)
-#ifdef _WIN32
- fprintf(stream, "some thread: no way to know the thread number from pthread on windows");
-#else
- fprintf(stream, "thread %lu", (unsigned long)pthread_self());
-#endif
+ fprintf(stream, "thread %lu", HDpthread_self_ulong());
#else
fprintf(stream, "thread 0");
#endif
@@ -668,6 +660,107 @@ H5E_set_auto(H5E_t *estack, const H5E_auto_op_t *op, void *client_data)
/*-------------------------------------------------------------------------
+ * Function: H5E_printf_stack
+ *
+ * Purpose: Printf-like wrapper around H5E_push_stack.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, August 12, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5E_printf_stack(H5E_t *estack, const char *file, const char *func, unsigned line,
+ hid_t cls_id, hid_t maj_id, hid_t min_id, const char *fmt, ...)
+{
+ va_list ap; /* Varargs info */
+#ifndef H5_HAVE_VASPRINTF
+ int tmp_len; /* Current size of description buffer */
+ int desc_len; /* Actual length of description when formatted */
+#endif /* H5_HAVE_VASPRINTF */
+ char *tmp = NULL; /* Buffer to place formatted description in */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ /*
+ * WARNING: We cannot call HERROR() from within this function or else we
+ * could enter infinite recursion. Furthermore, we also cannot
+ * call any other HDF5 macro or function which might call
+ * HERROR(). HERROR() is called by HRETURN_ERROR() which could
+ * be called by FUNC_ENTER().
+ */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5E_printf_stack)
+
+ /* Sanity check */
+ HDassert(cls_id > 0);
+ HDassert(maj_id > 0);
+ HDassert(min_id > 0);
+ HDassert(fmt);
+
+/* Note that the variable-argument parsing for the format is identical in
+ * the H5Epush2() routine - correct errors and make changes in both
+ * places. -QAK
+ */
+
+ /* Start the variable-argument parsing */
+ va_start(ap, fmt);
+
+#ifdef H5_HAVE_VASPRINTF
+ /* Use the vasprintf() routine, since it does what we're trying to do below */
+ if(HDvasprintf(&tmp, fmt, ap) < 0)
+ HGOTO_DONE(FAIL)
+#else /* H5_HAVE_VASPRINTF */
+ /* Allocate space for the formatted description buffer */
+ tmp_len = 128;
+ if(NULL == (tmp = H5MM_malloc((size_t)tmp_len)))
+ HGOTO_DONE(FAIL)
+
+ /* If the description doesn't fit into the initial buffer size, allocate more space and try again */
+ while((desc_len = HDvsnprintf(tmp, (size_t)tmp_len, fmt, ap))
+#ifdef H5_VSNPRINTF_WORKS
+ >
+#else /* H5_VSNPRINTF_WORKS */
+ >=
+#endif /* H5_VSNPRINTF_WORKS */
+ (tmp_len - 1)
+#ifndef H5_VSNPRINTF_WORKS
+ || (desc_len < 0)
+#endif /* H5_VSNPRINTF_WORKS */
+ ) {
+ /* shutdown & restart the va_list */
+ va_end(ap);
+ va_start(ap, fmt);
+
+ /* Release the previous description, it's too small */
+ H5MM_xfree(tmp);
+
+ /* Allocate a description of the appropriate length */
+#ifdef H5_VSNPRINTF_WORKS
+ tmp_len = desc_len + 1;
+#else /* H5_VSNPRINTF_WORKS */
+ tmp_len = 2 * tmp_len;
+#endif /* H5_VSNPRINTF_WORKS */
+ if(NULL == (tmp = H5MM_malloc((size_t)tmp_len)))
+ HGOTO_DONE(FAIL)
+ } /* end while */
+#endif /* H5_HAVE_VASPRINTF */
+
+ va_end(ap);
+
+ /* Push the error on the stack */
+ if(H5E_push_stack(estack, file, func, line, cls_id, maj_id, min_id, tmp) < 0)
+ HGOTO_DONE(FAIL)
+
+done:
+ if(tmp)
+ H5MM_xfree(tmp);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5E_printf_stack() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5E_push_stack
*
* Purpose: Pushes a new error record onto error stack for the current
@@ -730,13 +823,13 @@ H5E_push_stack(H5E_t *estack, const char *file, const char *func, unsigned line,
if(estack->nused < H5E_NSLOTS) {
/* Increment the IDs to indicate that they are used in this stack */
- if(H5I_inc_ref(cls_id) < 0)
+ if(H5I_inc_ref(cls_id, FALSE) < 0)
HGOTO_DONE(FAIL)
estack->slot[estack->nused].cls_id = cls_id;
- if(H5I_inc_ref(maj_id) < 0)
+ if(H5I_inc_ref(maj_id, FALSE) < 0)
HGOTO_DONE(FAIL)
estack->slot[estack->nused].maj_num = maj_id;
- if(H5I_inc_ref(min_id) < 0)
+ if(H5I_inc_ref(min_id, FALSE) < 0)
HGOTO_DONE(FAIL)
estack->slot[estack->nused].min_num = min_id;
if(NULL == (estack->slot[estack->nused].func_name = H5MM_xstrdup(func)))
@@ -786,11 +879,11 @@ H5E_clear_entries(H5E_t *estack, size_t nentries)
/* Decrement the IDs to indicate that they are no longer used by this stack */
/* (In reverse order that they were incremented, so that reference counts work well) */
- if(H5I_dec_ref(error->min_num) < 0)
+ if(H5I_dec_ref(error->min_num, FALSE) < 0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTDEC, FAIL, "unable to decrement ref count on error message")
- if(H5I_dec_ref(error->maj_num) < 0)
+ if(H5I_dec_ref(error->maj_num, FALSE) < 0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTDEC, FAIL, "unable to decrement ref count on error message")
- if(H5I_dec_ref(error->cls_id) < 0)
+ if(H5I_dec_ref(error->cls_id, FALSE) < 0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTDEC, FAIL, "unable to decrement ref count on error class")
/* Release strings */
@@ -894,7 +987,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5E_dump_api_stack(int is_api)
+H5E_dump_api_stack(hbool_t is_api)
{
herr_t ret_value = SUCCEED; /* Return value */
diff --git a/src/H5Eprivate.h b/src/H5Eprivate.h
index 05ce10e..7b1d7ef 100644
--- a/src/H5Eprivate.h
+++ b/src/H5Eprivate.h
@@ -40,7 +40,7 @@ typedef struct H5E_t H5E_t;
*/
#define HCOMMON_ERROR(maj, min, str) \
HERROR(maj, min, str); \
- (void)H5E_dump_api_stack((int)H5_IS_API(FUNC));
+ (void)H5E_dump_api_stack((hbool_t)H5_IS_API(FUNC));
/*
* HDONE_ERROR macro, used to facilitate error reporting between a
@@ -78,10 +78,12 @@ typedef struct H5E_t H5E_t;
/* Library-private functions defined in H5E package */
H5_DLL herr_t H5E_init(void);
-H5_DLL herr_t H5E_push_stack(H5E_t *estack, const char *file, const char *func, unsigned line,
- hid_t cls_id, hid_t maj_id, hid_t min_id, const char *desc);
+H5_DLL herr_t H5E_push_stack(H5E_t *estack, const char *file, const char *func,
+ unsigned line, hid_t cls_id, hid_t maj_id, hid_t min_id, const char *desc);
+H5_DLL herr_t H5E_printf_stack(H5E_t *estack, const char *file, const char *func,
+ unsigned line, hid_t cls_id, hid_t maj_id, hid_t min_id, const char *fmt, ...);
H5_DLL herr_t H5E_clear_stack(H5E_t *estack);
-H5_DLL herr_t H5E_dump_api_stack(int is_api);
+H5_DLL herr_t H5E_dump_api_stack(hbool_t is_api);
/*
* Macros handling system error messages as described in C standard.
diff --git a/src/H5Epubgen.h b/src/H5Epubgen.h
index 8386e0f..4e981dc 100644
--- a/src/H5Epubgen.h
+++ b/src/H5Epubgen.h
@@ -50,6 +50,7 @@
#define H5E_EFL (H5OPEN H5E_EFL_g)
#define H5E_TST (H5OPEN H5E_TST_g)
#define H5E_ARGS (H5OPEN H5E_ARGS_g)
+#define H5E_EARRAY (H5OPEN H5E_EARRAY_g)
#define H5E_ERROR (H5OPEN H5E_ERROR_g)
#define H5E_PLINE (H5OPEN H5E_PLINE_g)
#define H5E_FSPACE (H5OPEN H5E_FSPACE_g)
@@ -80,6 +81,7 @@ H5_DLLVAR hid_t H5E_SLIST_g; /* Skip Lists */
H5_DLLVAR hid_t H5E_EFL_g; /* External file list */
H5_DLLVAR hid_t H5E_TST_g; /* Ternary Search Trees */
H5_DLLVAR hid_t H5E_ARGS_g; /* Invalid arguments to routine */
+H5_DLLVAR hid_t H5E_EARRAY_g; /* Extensible Array */
H5_DLLVAR hid_t H5E_ERROR_g; /* Error API */
H5_DLLVAR hid_t H5E_PLINE_g; /* Data filters */
H5_DLLVAR hid_t H5E_FSPACE_g; /* Free Space Manager */
diff --git a/src/H5Epublic.h b/src/H5Epublic.h
index b0e93bb..932b857 100644
--- a/src/H5Epublic.h
+++ b/src/H5Epublic.h
@@ -180,7 +180,7 @@ H5_DLL ssize_t H5Eget_num(hid_t error_stack_id);
/* Symbols defined for compatibility with previous versions of the HDF5 API.
- *
+ *
* Use of these symbols is deprecated.
*/
#ifndef H5_NO_DEPRECATED_SYMBOLS
diff --git a/src/H5Eterm.h b/src/H5Eterm.h
index dedc313..7595e7f 100644
--- a/src/H5Eterm.h
+++ b/src/H5Eterm.h
@@ -48,6 +48,7 @@ H5E_SLIST_g=
H5E_EFL_g=
H5E_TST_g=
H5E_ARGS_g=
+H5E_EARRAY_g=
H5E_ERROR_g=
H5E_PLINE_g=
H5E_FSPACE_g=
diff --git a/src/H5F.c b/src/H5F.c
index 58ea43e..3789fec 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -29,6 +29,7 @@
#include "H5FDprivate.h" /* File drivers */
#include "H5Gprivate.h" /* Groups */
#include "H5Iprivate.h" /* IDs */
+#include "H5MFprivate.h" /* File memory management */
#include "H5MMprivate.h" /* Memory management */
#include "H5Pprivate.h" /* Property lists */
#include "H5SMprivate.h" /* Shared Object Header Messages */
@@ -42,17 +43,16 @@
#include "H5FDmulti.h" /*multiple files partitioned by mem usage */
#include "H5FDsec2.h" /*Posix unbuffered I/O */
#include "H5FDstdio.h" /* Standard C buffered I/O */
-#ifdef H5_HAVE_WINDOWS
+#ifdef H5_HAVE_WINDOWS
#include "H5FDwindows.h" /* Windows buffered I/O */
#endif
-#include "H5FDstream.h" /*in-memory files streamed via sockets */
#include "H5FDdirect.h" /*Linux direct I/O */
/* Struct only used by functions H5F_get_objects and H5F_get_objects_cb */
typedef struct H5F_olist_t {
H5I_type_t obj_type; /* Type of object to look for */
hid_t *obj_id_list; /* Pointer to the list of open IDs to return */
- unsigned *obj_id_count; /* Number of open IDs */
+ size_t *obj_id_count; /* Number of open IDs */
struct {
hbool_t local; /* Set flag for "local" file searches */
union {
@@ -60,12 +60,12 @@ typedef struct H5F_olist_t {
const H5F_t *file; /* Pointer to file to look inside */
} ptr;
} file_info;
- unsigned list_index; /* Current index in open ID array */
- int max_index; /* Maximum # of IDs to put into array */
+ size_t list_index; /* Current index in open ID array */
+ size_t max_index; /* Maximum # of IDs to put into array */
} H5F_olist_t;
/* PRIVATE PROTOTYPES */
-static unsigned H5F_get_objects(const H5F_t *f, unsigned types, int max_objs, hid_t *obj_id_list);
+static size_t H5F_get_objects(const H5F_t *f, unsigned types, size_t max_objs, hid_t *obj_id_list, hbool_t app_ref);
static int H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key);
static herr_t H5F_get_vfd_handle(const H5F_t *file, hid_t fapl, void** file_handle);
static H5F_t *H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id,
@@ -165,7 +165,7 @@ H5F_term_interface(void)
if(H5_interface_initialize_g) {
if((n = H5I_nmembers(H5I_FILE)) != 0) {
- H5I_clear_type(H5I_FILE, FALSE);
+ H5I_clear_type(H5I_FILE, FALSE, FALSE);
} else {
/* Make certain we've cleaned up all the shared file objects */
H5F_sfile_assert_num(0);
@@ -206,13 +206,13 @@ H5Fget_create_plist(hid_t file_id)
H5TRACE1("i", "i", file_id);
/* check args */
- if(NULL == (file = H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
- if(NULL == (plist = H5I_object(file->shared->fcpl_id)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(file->shared->fcpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
/* Create the property list object to return */
- if((ret_value = H5P_copy_plist(plist)) < 0)
+ if((ret_value = H5P_copy_plist(plist, TRUE)) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_CANTINIT, FAIL, "unable to copy file creation properties")
done:
@@ -251,11 +251,11 @@ H5Fget_access_plist(hid_t file_id)
H5TRACE1("i", "i", file_id);
/* Check args */
- if(NULL == (f = H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (f = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
/* Retrieve the file's access property list */
- if((ret_value = H5F_get_access_plist(f)) < 0)
+ if((ret_value = H5F_get_access_plist(f, TRUE)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get file access property list")
done:
@@ -287,7 +287,7 @@ done:
*-------------------------------------------------------------------------
*/
hid_t
-H5F_get_access_plist(H5F_t *f)
+H5F_get_access_plist(H5F_t *f, hbool_t app_ref)
{
H5P_genplist_t *new_plist; /* New property list */
H5P_genplist_t *old_plist; /* Old property list */
@@ -300,18 +300,18 @@ H5F_get_access_plist(H5F_t *f)
HDassert(f);
/* Make a copy of the default file access property list */
- if(NULL == (old_plist = H5I_object(H5P_LST_FILE_ACCESS_g)))
+ if(NULL == (old_plist = (H5P_genplist_t *)H5I_object(H5P_LST_FILE_ACCESS_g)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
- if((ret_value = H5P_copy_plist(old_plist)) < 0)
+ if((ret_value = H5P_copy_plist(old_plist, app_ref)) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_CANTINIT, FAIL, "can't copy file access property list")
- if(NULL == (new_plist = H5I_object(ret_value)))
+ if(NULL == (new_plist = (H5P_genplist_t *)H5I_object(ret_value)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
/* Copy properties of the file access property list */
if(H5P_set(new_plist, H5F_ACS_META_CACHE_INIT_CONFIG_NAME, &(f->shared->mdc_initCacheCfg)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set initial meta data cache resize config.")
- if(H5P_set(new_plist, H5F_ACS_DATA_CACHE_ELMT_SIZE_NAME, &(f->shared->rdcc_nelmts)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set data cache element size")
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set initial metadata cache resize config.")
+ if(H5P_set(new_plist, H5F_ACS_DATA_CACHE_NUM_SLOTS_NAME, &(f->shared->rdcc_nslots)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set data cache number of slots")
if(H5P_set(new_plist, H5F_ACS_DATA_CACHE_BYTE_SIZE_NAME, &(f->shared->rdcc_nbytes)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set data cache byte size")
if(H5P_set(new_plist, H5F_ACS_PREEMPT_READ_CHUNKS_NAME, &(f->shared->rdcc_w0)) < 0)
@@ -322,11 +322,11 @@ H5F_get_access_plist(H5F_t *f)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set alignment")
if(H5P_set(new_plist, H5F_ACS_GARBG_COLCT_REF_NAME, &(f->shared->gc_ref)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set garbage collect reference")
- if(H5P_set(new_plist, H5F_ACS_META_BLOCK_SIZE_NAME, &(f->shared->lf->def_meta_block_size)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set meta data cache size")
+ if(H5P_set(new_plist, H5F_ACS_META_BLOCK_SIZE_NAME, &(f->shared->meta_aggr.alloc_size)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set metadata cache size")
if(H5P_set(new_plist, H5F_ACS_SIEVE_BUF_SIZE_NAME, &(f->shared->sieve_buf_size)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't sieve buffer size")
- if(H5P_set(new_plist, H5F_ACS_SDATA_BLOCK_SIZE_NAME, &(f->shared->lf->def_sdata_block_size)) < 0)
+ if(H5P_set(new_plist, H5F_ACS_SDATA_BLOCK_SIZE_NAME, &(f->shared->sdata_aggr.alloc_size)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set 'small data' cache size")
if(H5P_set(new_plist, H5F_ACS_LATEST_FORMAT_NAME, &(f->shared->latest_format)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set 'latest format' flag")
@@ -339,7 +339,7 @@ H5F_get_access_plist(H5F_t *f)
HGOTO_ERROR(H5E_PLIST, H5E_CANTFREE, FAIL, "can't free the old driver information")
/* Increment the reference count on the driver ID and insert it into the property list */
- if(H5I_inc_ref(f->shared->lf->driver_id) < 0)
+ if(H5I_inc_ref(f->shared->lf->driver_id, FALSE) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINC, FAIL, "unable to increment ref count on VFL driver")
if(H5P_set(new_plist, H5F_ACS_FILE_DRV_ID_NAME, &(f->shared->lf->driver_id)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file driver ID")
@@ -371,31 +371,34 @@ done:
*
* Programmer: Raymond Lu
* Wednesday, Dec 5, 2001
- *
* Modification:
+ * Raymond Lu
+ * 24 September 2008
+ * Changed the return value to ssize_t to accommadate
+ * potential large number of objects.
*
*-------------------------------------------------------------------------
*/
-int
+ssize_t
H5Fget_obj_count(hid_t file_id, unsigned types)
{
- H5F_t *f=NULL;
- int ret_value; /* Return value */
+ H5F_t *f = NULL; /* File to query */
+ ssize_t ret_value; /* Return value */
FUNC_ENTER_API(H5Fget_obj_count, FAIL)
- H5TRACE2("Is", "iIu", file_id, types);
+ H5TRACE2("Zs", "iIu", file_id, types);
- if( file_id != (hid_t)H5F_OBJ_ALL && (NULL==(f=H5I_object_verify(file_id,H5I_FILE))) )
+ if(file_id != (hid_t)H5F_OBJ_ALL && (NULL == (f = (H5F_t *)H5I_object_verify(file_id, H5I_FILE))))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file id")
- if( (types&H5F_OBJ_ALL)==0)
+ if(0 == (types & H5F_OBJ_ALL))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not an object type")
- if((ret_value = H5F_get_obj_count(f, types)) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCOUNT, FAIL, "can't get object count")
+ /* H5F_get_obj_count doesn't fail */
+ ret_value = H5F_get_obj_count(f, types, TRUE);
done:
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5Fget_obj_count() */
/*-------------------------------------------------------------------------
@@ -404,23 +407,28 @@ done:
* Purpose: Private function return the number of opened object IDs
* (files, datasets, groups, datatypes) in the same file.
*
- * Return: Non-negative on success; negative on failure.
+ * Return: Non-negative on success; can't fail.
*
* Programmer: Raymond Lu
* Wednesday, Dec 5, 2001
*
* Modification:
+ * Raymond Lu
+ * 24 September 2008
+ * Changed the return value to size_t to accommadate
+ * potential large number of objects.
*
*-------------------------------------------------------------------------
*/
-unsigned
-H5F_get_obj_count(const H5F_t *f, unsigned types)
+size_t
+H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref)
{
- unsigned ret_value; /* Return value */
+ size_t ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_obj_count)
- ret_value=H5F_get_objects(f, types, -1, NULL);
+ /* H5F_get_objects doesn't fail */
+ ret_value=H5F_get_objects(f, types, 0, NULL, app_ref);
FUNC_LEAVE_NOAPI(ret_value)
}
@@ -437,29 +445,34 @@ H5F_get_obj_count(const H5F_t *f, unsigned types)
* Wednesday, Dec 5, 2001
*
* Modification:
+ * Raymond Lu
+ * 24 September 2008
+ * Changed the return value to ssize_t and MAX_OBJTS to size_t to
+ * accommadate potential large number of objects.
*
*-------------------------------------------------------------------------
*/
-herr_t
-H5Fget_obj_ids(hid_t file_id, unsigned types, int max_objs, hid_t *oid_list)
+ssize_t
+H5Fget_obj_ids(hid_t file_id, unsigned types, size_t max_objs, hid_t *oid_list)
{
- herr_t ret_value;
- H5F_t *f=NULL;
+ H5F_t *f = NULL; /* File to query */
+ ssize_t ret_value; /* Return value */
FUNC_ENTER_API(H5Fget_obj_ids, FAIL)
- H5TRACE4("e", "iIuIs*i", file_id, types, max_objs, oid_list);
+ H5TRACE4("Zs", "iIuz*i", file_id, types, max_objs, oid_list);
- if( file_id != (hid_t)H5F_OBJ_ALL && (NULL==(f=H5I_object_verify(file_id,H5I_FILE))) )
+ if(file_id != (hid_t)H5F_OBJ_ALL && (NULL == (f = (H5F_t *)H5I_object_verify(file_id, H5I_FILE))))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file id")
- if( (types&H5F_OBJ_ALL)==0)
+ if(0 == (types & H5F_OBJ_ALL))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not an object type")
- assert(oid_list);
-
- ret_value = H5F_get_obj_ids(f, types, max_objs, oid_list);
+ HDassert(oid_list);
+
+ /* H5F_get_objects doesn't fail */
+ ret_value = H5F_get_obj_ids(f, types, max_objs, oid_list, TRUE);
done:
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5Fget_obj_ids() */
/*-------------------------------------------------------------------------
@@ -467,23 +480,28 @@ done:
*
* Purpose: Private function to return a list of opened object IDs.
*
- * Return: Non-negative on success; negative on failure.
+ * Return: Non-negative on success; can't fail.
*
* Programmer: Raymond Lu
* Wednesday, Dec 5, 2001
*
* Modification:
+ * Raymond Lu
+ * 24 September 2008
+ * Changed the return value and MAX_OBJTS to size_t to accommadate
+ * potential large number of objects.
*
*-------------------------------------------------------------------------
*/
-unsigned
-H5F_get_obj_ids(const H5F_t *f, unsigned types, int max_objs, hid_t *oid_list)
+size_t
+H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *oid_list, hbool_t app_ref)
{
- unsigned ret_value; /* Return value */
+ size_t ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_obj_ids)
- ret_value = H5F_get_objects(f, types, max_objs, oid_list);
+ /* H5F_get_objects doesn't fail */
+ ret_value = H5F_get_objects(f, types, max_objs, oid_list, app_ref);
FUNC_LEAVE_NOAPI(ret_value)
}
@@ -495,7 +513,7 @@ H5F_get_obj_ids(const H5F_t *f, unsigned types, int max_objs, hid_t *oid_list)
* Purpose: This function is called by H5F_get_obj_count or
* H5F_get_obj_ids to get number of object IDs and/or a
* list of opened object IDs (in return value).
- * Return: Non-negative on success; negative on failure.
+ * Return: Non-negative on success; Can't fail.
*
* Programmer: Raymond Lu
* Wednesday, Dec 5, 2001
@@ -504,12 +522,12 @@ H5F_get_obj_ids(const H5F_t *f, unsigned types, int max_objs, hid_t *oid_list)
*
*---------------------------------------------------------------------------
*/
-static unsigned
-H5F_get_objects(const H5F_t *f, unsigned types, int max_index, hid_t *obj_id_list)
+static size_t
+H5F_get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_list, hbool_t app_ref)
{
- unsigned obj_id_count=0; /* Number of open IDs */
+ size_t obj_id_count=0; /* Number of open IDs */
H5F_olist_t olist; /* Structure to hold search results */
- unsigned ret_value; /* Return value */
+ size_t ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_objects)
@@ -520,7 +538,7 @@ H5F_get_objects(const H5F_t *f, unsigned types, int max_index, hid_t *obj_id_lis
olist.max_index = max_index;
/* Determine if we are searching for local or global objects */
- if(types&H5F_OBJ_LOCAL) {
+ if(types & H5F_OBJ_LOCAL) {
olist.file_info.local = TRUE;
olist.file_info.ptr.file = f;
} /* end if */
@@ -530,38 +548,39 @@ H5F_get_objects(const H5F_t *f, unsigned types, int max_index, hid_t *obj_id_lis
} /* end else */
/* Search through file IDs to count the number, and put their
- * IDs on the object list */
+ * IDs on the object list. H5I_search returns NULL if no object
+ * is found, so don't return failure in this function. */
if(types & H5F_OBJ_FILE) {
olist.obj_type = H5I_FILE;
- (void)H5I_search(H5I_FILE, H5F_get_objects_cb, &olist);
+ (void)H5I_search(H5I_FILE, H5F_get_objects_cb, &olist, app_ref);
} /* end if */
/* Search through dataset IDs to count number of datasets, and put their
* IDs on the object list */
- if( (max_index < 0 || (int)olist.list_index < max_index) && (types & H5F_OBJ_DATASET) ) {
+ if(types & H5F_OBJ_DATASET) {
olist.obj_type = H5I_DATASET;
- (void)H5I_search(H5I_DATASET, H5F_get_objects_cb, &olist);
+ (void)H5I_search(H5I_DATASET, H5F_get_objects_cb, &olist, app_ref);
}
/* Search through group IDs to count number of groups, and put their
* IDs on the object list */
- if( (max_index < 0 || (int)olist.list_index < max_index) && (types & H5F_OBJ_GROUP) ) {
+ if(types & H5F_OBJ_GROUP) {
olist.obj_type = H5I_GROUP;
- (void)H5I_search(H5I_GROUP, H5F_get_objects_cb, &olist);
+ (void)H5I_search(H5I_GROUP, H5F_get_objects_cb, &olist, app_ref);
}
/* Search through datatype IDs to count number of named datatypes, and put their
* IDs on the object list */
- if( (max_index < 0 || (int)olist.list_index < max_index) && (types & H5F_OBJ_DATATYPE) ) {
+ if(types & H5F_OBJ_DATATYPE) {
olist.obj_type = H5I_DATATYPE;
- (void)H5I_search(H5I_DATATYPE, H5F_get_objects_cb, &olist);
+ (void)H5I_search(H5I_DATATYPE, H5F_get_objects_cb, &olist, app_ref);
}
/* Search through attribute IDs to count number of attributes, and put their
* IDs on the object list */
- if( (max_index < 0 || (int)olist.list_index < max_index) && (types & H5F_OBJ_ATTR) ) {
+ if(types & H5F_OBJ_ATTR) {
olist.obj_type = H5I_ATTR;
- (void)H5I_search(H5I_ATTR, H5F_get_objects_cb, &olist);
+ (void)H5I_search(H5I_ATTR, H5F_get_objects_cb, &olist, app_ref);
}
/* Set the number of objects currently open */
@@ -578,6 +597,9 @@ H5F_get_objects(const H5F_t *f, unsigned types, int max_index, hid_t *obj_id_lis
* object is in the file, and either count it or put its ID
* on the list.
*
+ * Return: TRUE if the array of object IDs is filled up.
+ * FALSE otherwise.
+ *
* Programmer: Raymond Lu
* Wednesday, Dec 5, 2001
*
@@ -593,8 +615,8 @@ H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key)
FUNC_ENTER_NOAPI_NOINIT(H5F_get_objects_cb)
- assert(obj_ptr);
- assert(olist);
+ HDassert(obj_ptr);
+ HDassert(olist);
/* Count file IDs */
if(olist->obj_type == H5I_FILE) {
@@ -612,60 +634,71 @@ H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key)
if(olist->obj_id_count)
(*olist->obj_id_count)++;
- /* Check if we've filled up the array */
- if(olist->max_index>=0 && (int)olist->list_index>=olist->max_index)
+ /* Check if we've filled up the array. Return TRUE only if
+ * we have filled up the array. Otherwise return FALSE(RET_VALUE is
+ * preset to FALSE) because H5I_search needs the return value of FALSE
+ * to continue searching. */
+ if(olist->max_index>0 && olist->list_index>=olist->max_index)
HGOTO_DONE(TRUE) /* Indicate that the iterator should stop */
}
- } else { /* either count opened object IDs or put the IDs on the list */
+ } /* end if */
+ else { /* either count opened object IDs or put the IDs on the list */
H5O_loc_t *oloc; /* Group entry info for object */
switch(olist->obj_type) {
case H5I_ATTR:
- oloc = H5A_oloc((H5A_t*)obj_ptr);
+ oloc = H5A_oloc((H5A_t *)obj_ptr);
break;
+
case H5I_GROUP:
- oloc = H5G_oloc((H5G_t*)obj_ptr);
+ oloc = H5G_oloc((H5G_t *)obj_ptr);
break;
+
case H5I_DATASET:
- oloc = H5D_oloc((H5D_t*)obj_ptr);
+ oloc = H5D_oloc((H5D_t *)obj_ptr);
break;
+
case H5I_DATATYPE:
if(H5T_is_named((H5T_t*)obj_ptr)==TRUE)
oloc = H5T_oloc((H5T_t*)obj_ptr);
else
oloc = NULL;
break;
+
default:
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "unknown data object")
- }
+ } /* end switch */
if((olist->file_info.local &&
- ( (!olist->file_info.ptr.file && olist->obj_type==H5I_DATATYPE && H5T_is_immutable((H5T_t*)obj_ptr)==FALSE)
- || (!olist->file_info.ptr.file && olist->obj_type!=H5I_DATATYPE)
- || (oloc && oloc->file == olist->file_info.ptr.file) ))
+ ( (!olist->file_info.ptr.file && olist->obj_type == H5I_DATATYPE && H5T_is_immutable((H5T_t *)obj_ptr) == FALSE)
+ || (!olist->file_info.ptr.file && olist->obj_type != H5I_DATATYPE)
+ || (oloc && oloc->file == olist->file_info.ptr.file)))
|| (!olist->file_info.local &&
- ((!olist->file_info.ptr.shared && olist->obj_type==H5I_DATATYPE && H5T_is_immutable((H5T_t*)obj_ptr)==FALSE)
- || (!olist->file_info.ptr.shared && olist->obj_type!=H5I_DATATYPE)
- || (oloc && oloc->file && oloc->file->shared == olist->file_info.ptr.shared) ))) {
+ ((!olist->file_info.ptr.shared && olist->obj_type == H5I_DATATYPE && H5T_is_immutable((H5T_t *)obj_ptr) == FALSE)
+ || (!olist->file_info.ptr.shared && olist->obj_type != H5I_DATATYPE)
+ || (oloc && oloc->file && oloc->file->shared == olist->file_info.ptr.shared)))) {
/* Add the object's ID to the ID list, if appropriate */
if(olist->obj_id_list) {
olist->obj_id_list[olist->list_index] = obj_id;
olist->list_index++;
- }
+ } /* end if */
/* Increment the number of open objects */
if(olist->obj_id_count)
(*olist->obj_id_count)++;
- /* Check if we've filled up the array */
- if(olist->max_index>=0 && (int)olist->list_index>=olist->max_index)
+ /* Check if we've filled up the array. Return TRUE only if
+ * we have filled up the array. Otherwise return FALSE(RET_VALUE is
+ * preset to FALSE) because H5I_search needs the return value of FALSE
+ * to continue searching. */
+ if(olist->max_index>0 && olist->list_index>=olist->max_index)
HGOTO_DONE(TRUE) /* Indicate that the iterator should stop */
- }
- }
+ } /* end if */
+ } /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5F_get_objects_cb() */
/*-------------------------------------------------------------------------
@@ -688,22 +721,25 @@ done:
herr_t
H5Fget_vfd_handle(hid_t file_id, hid_t fapl, void **file_handle)
{
- H5F_t *file=NULL;
- herr_t ret_value;
+ H5F_t *file; /* File to query */
+ herr_t ret_value; /* Return value */
FUNC_ENTER_API(H5Fget_vfd_handle, FAIL)
H5TRACE3("e", "ii**x", file_id, fapl, file_handle);
/* Check args */
- assert(file_handle);
- if(NULL==(file=H5I_object_verify(file_id, H5I_FILE)))
+ if(!file_handle)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file handle pointer")
+
+ /* Get the file */
+ if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file id")
- ret_value=H5F_get_vfd_handle(file, fapl, file_handle);
+ ret_value = H5F_get_vfd_handle(file, fapl, file_handle);
done:
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5Fget_vfd_handle() */
/*-------------------------------------------------------------------------
@@ -762,31 +798,31 @@ done:
htri_t
H5Fis_hdf5(const char *name)
{
- H5FD_t *file = NULL;
- htri_t ret_value;
+ H5FD_t *file = NULL; /* Low-level file struct */
+ htri_t ret_value; /* Return value */
FUNC_ENTER_API(H5Fis_hdf5, FAIL)
H5TRACE1("t", "*s", name);
/* Check args and all the boring stuff. */
- if (!name || !*name)
+ if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "no file name specified")
/* Open the file at the virtual file layer */
- if (NULL==(file=H5FD_open(name, H5F_ACC_RDONLY, H5P_FILE_ACCESS_DEFAULT, HADDR_UNDEF)))
+ if(NULL == (file = H5FD_open(name, H5F_ACC_RDONLY, H5P_FILE_ACCESS_DEFAULT, HADDR_UNDEF)))
HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to open file")
/* The file is an hdf5 file if the hdf5 file signature can be found */
- ret_value = (HADDR_UNDEF!=H5F_locate_signature(file, H5AC_ind_dxpl_id));
+ ret_value = (HADDR_UNDEF != H5F_locate_signature(file, H5AC_ind_dxpl_id));
done:
/* Close the file */
- if (file)
- if(H5FD_close(file) < 0 && ret_value>=0)
+ if(file)
+ if(H5FD_close(file) < 0 && ret_value >= 0)
HDONE_ERROR(H5E_IO, H5E_CANTCLOSEFILE, FAIL, "unable to close file")
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5Fis_hdf5() */
/*-------------------------------------------------------------------------
@@ -844,17 +880,20 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf)
} /* end if */
else {
unsigned super_vers = HDF5_SUPERBLOCK_VERSION_DEF; /* Superblock version for file */
- H5P_genplist_t *plist; /* Property list */
+ H5P_genplist_t *plist; /* Property list */
+ size_t u; /* Local index variable */
HDassert(lf != NULL);
if(NULL == (f->shared = H5FL_CALLOC(H5F_file_t)))
HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, NULL, "can't allocate shared file structure")
- f->shared->super_addr = HADDR_UNDEF;
f->shared->base_addr = HADDR_UNDEF;
f->shared->extension_addr = HADDR_UNDEF;
f->shared->sohm_addr = HADDR_UNDEF;
f->shared->sohm_vers = HDF5_SHAREDHEADER_VERSION;
+ for(u = 0; u < NELMTS(f->shared->fs_addr); u++)
+ f->shared->fs_addr[u] = HADDR_UNDEF;
f->shared->driver_addr = HADDR_UNDEF;
+ f->shared->accum.loc = HADDR_UNDEF;
f->shared->lf = lf;
/*
@@ -862,9 +901,9 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf)
* new file handle. We do this early because some values might need
* to change as the file is being opened.
*/
- if(NULL == (plist = H5I_object(fcpl_id)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(fcpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not property list")
- f->shared->fcpl_id = H5P_copy_plist(plist);
+ f->shared->fcpl_id = H5P_copy_plist(plist, FALSE);
/* Get the FCPL values to cache */
if(H5P_get(plist, H5F_CRT_ADDR_BYTE_NUM_NAME, &f->shared->sizeof_addr) < 0)
@@ -880,14 +919,14 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf)
HDassert(f->shared->sohm_nindexes < 255);
/* Get the FAPL values to cache */
- if(NULL == (plist = H5I_object(fapl_id)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not file access property list")
if(H5P_get(plist, H5F_ACS_META_CACHE_INIT_CONFIG_NAME, &(f->shared->mdc_initCacheCfg)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get initial meta data cache resize config")
- if(H5P_get(plist, H5F_ACS_DATA_CACHE_ELMT_SIZE_NAME, &(f->shared->rdcc_nelmts)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get data cache element size")
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get initial metadata cache resize config")
+ if(H5P_get(plist, H5F_ACS_DATA_CACHE_NUM_SLOTS_NAME, &(f->shared->rdcc_nslots)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get data cache number of slots")
if(H5P_get(plist, H5F_ACS_DATA_CACHE_BYTE_SIZE_NAME, &(f->shared->rdcc_nbytes)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get data cache cache size")
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get data cache byte size")
if(H5P_get(plist, H5F_ACS_PREEMPT_READ_CHUNKS_NAME, &(f->shared->rdcc_w0)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get preempt read chunk")
if(H5P_get(plist, H5F_ACS_ALIGN_THRHD_NAME, &(f->shared->threshold)) < 0)
@@ -900,6 +939,23 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get sieve buffer size")
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(H5P_get(plist, H5F_ACS_META_BLOCK_SIZE_NAME, &(f->shared->meta_aggr.alloc_size)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get metadata cache size")
+ f->shared->meta_aggr.feature_flag = H5FD_FEAT_AGGREGATE_METADATA;
+ if(H5P_get(plist, H5F_ACS_SDATA_BLOCK_SIZE_NAME, &(f->shared->sdata_aggr.alloc_size)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get 'small data' cache size")
+ f->shared->sdata_aggr.feature_flag = H5FD_FEAT_AGGREGATE_SMALLDATA;
+
+ /* Get the VFD values to cache */
+ f->shared->maxaddr = H5FD_get_maxaddr(lf);
+ if(!H5F_addr_defined(f->shared->maxaddr))
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad maximum address from VFD")
+ if(H5FD_get_feature_flags(lf, &f->shared->feature_flags) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get feature flags from VFD")
+ if(H5FD_get_fs_type_map(lf, f->shared->fs_type_map) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get free space type mapping from VFD")
+ if(H5MF_init_merge_flags(f) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "problem initializing free space merge flags")
/* Bump superblock version if we are to use the latest version of the format */
if(f->shared->latest_format)
@@ -911,26 +967,26 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf)
* and set the version # of the superblock to 1 if it is a non-default
* value.
*/
- else if(f->shared->btree_k[H5B_ISTORE_ID] != HDF5_BTREE_ISTORE_IK_DEF)
+ else if(f->shared->btree_k[H5B_CHUNK_ID] != HDF5_BTREE_CHUNK_IK_DEF)
super_vers = HDF5_SUPERBLOCK_VERSION_1;
/* If a newer superblock 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)))
+ if(NULL == (c_plist = (H5P_genplist_t *)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 */
/*
- * Create a meta data cache with the specified number of elements.
+ * Create a metadata cache with the specified number of elements.
* The cache might be created with a different number of elements and
* the access property list should be updated to reflect that.
*/
if(SUCCEED != H5AC_create(f, &(f->shared->mdc_initCacheCfg)))
- HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create meta data cache")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create metadata cache")
/* Create the file's "open object" information */
if(H5FO_create(f) < 0)
@@ -953,8 +1009,8 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf)
done:
if(!ret_value && f) {
if(!shared)
- H5FL_FREE(H5F_file_t, f->shared);
- H5FL_FREE(H5F_t, f);
+ (void)H5FL_FREE(H5F_file_t, f->shared);
+ (void)H5FL_FREE(H5F_t, f);
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
@@ -974,6 +1030,9 @@ done:
* Programmer: Robb Matzke
* matzke@llnl.gov
* Jul 18 1997
+ * Modifications:
+ * Vailin Choi, April 2, 2008
+ * Free f->extpath
*
*-------------------------------------------------------------------------
*/
@@ -1030,10 +1089,13 @@ H5F_dest(H5F_t *f, hid_t dxpl_id)
if(H5AC_dest(f, dxpl_id))
/* Push error, but keep going*/
HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
+ if(H5F_accum_reset(f) < 0)
+ /* Push error, but keep going*/
+ HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
if(H5FO_dest(f) < 0)
/* Push error, but keep going*/
HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
- f->shared->cwfs = H5MM_xfree(f->shared->cwfs);
+ f->shared->cwfs = (struct H5HG_heap_t **)H5MM_xfree(f->shared->cwfs);
if(H5G_node_close(f) < 0)
/* Push error, but keep going*/
HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
@@ -1042,7 +1104,7 @@ H5F_dest(H5F_t *f, hid_t dxpl_id)
if(H5I_GENPROP_LST != H5I_get_type(f->shared->fcpl_id))
/* Push error, but keep going*/
HDONE_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a property list")
- if(H5I_dec_ref(f->shared->fcpl_id) < 0)
+ if(H5I_dec_ref(f->shared->fcpl_id, FALSE) < 0)
/* Push error, but keep going*/
HDONE_ERROR(H5E_PLIST, H5E_CANTFREE, FAIL, "can't close property list")
@@ -1051,8 +1113,12 @@ H5F_dest(H5F_t *f, hid_t dxpl_id)
/* Push error, but keep going*/
HDONE_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "problems closing file")
+ /* Free mount table */
+ f->shared->mtab.child = (H5F_mount_t *)H5MM_xfree(f->shared->mtab.child);
+ f->shared->mtab.nalloc = 0;
+
/* Destroy shared file struct */
- f->shared = H5FL_FREE(H5F_file_t,f->shared);
+ f->shared = (H5F_file_t *)H5FL_FREE(H5F_file_t, f->shared);
} else if(f->shared->nrefs > 0) {
/*
@@ -1063,13 +1129,12 @@ H5F_dest(H5F_t *f, hid_t dxpl_id)
}
/* Free the non-shared part of the file */
- f->name = H5MM_xfree(f->name);
- f->mtab.child = H5MM_xfree(f->mtab.child);
- f->mtab.nalloc = 0;
+ f->name = (char *)H5MM_xfree(f->name);
+ f->extpath = (char *)H5MM_xfree(f->extpath);
if(H5FO_top_dest(f) < 0)
HDONE_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "problems closing file")
f->shared = NULL;
- H5FL_FREE(H5F_t, f);
+ (void)H5FL_FREE(H5F_t, f);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F_dest() */
@@ -1153,6 +1218,9 @@ H5F_dest(H5F_t *f, hid_t dxpl_id)
* Modified H5F_flush call to take one flag instead of
* multiple Boolean flags.
*
+ * Vailin Choi, 2008-04-02
+ * To formulate path for later searching of target file for external link
+ * via H5_build_extpath().
*-------------------------------------------------------------------------
*/
H5F_t *
@@ -1266,7 +1334,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t d
file->name = H5MM_xstrdup(name);
/* Get the file access property list, for future queries */
- if(NULL == (a_plist = H5I_object(fapl_id)))
+ if(NULL == (a_plist = (H5P_genplist_t *)H5I_object(fapl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not file access property list")
/* This step is for h5repart tool only. If user wants to change file driver from
@@ -1349,6 +1417,10 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t d
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "file close degree doesn't match")
} /* end if */
+ /* formulate the absolute path for later search of target file for external link */
+ if (H5_build_extpath(name, &file->extpath) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to build extpath")
+
/* Success */
ret_value = file;
@@ -1462,7 +1534,7 @@ H5Fcreate(const char *filename, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to create file")
/* Get an atom for the file */
- if((ret_value = H5I_register(H5I_FILE, new_file)) < 0)
+ if((ret_value = H5I_register(H5I_FILE, new_file, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize file")
/* Keep this ID in file object structure */
@@ -1543,7 +1615,7 @@ H5Fopen(const char *filename, unsigned flags, hid_t fapl_id)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to open file")
/* Get an atom for the file */
- if((ret_value = H5I_register(H5I_FILE, new_file)) < 0)
+ if((ret_value = H5I_register(H5I_FILE, new_file, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize file handle")
/* Keep this ID in file object structure */
@@ -1582,45 +1654,57 @@ done:
herr_t
H5Fflush(hid_t object_id, H5F_scope_t scope)
{
- H5F_t *f = NULL;
- H5G_t *grp = NULL;
- H5T_t *type = NULL;
- H5D_t *dset = NULL;
- H5A_t *attr = NULL;
- H5O_loc_t *oloc = NULL;
- herr_t ret_value=SUCCEED; /* Return value */
+ H5F_t *f = NULL; /* File to flush */
+ H5O_loc_t *oloc = NULL; /* Object location for ID */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(H5Fflush, FAIL)
H5TRACE2("e", "iFs", object_id, scope);
switch(H5I_get_type(object_id)) {
case H5I_FILE:
- if(NULL == (f = H5I_object(object_id)))
+ if(NULL == (f = (H5F_t *)H5I_object(object_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier")
break;
case H5I_GROUP:
- if(NULL == (grp = H5I_object(object_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid group identifier")
- oloc = H5G_oloc(grp);
+ {
+ H5G_t *grp;
+
+ if(NULL == (grp = (H5G_t *)H5I_object(object_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid group identifier")
+ oloc = H5G_oloc(grp);
+ }
break;
case H5I_DATATYPE:
- if(NULL == (type = H5I_object(object_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid type identifier")
- oloc = H5T_oloc(type);
+ {
+ H5T_t *type;
+
+ if(NULL == (type = (H5T_t *)H5I_object(object_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid type identifier")
+ oloc = H5T_oloc(type);
+ }
break;
case H5I_DATASET:
- if(NULL == (dset = H5I_object(object_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataset identifier")
- oloc = H5D_oloc(dset);
+ {
+ H5D_t *dset;
+
+ if(NULL == (dset = (H5D_t *)H5I_object(object_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataset identifier")
+ oloc = H5D_oloc(dset);
+ }
break;
case H5I_ATTR:
- if(NULL == (attr = H5I_object(object_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid attribute identifier")
- oloc = H5A_oloc(attr);
+ {
+ H5A_t *attr;
+
+ if(NULL == (attr = (H5A_t *)H5I_object(object_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid attribute identifier")
+ oloc = H5A_oloc(attr);
+ }
break;
default:
@@ -1684,62 +1768,57 @@ H5F_flush(H5F_t *f, hid_t dxpl_id, H5F_scope_t scope, unsigned flags)
/* Flush other files, depending on scope */
if(H5F_SCOPE_GLOBAL == scope) {
- while(f->mtab.parent)
- f = f->mtab.parent;
+ while(f->parent)
+ f = f->parent;
scope = H5F_SCOPE_DOWN;
} /* end while */
if(H5F_SCOPE_DOWN == scope)
- for(i = 0; i < f->mtab.nmounts; i++)
- if(H5F_flush(f->mtab.child[i].file, dxpl_id, scope, flags) < 0)
+ for(i = 0; i < f->shared->mtab.nmounts; i++)
+ if(H5F_flush(f->shared->mtab.child[i].file, dxpl_id, scope, flags) < 0)
nerrors++;
/* Flush any cached dataset storage raw data */
if(H5D_flush(f, dxpl_id, flags) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush dataset cache")
- /* flush (and invalidate, if requested) the entire meta data cache */
- H5AC_flags = 0;
- if((flags & H5F_FLUSH_INVALIDATE) != 0 )
- H5AC_flags |= H5AC__FLUSH_INVALIDATE_FLAG;
- if(H5AC_flush(f, dxpl_id, H5AC_flags) < 0)
- HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush meta data cache")
-
- /*
- * If we are invalidating everything (which only happens just before
- * the file closes), release the unused portion of the metadata and
- * "small data" blocks back to the free lists in the file.
+ /* If we will be closing the file, we should release the free space
+ * information now (needs to happen before truncating the file and
+ * before the metadata cache is shut down, since the free space manager is
+ * holding some data structures in memory and also because releasing free
+ * space can shrink the file's 'eoa' value)
*/
- if(flags & H5F_FLUSH_INVALIDATE) {
- if(f->shared->lf->feature_flags & H5FD_FEAT_AGGREGATE_METADATA) {
- /* Return the unused portion of the metadata block to a free list */
- if(f->shared->lf->eoma != 0)
- if(H5FD_free(f->shared->lf, H5FD_MEM_DEFAULT, dxpl_id,
- f->shared->lf->eoma, f->shared->lf->cur_meta_block_size) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "can't free metadata block")
-
- /* Reset metadata block information, just in case */
- f->shared->lf->eoma = 0;
- f->shared->lf->cur_meta_block_size = 0;
- } /* end if */
-
- if(f->shared->lf->feature_flags & H5FD_FEAT_AGGREGATE_SMALLDATA) {
- /* Return the unused portion of the "small data" block to a free list */
- if(f->shared->lf->eosda != 0)
- if(H5FD_free(f->shared->lf, H5FD_MEM_DRAW, dxpl_id,
- f->shared->lf->eosda, f->shared->lf->cur_sdata_block_size) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "can't free 'small data' block")
-
- /* Reset "small data" block information, just in case */
- f->shared->lf->eosda = 0;
- f->shared->lf->cur_sdata_block_size = 0;
- } /* end if */
+ if(flags & H5F_FLUSH_CLOSING) {
+ /* Shutdown file free space manager(s) */
+ if(H5MF_close(f, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release file free space info")
} /* end if */
+ /* Truncate the file to the current allocated size */
+ /* (needs to happen before superblock write, since the 'eoa' value is
+ * written in superblock -QAK)
+ */
+ if(H5FD_truncate(f->shared->lf, dxpl_id, (unsigned)((flags & H5F_FLUSH_CLOSING) > 0)) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "low level truncate failed")
+
/* Write the superblock to disk */
- if(H5F_super_write(f, dxpl_id) != SUCCEED)
+ /* (needs to happen before metadata flush (H5AC_flush), since the information
+ * in the superblock extension may be updated - 2008/10/14, QAK)
+ */
+ if(H5F_super_write(f, dxpl_id) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_WRITEERROR, FAIL, "unable to write superblock to file")
+ /* Flush (and invalidate, if requested) the entire metadata cache */
+ H5AC_flags = 0;
+ if((flags & H5F_FLUSH_INVALIDATE) != 0 )
+ H5AC_flags |= H5AC__FLUSH_INVALIDATE_FLAG;
+ if(H5AC_flush(f, dxpl_id, H5AC_flags) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush metadata cache")
+
+ /* Flush out the metadata accumulator */
+ if(H5F_accum_flush(f, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "unable to flush metadata accumulator")
+
/* Flush file buffers to disk. */
if(H5FD_flush(f->shared->lf, dxpl_id, (unsigned)((flags & H5F_FLUSH_CLOSING) > 0)) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "low level flush failed")
@@ -1915,10 +1994,10 @@ H5F_try_close(H5F_t *f)
unsigned u; /* Local index variable */
/* Get the list of IDs of open dataset, group, & attribute objects */
- while((obj_count = H5F_get_obj_ids(f, H5F_OBJ_LOCAL|H5F_OBJ_DATASET|H5F_OBJ_GROUP|H5F_OBJ_ATTR, (int)(sizeof(objs)/sizeof(objs[0])), objs)) != 0) {
+ while((obj_count = H5F_get_obj_ids(f, H5F_OBJ_LOCAL|H5F_OBJ_DATASET|H5F_OBJ_GROUP|H5F_OBJ_ATTR, (int)(sizeof(objs)/sizeof(objs[0])), objs, FALSE)) != 0) {
/* Try to close all the open objects in this file */
for(u = 0; u < obj_count; u++)
- if(H5I_dec_ref(objs[u]) < 0)
+ if(H5I_dec_ref(objs[u], FALSE) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object")
} /* end while */
@@ -1927,10 +2006,10 @@ H5F_try_close(H5F_t *f)
* they could be using one of the named datatypes and then the
* open named datatype ID will get closed twice)
*/
- while((obj_count = H5F_get_obj_ids(f, H5F_OBJ_LOCAL|H5F_OBJ_DATATYPE, (int)(sizeof(objs)/sizeof(objs[0])), objs)) != 0) {
+ while((obj_count = H5F_get_obj_ids(f, H5F_OBJ_LOCAL|H5F_OBJ_DATATYPE, (int)(sizeof(objs)/sizeof(objs[0])), objs, FALSE)) != 0) {
/* Try to close all the open objects in this file */
for(u = 0; u < obj_count; u++)
- if(H5I_dec_ref(objs[u]) < 0)
+ if(H5I_dec_ref(objs[u], FALSE) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object")
} /* end while */
} /* end if */
@@ -1939,8 +2018,8 @@ H5F_try_close(H5F_t *f)
/* Check if this is a child file in a mounting hierarchy & proceed up the
* hierarchy if so.
*/
- if(f->mtab.parent)
- if(H5F_try_close(f->mtab.parent) < 0)
+ if(f->parent)
+ if(H5F_try_close(f->parent) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close parent file")
/* Unmount and close each child before closing the current file. */
@@ -1955,7 +2034,7 @@ H5F_try_close(H5F_t *f)
*/
if(f->intent&H5F_ACC_RDWR) {
/* Flush and destroy all caches */
- if(H5F_flush(f, H5AC_dxpl_id, H5F_SCOPE_LOCAL, H5C__NO_FLAGS_SET) < 0)
+ if(H5F_flush(f, H5AC_dxpl_id, H5F_SCOPE_LOCAL, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache")
} /* end if */
@@ -2009,7 +2088,7 @@ H5Fclose(hid_t file_id)
* Decrement reference count on atom. When it reaches zero the file will
* be closed.
*/
- if(H5I_dec_ref(file_id) < 0)
+ if(H5I_dec_ref(file_id, TRUE) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTCLOSEFILE, FAIL, "decrementing file ID failed")
done:
@@ -2050,7 +2129,7 @@ H5Freopen(hid_t file_id)
H5TRACE1("i", "i", file_id);
/* Check arguments */
- if(NULL == (old_file = H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (old_file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
/* Get a new "top level" file struct, sharing the same "low level" file struct */
@@ -2063,7 +2142,7 @@ H5Freopen(hid_t file_id)
/* Duplicate old file's name */
new_file->name = H5MM_xstrdup(old_file->name);
- if((ret_value = H5I_register(H5I_FILE, new_file)) < 0)
+ if((ret_value = H5I_register(H5I_FILE, new_file, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize file handle")
/* Keep this ID in file object structure */
@@ -2089,385 +2168,37 @@ done:
* Programmer: James Laird
* August 23, 2006
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
herr_t
H5Fget_intent(hid_t file_id, unsigned *intent_flags)
{
- H5F_t * file = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_API(H5Fget_intent, FAIL)
H5TRACE2("e", "i*Iu", file_id, intent_flags);
- if(NULL == (file = H5I_object_verify(file_id, H5I_FILE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
-
/* If no intent flags were passed in, exit quietly */
- if(!intent_flags)
- HGOTO_DONE(SUCCEED)
-
- *intent_flags = H5F_get_intent(file);
-
- /* HDF5 uses some flags internally that users don't know about.
- * Simplify things for them so that they get one of H5F_ACC_RDWR
- * or H5F_ACC_RDONLY.
- */
- if(*intent_flags & H5F_ACC_RDWR)
- *intent_flags = H5F_ACC_RDWR;
- else
- *intent_flags = H5F_ACC_RDONLY;
+ if(intent_flags) {
+ H5F_t * file; /* Pointer to file structure */
-done:
- FUNC_LEAVE_API(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_get_intent
- *
- * Purpose: Quick and dirty routine to retrieve the file's 'intent' flags
- * (Mainly added to stop non-file routines from poking about in the
- * H5F_t data structure)
- *
- * Return: 'intent' on success/abort on failure (shouldn't fail)
- *
- * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
- * September 29, 2000
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-unsigned
-H5F_get_intent(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_intent)
-
- HDassert(f);
-
- FUNC_LEAVE_NOAPI(f->intent)
-} /* end H5F_get_intent() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_sizeof_addr
- *
- * Purpose: Quick and dirty routine to retrieve the size of the file's size_t
- * (Mainly added to stop non-file routines from poking about in the
- * H5F_t data structure)
- *
- * Return: 'sizeof_addr' on success/abort on failure (shouldn't fail)
- *
- * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
- * September 29, 2000
- *
- * Modifications:
- *
- * Raymond Lu, Oct 14, 2001
- * Changed to generic property list.
- *
- *-------------------------------------------------------------------------
- */
-size_t
-H5F_sizeof_addr(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sizeof_addr)
-
- assert(f);
- assert(f->shared);
-
- FUNC_LEAVE_NOAPI(f->shared->sizeof_addr)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_sizeof_size
- *
- * Purpose: Quick and dirty routine to retrieve the size of the file's off_t
- * (Mainly added to stop non-file routines from poking about in the
- * H5F_t data structure)
- *
- * Return: 'sizeof_size' on success/abort on failure (shouldn't fail)
- *
- * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
- * September 29, 2000
- *
- *-------------------------------------------------------------------------
- */
-size_t
-H5F_sizeof_size(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sizeof_size)
-
- assert(f);
- assert(f->shared);
-
- FUNC_LEAVE_NOAPI(f->shared->sizeof_size)
-} /* H5F_sizeof_size() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_sym_leaf_k
- *
- * Purpose: Replaced a macro to retrieve the symbol table leaf size,
- * now that the generic properties are being used to store
- * the values.
- *
- * Return: Success: Non-negative, and the symbol table leaf size is
- * returned.
- *
- * Failure: Negative (should not happen)
- *
- * Programmer: Raymond Lu
- * slu@ncsa.uiuc.edu
- * Oct 14 2001
- *
- *-------------------------------------------------------------------------
- */
-unsigned
-H5F_sym_leaf_k(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sym_leaf_k)
-
- assert(f);
- assert(f->shared);
-
- FUNC_LEAVE_NOAPI(f->shared->sym_leaf_k)
-} /* end H5F_sym_leaf_k() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_Kvalue
- *
- * Purpose: Replaced a macro to retrieve a B-tree key value for a certain
- * type, now that the generic properties are being used to store
- * the B-tree values.
- *
- * Return: Success: Non-negative, and the B-tree key value is
- * returned.
- *
- * Failure: Negative (should not happen)
- *
- * Programmer: Raymond Lu
- * slu@ncsa.uiuc.edu
- * Oct 14 2001
- *
- *-------------------------------------------------------------------------
- */
-unsigned
-H5F_Kvalue(const H5F_t *f, const H5B_class_t *type)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_Kvalue)
-
- assert(f);
- assert(f->shared);
- assert(type);
-
- FUNC_LEAVE_NOAPI(f->shared->btree_k[type->id])
-} /* end H5F_Kvalue() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_rdcc_nelmts
- *
- * Purpose: Replaced a macro to retrieve the raw data cache number of elments,
- * now that the generic properties are being used to store
- * the values.
- *
- * Return: Success: Non-negative, and the raw data cache number of
- * of elemnts is returned.
- *
- * Failure: Negative (should not happen)
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Jun 1 2004
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-size_t
-H5F_rdcc_nelmts(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_rdcc_nelmts)
-
- assert(f);
- assert(f->shared);
-
- FUNC_LEAVE_NOAPI(f->shared->rdcc_nelmts)
-} /* end H5F_rdcc_nelmts() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_rdcc_nbytes
- *
- * Purpose: Replaced a macro to retrieve the raw data cache number of bytes,
- * now that the generic properties are being used to store
- * the values.
- *
- * Return: Success: Non-negative, and the raw data cache number of
- * of bytes is returned.
- *
- * Failure: Negative (should not happen)
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Jun 1 2004
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-size_t
-H5F_rdcc_nbytes(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_rdcc_nbytes)
-
- assert(f);
- assert(f->shared);
-
- FUNC_LEAVE_NOAPI(f->shared->rdcc_nbytes)
-} /* end H5F_rdcc_nbytes() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_rdcc_w0
- *
- * Purpose: Replaced a macro to retrieve the raw data cache 'w0' value
- * now that the generic properties are being used to store
- * the values.
- *
- * Return: Success: Non-negative, and the raw data cache 'w0' value
- * is returned.
- *
- * Failure: Negative (should not happen)
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Jun 2 2004
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-double
-H5F_rdcc_w0(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_rdcc_w0)
-
- assert(f);
- assert(f->shared);
-
- FUNC_LEAVE_NOAPI(f->shared->rdcc_w0)
-} /* end H5F_rdcc_w0() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_has_feature
- *
- * Purpose: Check if a file has a particular feature enabled
- *
- * Return: Success: Non-negative - TRUE or FALSE
- * Failure: Negative (should not happen)
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * May 31 2004
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-hbool_t
-H5F_has_feature(const H5F_t *f, unsigned feature)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_has_feature)
-
- assert(f);
- assert(f->shared);
-
- FUNC_LEAVE_NOAPI((hbool_t)(f->shared->lf->feature_flags&feature))
-} /* end H5F_has_feature() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_get_driver_id
- *
- * Purpose: Quick and dirty routine to retrieve the file's 'driver_id' value
- * (Mainly added to stop non-file routines from poking about in the
- * H5F_t data structure)
- *
- * Return: 'driver_id' on success/abort on failure (shouldn't fail)
- *
- * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
- * October 10, 2000
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-hid_t
-H5F_get_driver_id(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_driver_id)
-
- assert(f);
- assert(f->shared);
- assert(f->shared->lf);
-
- FUNC_LEAVE_NOAPI(f->shared->lf->driver_id)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_get_fileno
- *
- * Purpose: Quick and dirty routine to retrieve the file's 'fileno' value
- * (Mainly added to stop non-file routines from poking about in the
- * H5F_t data structure)
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
- * March 27, 2002
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5F_get_fileno(const H5F_t *f, unsigned long *filenum)
-{
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI(H5F_get_fileno, FAIL)
-
- assert(f);
- assert(f->shared);
- assert(f->shared->lf);
- assert(filenum);
+ /* Get the internal file structure */
+ if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
- /* Retrieve the file's serial number */
- if(H5FD_get_fileno(f->shared->lf,filenum) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, FAIL, "can't retrieve fileno")
+ /* HDF5 uses some flags internally that users don't know about.
+ * Simplify things for them so that they only get either H5F_ACC_RDWR
+ * or H5F_ACC_RDONLY.
+ */
+ if(H5F_INTENT(file) & H5F_ACC_RDWR)
+ *intent_flags = H5F_ACC_RDWR;
+ else
+ *intent_flags = H5F_ACC_RDONLY;
+ } /* end if */
done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_get_fileno() */
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Fget_intent() */
/*-------------------------------------------------------------------------
@@ -2484,7 +2215,7 @@ done:
*-------------------------------------------------------------------------
*/
hid_t
-H5F_get_id(H5F_t *file)
+H5F_get_id(H5F_t *file, hbool_t app_ref)
{
hid_t ret_value;
@@ -2494,11 +2225,11 @@ H5F_get_id(H5F_t *file)
if(file->file_id == -1) {
/* Get an atom for the file */
- if((file->file_id = H5I_register(H5I_FILE, file)) < 0)
+ if((file->file_id = H5I_register(H5I_FILE, file, app_ref)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize file")
} else {
/* Increment reference count on atom. */
- if(H5I_inc_ref(file->file_id) < 0)
+ if(H5I_inc_ref(file->file_id, app_ref) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTSET, FAIL, "incrementing file ID failed")
} /* end else */
@@ -2510,35 +2241,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5F_get_base_addr
- *
- * Purpose: Quick and dirty routine to retrieve the file's 'base_addr' value
- * (Mainly added to stop non-file routines from poking about in the
- * H5F_t data structure)
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Raymond Lu <slu@ncsa.uiuc.edu>
- * December 20, 2002
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-haddr_t
-H5F_get_base_addr(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_base_addr)
-
- assert(f);
- assert(f->shared);
-
- FUNC_LEAVE_NOAPI(f->shared->base_addr)
-} /* end H5F_get_base_addr() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5F_get_eoa
*
* Purpose: Quick and dirty routine to retrieve the file's 'eoa' value
@@ -2548,314 +2250,26 @@ H5F_get_base_addr(const H5F_t *f)
* Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
* June 1, 2004
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
haddr_t
-H5F_get_eoa(const H5F_t *f)
+H5F_get_eoa(const H5F_t *f, H5FD_mem_t type)
{
haddr_t ret_value;
FUNC_ENTER_NOAPI(H5F_get_eoa, HADDR_UNDEF)
- assert(f);
- assert(f->shared);
+ HDassert(f);
+ HDassert(f->shared);
/* Dispatch to driver */
- if (HADDR_UNDEF==(ret_value=H5FD_get_eoa(f->shared->lf, H5FD_MEM_DEFAULT)))
+ if(HADDR_UNDEF == (ret_value = H5FD_get_eoa(f->shared->lf, type)))
HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "driver get_eoa request failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F_get_eoa() */
-#ifdef H5_HAVE_PARALLEL
-
-/*-------------------------------------------------------------------------
- * Function: H5F_mpi_get_rank
- *
- * Purpose: Retrieves the rank of an MPI process.
- *
- * Return: Success: The rank (non-negative)
- *
- * Failure: Negative
- *
- * Programmer: Quincey Koziol
- * Friday, January 30, 2004
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-int
-H5F_mpi_get_rank(const H5F_t *f)
-{
- int ret_value;
-
- FUNC_ENTER_NOAPI(H5F_mpi_get_rank, FAIL)
-
- assert(f && f->shared);
-
- /* Dispatch to driver */
- if ((ret_value=H5FD_mpi_get_rank(f->shared->lf)) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "driver get_rank request failed")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_mpi_get_rank() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_mpi_get_comm
- *
- * Purpose: Retrieves the file's communicator
- *
- * Return: Success: The communicator (non-negative)
- *
- * Failure: Negative
- *
- * Programmer: Quincey Koziol
- * Friday, January 30, 2004
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-MPI_Comm
-H5F_mpi_get_comm(const H5F_t *f)
-{
- MPI_Comm ret_value;
-
- FUNC_ENTER_NOAPI(H5F_mpi_get_comm, MPI_COMM_NULL)
-
- assert(f && f->shared);
-
- /* Dispatch to driver */
- if ((ret_value=H5FD_mpi_get_comm(f->shared->lf))==MPI_COMM_NULL)
- HGOTO_ERROR(H5E_VFL, H5E_CANTGET, MPI_COMM_NULL, "driver get_comm request failed")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_mpi_get_comm() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_mpi_get_size
- *
- * Purpose: Retrieves the size of an MPI process.
- *
- * Return: Success: The size (positive)
- *
- * Failure: Negative
- *
- * Programmer: John Mainzer
- * Friday, May 6, 2005
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-int
-H5F_mpi_get_size(const H5F_t *f)
-{
- int ret_value;
-
- FUNC_ENTER_NOAPI(H5F_mpi_get_size, FAIL)
-
- assert(f && f->shared);
-
- /* Dispatch to driver */
- if ((ret_value=H5FD_mpi_get_size(f->shared->lf)) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "driver get_size request failed")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_mpi_get_size() */
-#endif /* H5_HAVE_PARALLEL */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_grp_btree_shared
- *
- * Purpose: Replaced a macro to retrieve the shared B-tree node info
- * now that the generic properties are being used to store
- * the values.
- *
- * Return: Success: Non-void, and the shared B-tree node info
- * is returned.
- *
- * Failure: void (should not happen)
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Jul 5 2004
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-H5RC_t *
-H5F_grp_btree_shared(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_grp_btree_shared)
-
- assert(f);
- assert(f->shared);
-
- FUNC_LEAVE_NOAPI(f->shared->grp_btree_shared)
-} /* end H5F_grp_btree_shared() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_sieve_buf_size
- *
- * Purpose: Replaced a macro to retrieve the dataset sieve buffer size
- * now that the generic properties are being used to store
- * the values.
- *
- * Return: Success: Non-void, and the dataset sieve buffer size
- * is returned.
- *
- * Failure: void (should not happen)
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Jul 8 2005
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-size_t
-H5F_sieve_buf_size(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sieve_buf_size)
-
- assert(f);
- assert(f->shared);
-
- FUNC_LEAVE_NOAPI(f->shared->sieve_buf_size)
-} /* end H5F_sieve_buf_size() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_gc_ref
- *
- * Purpose: Replaced a macro to retrieve the "garbage collect
- * references flag" now that the generic properties are being used
- * to store the values.
- *
- * Return: Success: The "garbage collect references flag"
- * is returned.
- *
- * Failure: (should not happen)
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Jul 8 2005
- *
- *-------------------------------------------------------------------------
- */
-unsigned
-H5F_gc_ref(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_gc_ref)
-
- HDassert(f);
- HDassert(f->shared);
-
- FUNC_LEAVE_NOAPI(f->shared->gc_ref)
-} /* end H5F_gc_ref() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_get_fcpl
- *
- * Purpose: Retrieve the value of a file's FCPL.
- *
- * Return: Success: The FCPL for the file.
- *
- * Failure: ? (should not happen)
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * May 25 2005
- *
- *-------------------------------------------------------------------------
- */
-hid_t
-H5F_get_fcpl(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_fcpl)
-
- assert(f);
- assert(f->shared);
-
- FUNC_LEAVE_NOAPI(f->shared->fcpl_id)
-} /* end H5F_get_fcpl() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_use_latest_format
- *
- * Purpose: Retrieve the 'use the latest version of the format' flag for
- * the file.
- *
- * Return: Success: Non-negative, the 'use the latest format' flag
- *
- * Failure: (can't happen)
- *
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Oct 2 2006
- *
- *-------------------------------------------------------------------------
- */
-hbool_t
-H5F_use_latest_format(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_use_latest_format)
-
- HDassert(f);
- HDassert(f->shared);
-
- FUNC_LEAVE_NOAPI(f->shared->latest_format)
-} /* end H5F_use_latest_format() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_get_fc_degree
- *
- * Purpose: Retrieve the 'file close degree' for the file.
- *
- * Return: Success: Non-negative, the 'file close degree'
- *
- * Failure: (can't happen)
- *
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Mar 5 2007
- *
- *-------------------------------------------------------------------------
- */
-H5F_close_degree_t
-H5F_get_fc_degree(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_fc_degree)
-
- HDassert(f);
- HDassert(f->shared);
-
- FUNC_LEAVE_NOAPI(f->shared->fc_degree)
-} /* end H5F_get_fc_degree() */
-
/*-------------------------------------------------------------------------
* Function: H5F_incr_nopen_objs
@@ -2912,148 +2326,6 @@ H5F_decr_nopen_objs(H5F_t *f)
/*-------------------------------------------------------------------------
- * Function: H5F_store_msg_crt_idx
- *
- * Purpose: Retrieve the 'store message creation index' flag for the file.
- *
- * Return: Success: Non-negative, the 'store message creation index' flag
- *
- * Failure: (can't happen)
- *
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Mar 6 2007
- *
- *-------------------------------------------------------------------------
- */
-hbool_t
-H5F_store_msg_crt_idx(const H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_store_msg_crt_idx)
-
- HDassert(f);
- HDassert(f->shared);
-
- FUNC_LEAVE_NOAPI(f->shared->store_msg_crt_idx)
-} /* end H5F_store_msg_crt_idx() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_block_read
- *
- * Purpose: Reads some data from a file/server/etc into a buffer.
- * The data is contiguous. The address is relative to the base
- * address for the file.
- *
- * Errors:
- * IO READERROR Low-level read failed.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Jul 10 1997
- *
- * Modifications:
- * Albert Cheng, 1998-06-02
- * Added XFER_MODE argument
- *
- * Robb Matzke, 1999-07-28
- * The ADDR argument is passed by value.
- *
- * Robb Matzke, 1999-08-02
- * Modified to use the virtual file layer. The data transfer
- * property list is passed in by object ID since that's how the
- * virtual file layer needs it.
- *-------------------------------------------------------------------------
- */
-herr_t
-H5F_block_read(const H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size, hid_t dxpl_id,
- void *buf/*out*/)
-{
- haddr_t abs_addr;
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5F_block_read, FAIL)
-
- assert (f);
- assert (f->shared);
- assert(size<SIZET_MAX);
- assert (buf);
-
- /* convert the relative address to an absolute address */
- abs_addr = f->shared->base_addr + addr;
-
- /* Read the data */
- if(H5FD_read(f->shared->lf, type, dxpl_id, abs_addr, size, buf) < 0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file read failed")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_block_write
- *
- * Purpose: Writes some data from memory to a file/server/etc. The
- * data is contiguous. The address is relative to the base
- * address.
- *
- * Errors:
- * IO WRITEERROR Low-level write failed.
- * IO WRITEERROR No write intent.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Jul 10 1997
- *
- * Modifications:
- * Albert Cheng, 1998-06-02
- * Added XFER_MODE argument
- *
- * Robb Matzke, 1999-07-28
- * The ADDR argument is passed by value.
- *
- * Robb Matzke, 1999-08-02
- * Modified to use the virtual file layer. The data transfer
- * property list is passed in by object ID since that's how the
- * virtual file layer needs it.
- *-------------------------------------------------------------------------
- */
-herr_t
-H5F_block_write(const H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
- hid_t dxpl_id, const void *buf)
-{
- haddr_t abs_addr;
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5F_block_write, FAIL)
-
- assert (f);
- assert (f->shared);
- assert (size<SIZET_MAX);
- assert (buf);
-
- if (0==(f->intent & H5F_ACC_RDWR))
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "no write intent")
-
- /* Convert the relative address to an absolute address */
- abs_addr = f->shared->base_addr + addr;
-
- /* Write the data */
- if (H5FD_write(f->shared->lf, type, dxpl_id, abs_addr, size, buf))
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
* Function: H5F_addr_encode
*
* Purpose: Encodes an address into the buffer pointed to by *PP and
@@ -3160,18 +2432,18 @@ H5F_addr_decode(const H5F_t *f, const uint8_t **pp/*in,out*/, haddr_t *addr_p/*o
hssize_t
H5Fget_freespace(hid_t file_id)
{
- H5F_t *file=NULL; /* File object for file ID */
+ H5F_t *file; /* File object for file ID */
hssize_t ret_value; /* Return value */
FUNC_ENTER_API(H5Fget_freespace, FAIL)
H5TRACE1("Hs", "i", file_id);
/* Check args */
- if(NULL == (file = H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
/* Go get the actual amount of free space in the file */
- if((ret_value = H5FD_get_freespace(file->shared->lf)) < 0)
+ if((ret_value = H5MF_get_freespace(file, H5AC_ind_dxpl_id)) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to check free space for file")
done:
@@ -3200,20 +2472,20 @@ done:
herr_t
H5Fget_filesize(hid_t file_id, hsize_t *size)
{
- H5F_t *file=NULL; /* File object for file ID */
- herr_t ret_value = SUCCEED; /* Return value */
- haddr_t eof;
+ H5F_t *file; /* File object for file ID */
+ haddr_t eof; /* End of file address */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(H5Fget_filesize, FAIL)
H5TRACE2("e", "i*h", file_id, size);
/* Check args */
- if(NULL==(file=H5I_object_verify(file_id, H5I_FILE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
+ if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
/* Go get the actual file size */
- if((eof = H5FDget_eof(file->shared->lf))==HADDR_UNDEF)
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get file size")
+ if(HADDR_UNDEF == (eof = H5FDget_eof(file->shared->lf)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get file size")
*size = (hsize_t)eof;
@@ -3250,24 +2522,18 @@ herr_t
H5Fget_mdc_config(hid_t file_id,
H5AC_cache_config_t *config_ptr)
{
- H5F_t *file=NULL; /* File object for file ID */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5F_t *file; /* File object for file ID */
herr_t result;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(H5Fget_mdc_config, FAIL)
H5TRACE2("e", "i*x", file_id, config_ptr);
/* Check args */
- if ( NULL == (file = H5I_object_verify(file_id, H5I_FILE)) ) {
-
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
- }
-
- if ( ( NULL == config_ptr ) ||
- ( config_ptr->version != H5AC__CURR_CACHE_CONFIG_VERSION ) ) {
-
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Bad config_ptr")
- }
+ if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
+ if((NULL == config_ptr) || (config_ptr->version != H5AC__CURR_CACHE_CONFIG_VERSION))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Bad config_ptr")
/* Go get the resize configuration */
result = H5AC_get_cache_auto_resize_config(file->shared->cache, config_ptr);
@@ -3309,18 +2575,16 @@ herr_t
H5Fset_mdc_config(hid_t file_id,
H5AC_cache_config_t *config_ptr)
{
- H5F_t *file=NULL; /* File object for file ID */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5F_t *file; /* File object for file ID */
herr_t result;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(H5Fset_mdc_config, FAIL)
H5TRACE2("e", "i*x", file_id, config_ptr);
/* Check args */
- if ( NULL == (file = H5I_object_verify(file_id, H5I_FILE)) ) {
-
+ if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
- }
/* set the resize configuration */
result = H5AC_set_cache_auto_resize_config(file->shared->cache, config_ptr);
@@ -3363,23 +2627,19 @@ herr_t
H5Fget_mdc_hit_rate(hid_t file_id,
double *hit_rate_ptr)
{
- H5F_t *file=NULL; /* File object for file ID */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5F_t *file; /* File object for file ID */
herr_t result;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(H5Fget_mdc_hit_rate, FAIL)
H5TRACE2("e", "i*d", file_id, hit_rate_ptr);
/* Check args */
- if ( NULL == (file = H5I_object_verify(file_id, H5I_FILE)) ) {
-
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
- }
-
- if ( NULL == hit_rate_ptr ) {
+ if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL hit rate pointer")
- }
+ if(NULL == hit_rate_ptr)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL hit rate pointer")
/* Go get the current hit rate */
result = H5AC_get_cache_hit_rate(file->shared->cache, hit_rate_ptr);
@@ -3426,20 +2686,18 @@ H5Fget_mdc_size(hid_t file_id,
size_t *cur_size_ptr,
int *cur_num_entries_ptr)
{
- H5F_t *file=NULL; /* File object for file ID */
- herr_t ret_value = SUCCEED; /* Return value */
- herr_t result;
+ H5F_t *file; /* File object for file ID */
int32_t cur_num_entries;
+ herr_t result;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(H5Fget_mdc_size, FAIL)
H5TRACE5("e", "i*z*z*z*Is", file_id, max_size_ptr, min_clean_size_ptr,
cur_size_ptr, cur_num_entries_ptr);
/* Check args */
- if ( NULL == (file = H5I_object_verify(file_id, H5I_FILE)) ) {
-
+ if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
- }
/* Go get the size data */
result = H5AC_get_cache_size(file->shared->cache,
@@ -3499,7 +2757,7 @@ H5Freset_mdc_hit_rate_stats(hid_t file_id)
H5TRACE1("e", "i", file_id);
/* Check args */
- if(NULL == (file = H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
/* Reset the hit rate statistic */
@@ -3545,7 +2803,7 @@ H5Fget_name(hid_t obj_id, char *name/*out*/, size_t size)
* the top file in a mount hierarchy)
*/
if(H5I_get_type(obj_id) == H5I_FILE ) {
- if(NULL == (f = H5I_object(obj_id)))
+ if(NULL == (f = (H5F_t *)H5I_object(obj_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
} /* end if */
else {
@@ -3605,7 +2863,7 @@ H5Fget_info(hid_t obj_id, H5F_info_t *finfo)
* the top file in a mount hierarchy)
*/
if(H5I_get_type(obj_id) == H5I_FILE ) {
- if(NULL == (f = H5I_object(obj_id)))
+ if(NULL == (f = (H5F_t *)H5I_object(obj_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
} /* end if */
else {
@@ -3634,4 +2892,3 @@ H5Fget_info(hid_t obj_id, H5F_info_t *finfo)
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Fget_info() */
-
diff --git a/src/H5FD.c b/src/H5FD.c
index c9dbaf0..4c316d1 100644
--- a/src/H5FD.c
+++ b/src/H5FD.c
@@ -24,18 +24,25 @@
* file driver layer.
*/
+/****************/
+/* Module Setup */
+/****************/
+
#define H5F_PACKAGE /*suppress error about including H5Fpkg */
+#define H5FD_PACKAGE /*suppress error about including H5FDpkg */
/* Interface initialization */
#define H5_INTERFACE_INIT_FUNC H5FD_init_interface
-/* Packages needed by this file */
+/***********/
+/* Headers */
+/***********/
#include "H5private.h" /* Generic Functions */
#include "H5Dprivate.h" /* Datasets */
#include "H5Eprivate.h" /* Error handling */
#include "H5Fpkg.h" /* File access */
-#include "H5FDprivate.h" /* File drivers */
+#include "H5FDpkg.h" /* File Drivers */
#include "H5FDcore.h" /* Files stored entirely in memory */
#include "H5FDfamily.h" /* File families */
#include "H5FDlog.h" /* sec2 driver with I/O logging (for debugging) */
@@ -46,43 +53,48 @@
#ifdef H5_HAVE_WINDOWS
#include "H5FDwindows.h" /* Windows buffered I/O */
#endif
-#include "H5FDstream.h" /* In-memory files streamed via sockets */
#include "H5FDdirect.h" /* Direct file I/O */
-#include "H5FLprivate.h" /* Free lists */
#include "H5Iprivate.h" /* IDs */
#include "H5MMprivate.h" /* Memory management */
#include "H5Pprivate.h" /* Property lists */
-/* static prototypes */
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
static herr_t H5FD_pl_copy(void *(*copy_func)(const void *), size_t pl_size,
const void *old_pl, void **copied_pl);
static herr_t H5FD_pl_close(hid_t driver_id, herr_t (*free_func)(void *),
void *pl);
static herr_t H5FD_free_cls(H5FD_class_t *cls);
-static haddr_t H5FD_alloc_from_free_list(H5FD_t *file, H5FD_mem_t type,
- hsize_t size);
-static haddr_t H5FD_alloc_metadata(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id,
- hsize_t size);
-static haddr_t H5FD_alloc_raw(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id,
- hsize_t size);
-static haddr_t H5FD_real_alloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size);
-static herr_t H5FD_free_freelist(H5FD_t *file);
-static haddr_t H5FD_update_eoa(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size);
-/* Declare a free list to manage the H5FD_free_t struct */
-H5FL_DEFINE(H5FD_free_t);
+/*********************/
+/* Package Variables */
+/*********************/
-/* Declare a PQ free list to manage the metadata accumulator buffer */
-H5FL_BLK_DEFINE_STATIC(meta_accum);
-/* Local macro definitions */
-#define H5FD_ACCUM_THROTTLE 8
-#define H5FD_ACCUM_THRESHOLD 2048
+/*****************************/
+/* Library Private Variables */
+/*****************************/
-/* Define this to display information about file allocations */
-/* #define H5FD_ALLOC_DEBUG */
-/* Static local variables */
+/*******************/
+/* Local Variables */
+/*******************/
/*
* Global count of the number of H5FD_t's handed out. This is used as a
@@ -100,6 +112,32 @@ static unsigned long file_serial_no;
/*-------------------------------------------------------------------------
+ * Function: H5FD_init
+ *
+ * Purpose: Initialize the interface from some other package.
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, January 3, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FD_init(void)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5FD_init, FAIL)
+ /* FUNC_ENTER() does all the work */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_init() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5FD_init_interface
*
* Purpose: Initialize the virtual file layer.
@@ -162,14 +200,14 @@ H5FD_term_interface(void)
if(H5_interface_initialize_g) {
if((n=H5I_nmembers(H5I_VFL))!=0) {
- H5I_clear_type(H5I_VFL, FALSE);
+ H5I_clear_type(H5I_VFL, FALSE, FALSE);
/* Reset the VFL drivers, if they've been closed */
if(H5I_nmembers(H5I_VFL)==0) {
H5FD_sec2_term();
-#ifdef H5_HAVE_DIRECT
+#ifdef H5_HAVE_DIRECT
H5FD_direct_term();
-#endif
+#endif
H5FD_log_term();
H5FD_stdio_term();
#ifdef H5_HAVE_WINDOWS
@@ -182,9 +220,6 @@ H5FD_term_interface(void)
H5FD_mpio_term();
H5FD_mpiposix_term();
#endif /* H5_HAVE_PARALLEL */
-#ifdef H5_HAVE_STREAM
- H5FD_stream_term();
-#endif
} /* end if */
} else {
H5I_dec_type_ref(H5I_VFL);
@@ -243,7 +278,7 @@ H5FD_free_cls(H5FD_class_t *cls)
* Monday, July 26, 1999
*
* Modifications:
- * Copied guts of function info H5FD_register
+ * Copied guts of function into H5FD_register
* Quincey Koziol
* Friday, January 30, 2004
*
@@ -274,7 +309,7 @@ H5FDregister(const H5FD_class_t *cls)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid free-list mapping")
/* Create the new class ID */
- if((ret_value=H5FD_register(cls, sizeof(H5FD_class_t))) < 0)
+ if((ret_value=H5FD_register(cls, sizeof(H5FD_class_t), TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register file driver ID")
done:
@@ -310,35 +345,35 @@ done:
*-------------------------------------------------------------------------
*/
hid_t
-H5FD_register(const void *_cls, size_t size)
+H5FD_register(const void *_cls, size_t size, hbool_t app_ref)
{
- hid_t ret_value;
- const H5FD_class_t *cls=(const H5FD_class_t *)_cls;
- H5FD_class_t *saved=NULL;
+ const H5FD_class_t *cls = (const H5FD_class_t *)_cls;
+ H5FD_class_t *saved = NULL;
H5FD_mem_t type;
+ hid_t ret_value;
FUNC_ENTER_NOAPI(H5FD_register, FAIL)
/* Check arguments */
- assert(cls);
- assert(cls->open && cls->close);
- assert(cls->get_eoa && cls->set_eoa);
- assert(cls->get_eof);
- assert(cls->read && cls->write);
- for (type=H5FD_MEM_DEFAULT; type<H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t,type))
- assert(cls->fl_map[type]>=H5FD_MEM_NOLIST && cls->fl_map[type]<H5FD_MEM_NTYPES);
+ HDassert(cls);
+ HDassert(cls->open && cls->close);
+ HDassert(cls->get_eoa && cls->set_eoa);
+ HDassert(cls->get_eof);
+ HDassert(cls->read && cls->write);
+ for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type))
+ HDassert(cls->fl_map[type] >= H5FD_MEM_NOLIST && cls->fl_map[type] < H5FD_MEM_NTYPES);
/* Copy the class structure so the caller can reuse or free it */
- if(NULL==(saved=H5MM_malloc(size)))
+ if(NULL == (saved = (H5FD_class_t *)H5MM_malloc(size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for file driver class struct")
- HDmemcpy(saved,cls,size);
+ HDmemcpy(saved, cls, size);
/* Create the new class ID */
- if((ret_value=H5I_register(H5I_VFL, saved)) < 0)
+ if((ret_value = H5I_register(H5I_VFL, saved, app_ref)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register file driver ID")
done:
- if(ret_value<0)
+ if(ret_value < 0)
if(saved)
H5MM_xfree(saved);
@@ -378,7 +413,7 @@ H5FDunregister(hid_t driver_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file driver")
/* The H5FD_class_t struct will be freed by this function */
- if(H5I_dec_ref(driver_id) < 0)
+ if(H5I_dec_ref(driver_id, TRUE) < 0)
HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "unable to unregister file driver")
done:
@@ -389,7 +424,7 @@ done:
/*-------------------------------------------------------------------------
* Function: H5FD_get_class
*
- * Purpose: Optains a pointer to the driver struct containing all the
+ * Purpose: Obtains a pointer to the driver struct containing all the
* callback pointers, etc. The PLIST_ID argument can be a file
* access property list, a data transfer property list, or a
* file driver identifier.
@@ -414,13 +449,13 @@ H5FD_get_class(hid_t id)
FUNC_ENTER_NOAPI(H5FD_get_class, NULL)
if(H5I_VFL == H5I_get_type(id))
- ret_value = H5I_object(id);
+ ret_value = (H5FD_class_t *)H5I_object(id);
else {
H5P_genplist_t *plist; /* Property list pointer */
hid_t driver_id = -1;
/* Get the plist structure */
- if(NULL == (plist = H5I_object(id)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(id)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, NULL, "can't find object for ID")
if(TRUE == H5P_isa_class(id, H5P_FILE_ACCESS)) {
@@ -629,7 +664,7 @@ H5FD_pl_close(hid_t driver_id, herr_t (*free_func)(void *), void *pl)
H5MM_xfree(pl);
/* Decrement reference count for driver */
- if(H5I_dec_ref(driver_id) < 0)
+ if(H5I_dec_ref(driver_id, FALSE) < 0)
HGOTO_ERROR(H5E_VFL, H5E_CANTDEC, FAIL, "can't decrement reference count for driver")
done:
@@ -705,7 +740,7 @@ H5FD_fapl_open(H5P_genplist_t *plist, hid_t driver_id, const void *driver_info)
FUNC_ENTER_NOAPI(H5FD_fapl_open, FAIL)
/* Increment the reference count on driver and copy driver info */
- if(H5I_inc_ref(driver_id) < 0)
+ if(H5I_inc_ref(driver_id, FALSE) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINC, FAIL, "unable to increment ref count on VFL driver")
if(H5FD_fapl_copy(driver_id, driver_info, &copied_driver_info) < 0)
HGOTO_ERROR (H5E_PLIST, H5E_CANTCOPY, FAIL, "can't copy VFL driver info")
@@ -741,17 +776,17 @@ done:
herr_t
H5FD_fapl_copy(hid_t driver_id, const void *old_fapl, void **copied_fapl)
{
- H5FD_class_t *driver=NULL;
- herr_t ret_value=SUCCEED; /* Return value */
+ H5FD_class_t *driver;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5FD_fapl_copy, FAIL)
/* Check args */
- if(NULL==(driver=H5I_object(driver_id)))
+ if(NULL == (driver = (H5FD_class_t *)H5I_object(driver_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a driver ID")
/* Copy the file access property list */
- if(H5FD_pl_copy(driver->fapl_copy,driver->fapl_size,old_fapl,copied_fapl) < 0)
+ if(H5FD_pl_copy(driver->fapl_copy, driver->fapl_size, old_fapl, copied_fapl) < 0)
HGOTO_ERROR(H5E_VFL, H5E_UNSUPPORTED, FAIL, "can't copy driver file access property list")
done:
@@ -784,7 +819,7 @@ H5FD_fapl_close(hid_t driver_id, void *fapl)
/* Check args */
if(driver_id > 0) {
- if(NULL == (driver = H5I_object(driver_id)))
+ if(NULL == (driver = (H5FD_class_t *)H5I_object(driver_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a driver ID")
/* Close the driver for the property list */
@@ -822,7 +857,7 @@ H5FD_dxpl_open(H5P_genplist_t *plist, hid_t driver_id, const void *driver_info)
FUNC_ENTER_NOAPI(H5FD_dxpl_open, FAIL)
/* Increment the reference count on the driver and copy the driver info */
- if(H5I_inc_ref(driver_id) < 0)
+ if(H5I_inc_ref(driver_id, FALSE) < 0)
HGOTO_ERROR (H5E_DATASET, H5E_CANTINC, FAIL, "can't increment VFL driver ID")
if(H5FD_dxpl_copy(driver_id, driver_info, &copied_driver_info) < 0)
HGOTO_ERROR (H5E_DATASET, H5E_CANTCOPY, FAIL, "can't copy VFL driver")
@@ -858,17 +893,17 @@ done:
herr_t
H5FD_dxpl_copy(hid_t driver_id, const void *old_dxpl, void **copied_dxpl)
{
- H5FD_class_t *driver=NULL;
- herr_t ret_value=SUCCEED; /* Return value */
+ H5FD_class_t *driver;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5FD_dxpl_copy, FAIL)
/* Check args */
- if(NULL==(driver=H5I_object(driver_id)))
+ if(NULL == (driver = (H5FD_class_t *)H5I_object(driver_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a driver ID")
/* Copy the file access property list */
- if(H5FD_pl_copy(driver->dxpl_copy,driver->dxpl_size,old_dxpl,copied_dxpl) < 0)
+ if(H5FD_pl_copy(driver->dxpl_copy, driver->dxpl_size, old_dxpl, copied_dxpl) < 0)
HGOTO_ERROR(H5E_VFL, H5E_UNSUPPORTED, FAIL, "can't copy driver data transfer property list")
done:
@@ -894,18 +929,18 @@ done:
herr_t
H5FD_dxpl_close(hid_t driver_id, void *dxpl)
{
- H5FD_class_t *driver=NULL;
- herr_t ret_value=SUCCEED; /* Return value */
+ H5FD_class_t *driver;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5FD_dxpl_close, FAIL)
/* Check args */
- if(driver_id>0) {
- if(NULL==(driver=H5I_object(driver_id)))
+ if(driver_id > 0) {
+ if(NULL == (driver = (H5FD_class_t *)H5I_object(driver_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a driver ID")
/* Close the driver for the property list */
- if(H5FD_pl_close(driver_id,driver->dxpl_free,dxpl) < 0)
+ if(H5FD_pl_close(driver_id, driver->dxpl_free, dxpl) < 0)
HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver fapl_free request failed")
} /* end if */
@@ -1015,36 +1050,36 @@ done:
H5FD_t *
H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
{
- H5FD_class_t *driver;
- H5FD_t *file=NULL;
- hid_t driver_id = -1;
- hsize_t meta_block_size=0;
- hsize_t sdata_block_size=0;
- H5P_genplist_t *plist; /* Property list pointer */
- H5FD_t *ret_value;
+ H5FD_class_t *driver; /* VFD for file */
+ H5FD_t *file = NULL; /* VFD file struct */
+ hid_t driver_id = -1; /* VFD ID */
+ H5P_genplist_t *plist; /* Property list pointer */
+ H5FD_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5FD_open, NULL)
- /* Get file access property list */
- if(NULL == (plist = H5I_object(fapl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list")
-
- if(0==maxaddr)
+ /* Sanity check */
+ if(0 == maxaddr)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "zero format address range")
+ /* Get file access property list */
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list");
+
+ /* Get the VFD to open the file with */
if(H5P_get(plist, H5F_ACS_FILE_DRV_ID_NAME, &driver_id) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get driver ID")
/* Get driver info */
- if(NULL==(driver=H5I_object(driver_id)))
+ if(NULL == (driver = (H5FD_class_t *)H5I_object(driver_id)))
HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, NULL, "invalid driver ID in file access property list")
- if(NULL==driver->open)
+ if(NULL == driver->open)
HGOTO_ERROR(H5E_VFL, H5E_UNSUPPORTED, NULL, "file driver has no `open' method")
/* Dispatch to file driver */
- if(HADDR_UNDEF==maxaddr)
+ if(HADDR_UNDEF == maxaddr)
maxaddr = driver->maxaddr;
- if(NULL==(file=(driver->open)(name, flags, fapl_id, maxaddr)))
+ if(NULL == (file = (driver->open)(name, flags, fapl_id, maxaddr)))
HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, NULL, "open failed")
/*
@@ -1052,18 +1087,10 @@ H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
* driver ID to prevent it from being freed while this file is open.
*/
file->driver_id = driver_id;
- if(H5I_inc_ref(file->driver_id) < 0)
+ if(H5I_inc_ref(file->driver_id, FALSE) < 0)
HGOTO_ERROR(H5E_VFL, H5E_CANTINC, NULL, "unable to increment ref count on VFL driver")
file->cls = driver;
file->maxaddr = maxaddr;
- HDmemset(file->fl, 0, sizeof(file->fl));
- if(H5P_get(plist, H5F_ACS_META_BLOCK_SIZE_NAME, &(meta_block_size)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get meta data block size")
- file->def_meta_block_size = meta_block_size;
- if(H5P_get(plist, H5F_ACS_SDATA_BLOCK_SIZE_NAME, &(sdata_block_size)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get 'small data' block size")
- file->def_sdata_block_size = sdata_block_size;
- file->accum_loc = HADDR_UNDEF;
if(H5P_get(plist, H5F_ACS_ALIGN_THRHD_NAME, &(file->threshold)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get alignment threshold")
if(H5P_get(plist, H5F_ACS_ALIGN_NAME, &(file->alignment)) < 0)
@@ -1074,19 +1101,23 @@ H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, NULL, "unable to query file driver")
/* Increment the global serial number & assign it to this H5FD_t object */
- if(++file_serial_no==0) {
+ if(++file_serial_no == 0) {
/* (Just error out if we wrap around for now...) */
HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, NULL, "unable to get file serial number")
} /* end if */
- file->fileno=file_serial_no;
+ file->fileno = file_serial_no;
+
+ /* Start with base address set to 0 */
+ /* (This will be changed later, when the superblock is located) */
+ file->base_addr = 0;
/* Set return value */
- ret_value=file;
+ ret_value = file;
done:
/* Can't cleanup 'file' information, since we don't know what type it is */
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_open() */
/*-------------------------------------------------------------------------
@@ -1163,13 +1194,9 @@ H5FD_close(H5FD_t *file)
/* check args */
HDassert(file && file->cls);
- /* Free the freelist */
- if(H5FD_free_freelist(file) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "can't release file space free list")
-
/* Prepare to close file by clearing all public fields */
driver = file->cls;
- if(H5I_dec_ref(file->driver_id) < 0)
+ if(H5I_dec_ref(file->driver_id, FALSE) < 0)
HGOTO_ERROR(H5E_VFL, H5E_CANTDEC, FAIL, "can't close driver ID")
/*
@@ -1186,74 +1213,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5FD_free_freelist
- * Purpose: Split off from H5FD_close(). Free the elements in the
- * free list for this file driver.
- * Return: Success: SUCCEED
- * Failure: Never fails
- * Programmer: Bill Wendling
- * 17. February 2003
- * Modifications:
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5FD_free_freelist(H5FD_t *file)
-{
- H5FD_mem_t i;
-#ifdef H5F_DEBUG
- unsigned nblocks = 0;
- hsize_t nbytes = 0;
-#endif /* H5F_DEBUG */
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_free_freelist)
-
- /* check args */
- HDassert(file && file->cls);
-
- /*
- * Free all free-lists, leaking any memory thus described. Also leaks
- * file space allocated but not used when metadata aggregation is
- * turned on.
- */
- for(i = H5FD_MEM_DEFAULT; i < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, i)) {
- H5FD_free_t *cur, *next;
-
- for( cur = file->fl[i]; cur; cur = next) {
-#ifdef H5F_DEBUG
- ++nblocks;
- nbytes += cur->size;
-#endif /* H5F_DEBUG */
- next = cur->next;
- H5FL_FREE(H5FD_free_t, cur);
- } /* end for */
-
- file->fl[i] = NULL;
- } /* end for */
-
-#ifdef H5F_DEBUG
- if(nblocks && H5DEBUG(F))
- HDfprintf(H5DEBUG(F),
- "H5F: leaked %Hu bytes of file memory in %u blocks\n",
- nbytes, nblocks);
-#endif /* H5F_DEBUG */
-
- /* Check if we need to reset the metadata accumulator information */
- if(file->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) {
- /* Free the buffer */
- if(file->meta_accum)
- file->meta_accum = H5FL_BLK_FREE(meta_accum, file->meta_accum);
-
- /* Reset the buffer sizes & location */
- file->accum_buf_size = file->accum_size = 0;
- file->accum_loc = HADDR_UNDEF;
- file->accum_dirty = 0;
- } /* end if */
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5FD_free_freelist() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5FDcmp
*
* Purpose: Compare the keys of two files using the file driver callback
@@ -1451,6 +1410,8 @@ done:
* Tuesday, July 27, 1999
*
* Modifications:
+ * Vailin Choi, 29th July 2008
+ * Two more parameters were added to H5FD_alloc() for handling alignment
*
*-------------------------------------------------------------------------
*/
@@ -1476,725 +1437,15 @@ H5FDalloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, HADDR_UNDEF, "not a data transfer property list")
/* Do the real work */
- if(HADDR_UNDEF == (ret_value = H5FD_alloc(file, type, dxpl_id, size)))
+ if(HADDR_UNDEF == (ret_value = H5FD_alloc(file, dxpl_id, type, size, NULL, NULL)))
HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "unable to allocate file memory")
-done:
- FUNC_LEAVE_API(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_alloc
- * Purpose: Private version of H5FDalloc().
- * Return: Success: The format address of the new file memory.
- * Failure: The undefined address HADDR_UNDEF
- * Programmer: Robb Matzke
- * Wednesday, August 4, 1999
- * Modifications:
- * Albert Cheng, 2001/05/01
- * Implement the allocation by alignment/threshold.
- *
- * Bill Wendling, 2002/12/02
- * Split apart into subfunctions for each separate task.
- *
- * Bill Wendling, 2003/02/19
- * Added support for FPHDF5.
- *
- * John Mainzer, 2004/04/13
- * Moved much of the FPHDF5 specific code into H5FP_client_alloc(),
- * and re-worked it to get rid of a race condition on the eoa.
- *
- *-------------------------------------------------------------------------
- */
-haddr_t
-H5FD_alloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size)
-{
- haddr_t ret_value = HADDR_UNDEF;
-
- FUNC_ENTER_NOAPI(H5FD_alloc, HADDR_UNDEF)
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size);
-#endif /* H5FD_ALLOC_DEBUG */
-
- /* check args */
- assert(file);
- assert(file->cls);
- assert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES);
- assert(size > 0);
-
-#ifdef H5F_DEBUG
- if(H5DEBUG(F))
- HDfprintf(H5DEBUG(F), "%s: alignment=%Hd, threshold=%Hd, size=%Hd\n",
- FUNC, file->alignment, file->threshold, size);
-#endif /* H5F_DEBUG */
-
- /* Try to allocate from the free list first */
- if((ret_value = H5FD_alloc_from_free_list(file, type, size)) != HADDR_UNDEF)
- HGOTO_DONE(ret_value)
-
-#ifdef H5F_DEBUG
- if(H5DEBUG(F))
- HDfprintf(H5DEBUG(F), "%s: Could not allocate from freelists\n", FUNC);
-#endif /* H5F_DEBUG */
-
- if(type != H5FD_MEM_DRAW) {
- /* Handle metadata differently from "raw" data */
- if((ret_value = H5FD_alloc_metadata(file, type, dxpl_id, size)) == HADDR_UNDEF)
- HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate for metadata")
- } else {
- /* Allocate "raw" data */
- if((ret_value = H5FD_alloc_raw(file, type, dxpl_id, size)) == HADDR_UNDEF)
- HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate for raw data")
- }
-
-done:
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: ret_value = %a\n", FUNC, ret_value);
-#endif /* H5FD_ALLOC_DEBUG */
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_alloc() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_alloc_from_free_list
- * Purpose: Try to allocate SIZE bytes of memory from the free list
- * if possible.
- *
- * This is split from H5FD_alloc().
- * Return: Success: The format address of the new file memory.
- * Failure: The undefined address HADDR_UNDEF
- * Programmer: Bill Wendling
- * 02. December, 2002
- * Modifications:
- *-------------------------------------------------------------------------
- */
-static haddr_t
-H5FD_alloc_from_free_list(H5FD_t *file, H5FD_mem_t type, hsize_t size)
-{
- H5FD_mem_t mapped_type;
- haddr_t ret_value = HADDR_UNDEF;
-
- FUNC_ENTER_NOAPI(H5FD_alloc_from_free_list, HADDR_UNDEF)
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size);
-#endif /* H5FD_ALLOC_DEBUG */
-
- assert(file);
- assert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES);
- assert(size > 0);
-
- /* Map the allocation request to a free list */
- if(H5FD_MEM_DEFAULT == file->cls->fl_map[type])
- mapped_type = type;
- else
- mapped_type = file->cls->fl_map[type];
-
- /*
- * Try to satisfy the request from the free list. Only perform the
- * search if the free list has the potential of satisfying the
- * request.
- *
- * Here, aligned requests are requests that are >= threshold and
- * alignment > 1.
- *
- * For non-aligned request, first try to find an exact match,
- * otherwise use the best match which is the smallest size that meets
- * the requested size.
- *
- * For aligned address request, find a block in the following order
- * of preferences:
- *
- * 1. block address is aligned and exact match in size;
- * 2. block address is aligned with smallest size > requested size;
- * 3. block address is not aligned with smallest size >= requested size.
- */
- if(mapped_type >= H5FD_MEM_DEFAULT && (file->maxsize == 0 || size <= file->maxsize)) {
- H5FD_free_t *prev = NULL, *best = NULL;
- H5FD_free_t *cur = file->fl[mapped_type];
- hbool_t found_aligned = FALSE;
- hbool_t need_aligned;
- hsize_t head;
-
- need_aligned = file->alignment > 1 && size >= file->threshold;
-
- while(cur) {
- if(cur->size > file->maxsize)
- file->maxsize = cur->size;
-
- if(need_aligned) {
- if((head = cur->addr % file->alignment) == 0) {
- /*
- * Aligned address
- */
- if(cur->size >= size) {
- if(cur->size == size) {
- /* exact match */
- ret_value = cur->addr;
-
- /*
- * Make certain we don't hand out a block of raw data
- * from the free list which overlaps with the metadata
- * aggregation buffer (if it's turned on)
- */
- if(type == H5FD_MEM_DRAW &&
- (file->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) &&
- H5F_addr_overlap(ret_value, size,
- file->accum_loc, file->accum_size)) {
- ret_value = HADDR_UNDEF;
- } else {
- if(prev)
- prev->next = cur->next;
- else
- file->fl[mapped_type] = cur->next;
-
- H5FL_FREE(H5FD_free_t, cur);
-
- if(size == file->maxsize)
- file->maxsize = 0; /*unknown*/
-
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: Exact size match (aligned)\n", FUNC);
-#endif /* H5FD_ALLOC_DEBUG */
- HGOTO_DONE(ret_value)
- }
- }
- else
- /* Favor smallest block, that's closest to the beginning of the file */
- if(!best || !found_aligned || cur->size < best->size ||
- (cur->size == best->size && H5F_addr_lt(cur->addr, best->addr))) {
- best = cur;
- found_aligned = TRUE;
- }
- } /* end if */
- } else {
- /*
- * Non-aligned address
- *
- * Check to see if this block is big enough to skip
- * to the next aligned address and is still big
- * enough for the requested size. The extra
- * (cur->size > head) is for preventing unsigned
- * underflow. (This could be improved by checking for
- * an exact match after excluding the head. Such
- * match is as good as the found_aligned case above.)
- */
- head = file->alignment - head; /* actual head size */
-
- if(!found_aligned && cur->size > head && cur->size-head >= size) {
- /* Favor smallest block, that's closest to the beginning of the file */
- if(!best || cur->size < best->size ||
- (cur->size == best->size && H5F_addr_lt(cur->addr, best->addr)))
- best = cur;
- } /* end if */
- } /* end else */
- } else {
- /* !need_aligned */
- if(cur->size >= size) {
- if(cur->size == size) {
- /* exact match */
- ret_value = cur->addr;
-
- /*
- * Make certain we don't hand out a block of raw data
- * from the free list which overlaps with the metadata
- * aggregation buffer (if it's turned on)
- */
- if(type == H5FD_MEM_DRAW &&
- (file->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) &&
- H5F_addr_overlap(ret_value, size, file->accum_loc,
- file->accum_size)) {
- ret_value = HADDR_UNDEF;
- } else {
- if(prev)
- prev->next = cur->next;
- else
- file->fl[mapped_type] = cur->next;
-
- H5FL_FREE(H5FD_free_t, cur);
-
- if(size == file->maxsize)
- file->maxsize = 0; /*unknown*/
-
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: Exact size match (unaligned)\n", FUNC);
-#endif /* H5FD_ALLOC_DEBUG */
- HGOTO_DONE(ret_value)
- }
- } /* end if */
- else {
- /* Favor smallest block, that's closest to the beginning of the file */
- if(!best || cur->size < best->size ||
- (cur->size == best->size && H5F_addr_lt(cur->addr, best->addr)))
- best = cur;
- } /* end else */
- } /* end if */
- } /* end else */
-
- prev = cur;
- cur = cur->next;
- } /* end while */
-
- /* Couldn't find exact match, use best fitting piece found */
- if(best) {
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: Splitting %Hu byte sized block\n", FUNC, best->size);
-#endif /* H5FD_ALLOC_DEBUG */
- if(best->size == file->maxsize)
- file->maxsize = 0; /*unknown*/
-
- if(!need_aligned || found_aligned) {
- /* free only tail */
- ret_value = best->addr;
-
- /*
- * Make certain we don't hand out a block of raw data
- * from the free list which overlaps with the metadata
- * aggregation buffer (if it's turned on)
- */
- if(type == H5FD_MEM_DRAW &&
- (file->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) &&
- H5F_addr_overlap(ret_value, size, file->accum_loc,
- file->accum_size)) {
- ret_value = HADDR_UNDEF;
- } else {
- best->addr += size; /* Reduce size of block on free list */
- best->size -= size;
- HGOTO_DONE(ret_value)
- }
- } else {
- /*
- * Split into 3 pieces. Keep the the head and tail in the
- * freelist.
- */
- H5FD_free_t *tmp = NULL;
-
- head = file->alignment - (best->addr % file->alignment);
- ret_value = best->addr + head;
-
- /*
- * Make certain we don't hand out a block of raw data
- * from the free list which overlaps with the metadata
- * aggregation buffer (if it's turned on)
- */
- if(type == H5FD_MEM_DRAW &&
- (file->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) &&
- H5F_addr_overlap(ret_value, size, file->accum_loc, file->accum_size)) {
- ret_value = HADDR_UNDEF;
- } else {
- /* Attempt to allocate memory for temporary node */
- if((tmp = H5FL_MALLOC(H5FD_free_t))==NULL)
- HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "free block allocation failed")
-
- if((tmp->size = (best->size - (head + size)))!=0) {
- tmp->addr = best->addr + (head + size);
- tmp->next = best->next;
- best->next = tmp;
- } else {
- /* no tail piece */
- H5FL_FREE(H5FD_free_t,tmp);
- }
-
- best->size = head;
- HGOTO_DONE(ret_value)
- } /* end else */
- } /* end else */
- } /* end if */
- } /* end if */
-
-done:
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: ret_value = %a\n", FUNC, ret_value);
-#endif /* H5FD_ALLOC_DEBUG */
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_alloc_from_free_list() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_alloc_metadata
- * Purpose: Try to allocate SIZE bytes of memory from the metadata
- * block if possible.
- *
- * This is split from H5FD_alloc().
- * Return: Success: The format address of the new file memory.
- * Failure: The undefined address HADDR_UNDEF
- * Programmer: Bill Wendling
- * 2. December, 2002
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static haddr_t
-H5FD_alloc_metadata(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size)
-{
- haddr_t ret_value = HADDR_UNDEF;
-
- FUNC_ENTER_NOAPI(H5FD_alloc_metadata, HADDR_UNDEF)
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size);
-#endif /* H5FD_ALLOC_DEBUG */
-
- /* check args */
- assert(file);
- assert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES);
- assert(size > 0);
-
- /*
- * If the metadata aggregation feature is enabled for this VFL
- * driver, allocate "generic" metadata space and sub-allocate out of
- * that, if possible. Otherwise just allocate through
- * H5FD_real_alloc()
- */
-
- /*
- * Allocate all types of metadata out of the metadata block
- */
- if(file->feature_flags & H5FD_FEAT_AGGREGATE_METADATA) {
- /*
- * Check if the space requested is larger than the space left in
- * the block
- */
- if(size > file->cur_meta_block_size) {
- haddr_t new_meta; /* Address for new metadata */
-
- /*
- * Check if the block asked for is too large for a metadata
- * block
- */
- if(size >= file->def_meta_block_size) {
- /* Allocate more room for this new block the regular way */
- if(HADDR_UNDEF==(new_meta = H5FD_real_alloc(file, type, dxpl_id, size)))
- HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate metadata block")
-
- /*
- * Check if the new metadata is at the end of the current
- * metadata block
- */
- if(file->eoma + file->cur_meta_block_size == new_meta) {
- /*
- * Treat the allocation request as if the current
- * metadata block grew by the amount allocated and
- * just update the eoma address. Don't bother
- * updating the cur_meta_block_size since it will
- * just grow and shrink by the same amount.
- */
- ret_value = file->eoma;
- file->eoma += size;
- } else {
- /* Use the new metadata block for the space allocated */
- ret_value = new_meta;
- }
- } else {
- /* Allocate another metadata block */
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: Allocating 'metadata' block\n", FUNC);
-#endif /* H5FD_ALLOC_DEBUG */
- if(HADDR_UNDEF==(new_meta = H5FD_real_alloc(file, H5FD_MEM_DEFAULT, dxpl_id,
- file->def_meta_block_size)))
- HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate metadata block")
-
- /*
- * Check if the new metadata is at the end of the current
- * metadata block
- */
- if(file->eoma + file->cur_meta_block_size == new_meta) {
- file->cur_meta_block_size += file->def_meta_block_size;
- } else {
- /*
- * Return the unused portion of the metadata block to
- * a free list
- */
- if(file->eoma != 0)
- if(H5FD_free(file, H5FD_MEM_DEFAULT, dxpl_id, file->eoma,
- file->cur_meta_block_size) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free metadata block")
-
- /* Point the metadata block at the newly allocated block */
- file->eoma = new_meta;
- file->cur_meta_block_size = file->def_meta_block_size;
- }
-
- /* Allocate space out of the metadata block */
- ret_value = file->eoma;
- file->cur_meta_block_size -= size;
- file->eoma += size;
- }
- } else {
- /* Allocate space out of the metadata block */
- ret_value = file->eoma;
- file->cur_meta_block_size -= size;
- file->eoma += size;
- }
- } else {
- /* Allocate data the regular way */
- if(HADDR_UNDEF==(ret_value = H5FD_real_alloc(file, type, dxpl_id, size)))
- HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate metadata block")
- }
-
-done:
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: ret_value = %a\n", FUNC, ret_value);
-#endif /* H5FD_ALLOC_DEBUG */
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_alloc_metadata() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_alloc_raw
- * Purpose: Try to allocate SIZE bytes of raw data.
- *
- * This is split from H5FD_alloc().
- * Return: Success: The format address of the new file memory.
- * Failure: The undefined address HADDR_UNDEF
- * Programmer: Bill Wendling
- * 2. December, 2002
- * Modifications:
- *-------------------------------------------------------------------------
- */
-static haddr_t
-H5FD_alloc_raw(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size)
-{
- haddr_t ret_value = HADDR_UNDEF;
-
- FUNC_ENTER_NOAPI(H5FD_alloc_raw, HADDR_UNDEF)
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size);
-#endif /* H5FD_ALLOC_DEBUG */
-
- /* check args */
- assert(file);
- assert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES);
- assert(size > 0);
-
- /*
- * If the "small data" aggregation feature is enabled for this VFL driver,
- * allocate "small data" space and sub-allocate out of that, if
- * possible. Otherwise just allocate through H5FD_real_alloc()
- */
- if(file->feature_flags & H5FD_FEAT_AGGREGATE_SMALLDATA) {
- /*
- * Check if the space requested is larger than the space left in
- * the block
- */
- if(size > file->cur_sdata_block_size) {
- haddr_t new_data; /* Address for new raw data block */
-
- /* Check if the block asked for is too large for the "small data" block */
- if(size >= file->def_sdata_block_size) {
- /* Allocate more room for this new block the regular way */
- if(HADDR_UNDEF==(new_data = H5FD_real_alloc(file, type, dxpl_id, size)))
- HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate raw data block")
-
- /*
- * Check if the new raw data is at the end of the current
- * "small data" block
- */
- if(file->eosda + file->cur_sdata_block_size == new_data) {
- /*
- * Treat the allocation request as if the current
- * "small data" block grew by the amount allocated
- * and just update the eosda address. Don't bother
- * updating the cur_sdata_block_size since it will
- * just grow and shrink by the same amount.
- */
- ret_value = file->eosda;
- file->eosda += size;
- } else {
- /* Use the new "small data" block for the space allocated */
- ret_value = new_data;
- }
- } else {
- /* Allocate another "small data" block */
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: Allocating 'small data' block\n", FUNC);
-#endif /* H5FD_ALLOC_DEBUG */
- if(HADDR_UNDEF==(new_data = H5FD_real_alloc(file, type, dxpl_id,
- file->def_sdata_block_size)))
- HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate raw data block")
-
- /*
- * Check if the new raw data is at the end of the current
- * "small data" block
- */
- if(file->eosda + file->cur_sdata_block_size == new_data) {
- file->cur_sdata_block_size += file->def_sdata_block_size;
- } else {
- /*
- * Return the unused portion of the "small data"
- * block to a free list
- */
- if(file->eosda != 0)
- if(H5FD_free(file, H5FD_MEM_DRAW, dxpl_id, file->eosda,
- file->cur_sdata_block_size) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free 'small data' block")
-
- /*
- * Point the "small data" block at the newly
- * allocated block
- */
- file->eosda = new_data;
- file->cur_sdata_block_size = file->def_sdata_block_size;
- }
-
- /* Allocate space out of the "small data" block */
- ret_value = file->eosda;
- file->cur_sdata_block_size -= size;
- file->eosda += size;
- }
- } else {
- /* Allocate space out of the "small data" block */
- ret_value = file->eosda;
- file->cur_sdata_block_size -= size;
- file->eosda += size;
- }
- } else {
- /* Allocate data the regular way */
- if(HADDR_UNDEF==(ret_value = H5FD_real_alloc(file, type, dxpl_id, size)))
- HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate raw data block")
- }
-
-done:
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: ret_value = %a\n", FUNC, ret_value);
-#endif /* H5FD_ALLOC_DEBUG */
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_alloc_raw() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_real_alloc
- *
- * Purpose: Double private version of H5FDalloc() :-)
- *
- * Return: Success: The format address of the new file memory.
- *
- * Failure: The undefined address HADDR_UNDEF
- *
- * Programmer: Quincey Koziol
- * Friday, August 25, 2000
- *
- * Modifications:
- * Albert Cheng, 2001/05/01
- * Implement the allocation by alignment/threshold.
- *
- *-------------------------------------------------------------------------
- */
-static haddr_t
-H5FD_real_alloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size)
-{
- haddr_t ret_value = HADDR_UNDEF;
-
- FUNC_ENTER_NOAPI_NOINIT(H5FD_real_alloc)
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size);
-#endif /* H5FD_ALLOC_DEBUG */
-
- /* check args */
- assert(file);
- assert(file->cls);
- assert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES);
- assert(size > 0);
-
- /*
- * Dispatch to driver `alloc' callback or extend the end-of-address
- * marker
- */
- if(file->cls->alloc) {
- if((ret_value = (file->cls->alloc)(file, type, dxpl_id, size)) == HADDR_UNDEF)
- HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "driver allocation request failed")
- } else {
- if((ret_value = H5FD_update_eoa(file, type, dxpl_id, size)) == HADDR_UNDEF)
- HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "driver eoa update request failed")
- }
-
-done:
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: ret_value = %a\n", FUNC, ret_value);
-#endif /* H5FD_ALLOC_DEBUG */
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_real_alloc() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_update_eoa
- * Purpose: Update the EOA field of the file's memory.
- *
- * This was split off from the H5FD_real_alloc function to
- * make life easier for all.
- * Return: Success: The format address of the new file memory.
- * Failure: The undefined address HADDR_UNDEF
- * Programmer: Bill Wendling
- * Wednesday, 04. December, 2002
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static haddr_t
-H5FD_update_eoa(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size)
-{
- haddr_t eoa, oldeoa = 0;
- hsize_t wasted;
- haddr_t ret_value = HADDR_UNDEF;
-
- FUNC_ENTER_NOAPI_NOINIT(H5FD_update_eoa)
-
- /* check args */
- assert(file);
- assert(file->cls);
- assert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES);
- assert(size > 0);
-
- eoa = file->cls->get_eoa(file, type);
-
-#ifdef H5F_DEBUG
- if(file->alignment * file->threshold != 1 && H5DEBUG(F))
- HDfprintf(H5DEBUG(F),
- "%s: alignment=%Hd, threshold=%Hd, size=%Hd, Begin eoa=%a\n",
- FUNC, file->alignment, file->threshold, size, eoa);
-#endif /* H5F_DEBUG */
-
- /* Wasted is 0 if not exceeding threshold or eoa happens to be aligned */
- wasted = (size >= file->threshold) ? (eoa % file->alignment) : 0;
- if(wasted) {
- wasted = file->alignment - wasted; /* actual waste */
- oldeoa = eoa; /* save it for later freeing */
-
- /* Advance eoa to the next alignment by allocating the wasted */
- if(H5F_addr_overflow(eoa, size) || (eoa + wasted) > file->maxaddr)
- HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "file allocation request failed")
-
- eoa += wasted;
-
- if(file->cls->set_eoa(file, type, eoa) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "file allocation request failed")
- } /* end if */
-
- /* allocate the aligned memory */
- if(H5F_addr_overflow(eoa, size) || eoa + size > file->maxaddr)
- HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "file allocation request failed")
-
- ret_value = eoa;
- eoa += size;
-
- if(file->cls->set_eoa(file, type, eoa) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "file allocation request failed")
-
- /* Free the wasted memory */
- if(wasted) {
- if(H5FD_free(file, type, dxpl_id, oldeoa, wasted) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "file deallocation request failed")
- } /* end if */
-
-#ifdef H5F_DEBUG
- if(file->alignment * file->threshold != 1 && H5DEBUG(F))
- HDfprintf(H5DEBUG(F),
- "%s: ret_value=%a, wasted=%Hd, Ended eoa=%a\n",
- FUNC, ret_value, wasted, eoa);
-#endif /* H5F_DEBUG */
+ /* (Note compensating for base address subtraction in internal routine) */
+ ret_value += file->base_addr;
done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_update_eoa() */
+ FUNC_LEAVE_API(ret_value)
+} /* end H5FDalloc() */
/*-------------------------------------------------------------------------
@@ -2238,7 +1489,8 @@ H5FDfree(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t siz
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list")
/* Do the real work */
- if(H5FD_free(file, type, dxpl_id, addr, size) < 0)
+ /* (Note compensating for base address addition in internal routine) */
+ if(H5FD_free(file, dxpl_id, type, addr - file->base_addr, size) < 0)
HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "file deallocation request failed")
done:
@@ -2247,676 +1499,17 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5FD_free
- *
- * Purpose: Private version of H5FDfree()
- *
- * Return: Success: Non-negative
- *
- * Failure: Negative
- *
- * Programmer: Robb Matzke
- * Wednesday, August 4, 1999
- *
- * Modifications:
- * Bill Wendling, February 20, 2003
- * Added support for Flexible PHDF5. If the process is the
- * Set-Aside-Process, then we execute this function. Clients
- * don't.
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5FD_free(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t size)
-{
- H5FD_mem_t mapped_type;
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5FD_free, FAIL)
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: type = %u, addr = %a, size = %Hu\n", FUNC, (unsigned)type, addr, size);
-#endif /* H5FD_ALLOC_DEBUG */
-
- /* Check args */
- HDassert(file);
- HDassert(file->cls);
- HDassert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES);
-
- if(!H5F_addr_defined(addr) || addr > file->maxaddr ||
- H5F_addr_overflow(addr, size) || (addr + size) > file->maxaddr)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid region")
-
- /* Allow 0-sized free's to occur without penalty */
- if(0 == size)
- HGOTO_DONE(SUCCEED)
-
- /* Map request type to free list */
- if(H5FD_MEM_DEFAULT==file->cls->fl_map[type])
- mapped_type = type;
- else
- mapped_type = file->cls->fl_map[type];
-
- /*
- * If the request maps to a free list then add memory to the free list
- * without ever telling the driver that it was freed. Otherwise let the
- * driver deallocate the memory.
- */
- if(mapped_type >= H5FD_MEM_DEFAULT) {
- H5FD_free_t *last; /* Last merged node */
- H5FD_free_t *last_prev = NULL;/* Pointer to node before merged node */
- H5FD_free_t *curr; /* Current free block being inspected */
- H5FD_free_t *prev; /* Previous free block being inspected */
-
- /* Adjust the metadata accumulator to remove the freed block, if it overlaps */
- if((file->feature_flags&H5FD_FEAT_ACCUMULATE_METADATA)
- && H5F_addr_overlap(addr, size, file->accum_loc, file->accum_size)) {
- size_t overlap_size; /* Size of overlap with accumulator */
-
- /* Check for overlapping the beginning of the accumulator */
- if(H5F_addr_le(addr, file->accum_loc)) {
- /* Check for completely overlapping the accumulator */
- if(H5F_addr_ge(addr + size, file->accum_loc + file->accum_size)) {
- /* Reset the entire accumulator */
- file->accum_loc=HADDR_UNDEF;
- file->accum_size=FALSE;
- file->accum_dirty=FALSE;
- } /* end if */
- /* Block to free must end within the accumulator */
- else {
- size_t new_accum_size; /* Size of new accumulator buffer */
-
- /* Calculate the size of the overlap with the accumulator, etc. */
- H5_ASSIGN_OVERFLOW(overlap_size,(addr+size)-file->accum_loc,haddr_t,size_t);
- new_accum_size=file->accum_size-overlap_size;
-
- /* Move the accumulator buffer information to eliminate the freed block */
- HDmemmove(file->meta_accum,file->meta_accum+overlap_size,new_accum_size);
-
- /* Adjust the accumulator information */
- file->accum_loc+=overlap_size;
- file->accum_size=new_accum_size;
- } /* end else */
- } /* end if */
- /* Block to free must start within the accumulator */
- else {
- /* Calculate the size of the overlap with the accumulator */
- H5_ASSIGN_OVERFLOW(overlap_size,(file->accum_loc+file->accum_size)-addr,haddr_t,size_t);
-
- /* Block to free is in the middle of the accumulator */
- if(H5F_addr_lt((addr + size), file->accum_loc + file->accum_size)) {
- haddr_t tail_addr;
- size_t tail_size;
-
- /* Calculate the address & size of the tail to write */
- tail_addr=addr+size;
- H5_ASSIGN_OVERFLOW(tail_size,(file->accum_loc+file->accum_size)-tail_addr,haddr_t,size_t);
-
- /* Write out the part of the accumulator after the block to free */
- /* (Use the driver's write call directly - to avoid looping back and writing to metadata accumulator) */
- if((file->cls->write)(file, H5FD_MEM_DEFAULT, dxpl_id, tail_addr, tail_size, file->meta_accum+(tail_addr-file->accum_loc)) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "file write request failed")
- } /* end if */
-
- /* Adjust the accumulator information */
- file->accum_size=file->accum_size-overlap_size;
- } /* end else */
- } /* end if */
-
- /* Scan through the existing blocks for the mapped type to see if we can extend one */
- curr = file->fl[mapped_type];
- last = prev = NULL;
- while(curr != NULL) {
- /* Check if the block to free adjoins the start of the current block */
- if((addr + size) == curr->addr) {
- /* If we previously found & merged a node, eliminate it from the list & free it */
- if(last != NULL) {
- /* Check if there was a previous block in the list */
- if(last_prev != NULL)
- /* Eliminate the merged block from the list */
- last_prev->next = last->next;
- /* No previous block, this must be the head of the list */
- else
- /* Eliminate the merged block from the list */
- file->fl[mapped_type] = last->next;
-
- /* Check for eliminating the block before the 'current' one */
- if(last == prev)
- prev = last_prev;
-
- /* Free the memory for the merged block */
- H5FL_FREE(H5FD_free_t, last);
- } /* end if */
-
- /* Adjust the address and size of the block found */
- curr->addr = addr;
- curr->size += size;
-
- /* Adjust the information about to memory block to include the merged block */
- addr = curr->addr;
- size = curr->size;
-
- /* Update the information about the merged node */
- last = curr;
- last_prev = prev;
- } /* end if */
- else {
- /* Check if the block to free adjoins the end of the current block */
- if((curr->addr + curr->size) == addr) {
- /* If we previously found & merged a node, eliminate it from the list & free it */
- if(last != NULL) {
- /* Check if there was a previous block in the list */
- if(last_prev != NULL)
- /* Eliminate the merged block from the list */
- last_prev->next = last->next;
- /* No previous block, this must be the head of the list */
- else
- /* Eliminate the merged block from the list */
- file->fl[mapped_type] = last->next;
-
- /* Check for eliminating the block before the 'current' one */
- if(last == prev)
- prev = last_prev;
-
- /* Free the memory for the merged block */
- H5FL_FREE(H5FD_free_t, last);
- } /* end if */
-
- /* Adjust the size of the block found */
- curr->size += size;
-
- /* Adjust the information about to memory block to include the merged block */
- addr = curr->addr;
- size = curr->size;
-
- /* Update the information about the merged node */
- last = curr;
- last_prev = prev;
- } /* end if */
- } /* end else */
-
- /* Advance to next node in list */
- prev = curr;
- curr = curr->next;
- } /* end while */
-
- /* Check if we adjusted an existing block */
- if(last != NULL) {
- /* Move the node found to the front, if it wasn't already there */
- if(last_prev != NULL) {
- last_prev->next = last->next;
- last->next = file->fl[mapped_type];
- file->fl[mapped_type] = last;
- } /* end if */
- } /* end if */
- else {
- /* Allocate a new node to hold the free block's information */
- if(NULL == (last = H5FL_MALLOC(H5FD_free_t)))
- HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, FAIL, "can't allocate node for free space info")
-
- last->addr = addr;
- last->size = size;
- last->next = file->fl[mapped_type];
- file->fl[mapped_type] = last;
- } /* end else */
-
- /* Check if we increased the size of the largest block on the list */
- file->maxsize = MAX(file->maxsize, last->size);
-
- /* Check if this free block adjoins the "metadata aggregator" */
- if(file->feature_flags & H5FD_FEAT_AGGREGATE_METADATA && file->eoma != 0) {
- hbool_t adjoins = FALSE; /* Whether the block adjoined the metadata aggregator */
-
- /* Does the new block adjoin the end of the metadata aggregator */
- if((file->eoma + file->cur_meta_block_size) == last->addr) {
- last->addr = file->eoma;
- adjoins = TRUE;
- } /* end if */
- /* Does the new block adjoin the beginning of the metadata aggregator */
- else if((last->addr + last->size) == file->eoma)
- adjoins = TRUE;
-
- /* Reset metadata aggregator information, if adjoined */
- if(adjoins) {
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: Adjoined metadata aggregator\n", FUNC);
-#endif /* H5FD_ALLOC_DEBUG */
- last->size += file->cur_meta_block_size;
- file->eoma = 0;
- file->cur_meta_block_size = 0;
- } /* end if */
- } /* end if */
-
- /* Check if this free block adjoins the "small data aggregator" */
- if(file->feature_flags & H5FD_FEAT_AGGREGATE_SMALLDATA && file->eosda != 0) {
- hbool_t adjoins = FALSE; /* Whether the block adjoined the small-data aggregator */
-
- /* Does the new block adjoin the end of the small-data aggregator */
- if((file->eosda + file->cur_sdata_block_size) == last->addr) {
- last->addr = file->eosda;
- adjoins = TRUE;
- } /* end if */
- /* Does the new block adjoin the beginning of the small-data aggregator */
- else if((last->addr + last->size) == file->eosda)
- adjoins = TRUE;
-
- /* Reset small-data aggregator information, if adjoined */
- if(adjoins) {
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: Adjoined small data aggregator\n", FUNC);
-#endif /* H5FD_ALLOC_DEBUG */
- last->size += file->cur_sdata_block_size;
- file->eosda = 0;
- file->cur_sdata_block_size = 0;
- } /* end if */
- } /* end if */
-
- /* Check if this free block is at the end of file allocated space.
- * Truncate it if this is true. */
- if(file->cls->get_eoa) {
- haddr_t eoa;
-
- eoa = file->cls->get_eoa(file, type);
- if(eoa == (last->addr + last->size)) {
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: Reducing file size to = %a\n", FUNC, last->addr);
-#endif /* H5FD_ALLOC_DEBUG */
- if(file->cls->set_eoa(file, type, last->addr) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "set end of space allocation request failed")
-
- /* Remove this free block from the list */
- file->fl[mapped_type] = last->next;
- if(file->maxsize == last->size)
- file->maxsize = 0; /*unknown*/
- H5FL_FREE(H5FD_free_t, last);
- } /* end if */
- } /* end if */
- } else if(file->cls->free) {
- if((file->cls->free)(file, type, dxpl_id, addr, size) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver free request failed")
- } else {
- /* leak memory */
-#ifdef H5F_DEBUG
-HDfprintf(stderr, "%s: LEAKED MEMORY!!! type = %u, addr = %a, size = %Hu\n", FUNC, (unsigned)type, addr, size);
-#endif /* H5F_DEBUG */
- } /* end else */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_free() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FDrealloc
- *
- * Purpose: Changes the size of an allocated chunk of memory, possibly
- * also changing its location in the file.
- *
- * Return: Success: New address of the block of memory, not
- * necessarily the same as the original address.
- *
- * Failure: HADDR_UNDEF
- *
- * Programmer: Robb Matzke
- * Tuesday, August 3, 1999
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-haddr_t
-H5FDrealloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t old_addr, hsize_t old_size,
- hsize_t new_size)
-{
- haddr_t ret_value = HADDR_UNDEF;
-
- FUNC_ENTER_API(H5FDrealloc, HADDR_UNDEF)
- H5TRACE6("a", "*xMtiahh", file, type, dxpl_id, old_addr, old_size, new_size);
-
- /* Check args */
- if(H5P_DEFAULT == dxpl_id)
- dxpl_id = H5P_DATASET_XFER_DEFAULT;
- else
- if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, HADDR_UNDEF, "not a data transfer property list")
-
- if(HADDR_UNDEF == (ret_value = H5FD_realloc(file, type, dxpl_id, old_addr, old_size, new_size)))
- HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "file reallocation request failed")
-
-done:
- FUNC_LEAVE_API(ret_value)
-} /* end H5FDrealloc() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_realloc
- *
- * Purpose: Private version of H5FDrealloc()
- *
- * Return: Success: New address of the block of memory, not
- * necessarily the same as the original address.
- *
- * Failure: HADDR_UNDEF
- *
- * Programmer: Robb Matzke
- * Wednesday, August 4, 1999
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-haddr_t
-H5FD_realloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t old_addr, hsize_t old_size,
- hsize_t new_size)
-{
- haddr_t new_addr=old_addr;
- uint8_t _buf[8192];
- uint8_t *buf=_buf;
- haddr_t ret_value; /* Return value */
-
- FUNC_ENTER_NOAPI(H5FD_realloc, HADDR_UNDEF)
-
- if(new_size == old_size) {
- /*nothing to do*/
- } else if(0 == old_size) {
- /* allocate memory */
- HDassert(!H5F_addr_defined(old_addr));
- if(HADDR_UNDEF == (new_addr = H5FD_alloc(file, type, dxpl_id, new_size)))
- HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, HADDR_UNDEF, "file allocation failed")
- } else if(0==new_size) {
- /* free memory */
- HDassert(H5F_addr_defined(old_addr));
- if(H5FD_free(file, type, dxpl_id, old_addr, old_size) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "file deallocation request failed")
- new_addr = HADDR_UNDEF;
- } else if(new_size<old_size) {
- /* free the end of the block */
- if(H5FD_free(file, type, dxpl_id, old_addr+old_size, old_size-new_size) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "file deallocation request failed")
- } else {
- /* move memory to new location */
- /* Note! This may fail if sizeof(hsize_t)>sizeof(size_t) and the
- * object on disk is too large to read into a memory buffer all at one
- * time. This chunk of code would have to be re-written using a loop
- * to move pieces of the realloced data through a fixed size buffer, etc.
- * -QAK, 6/20/01
- */
- if(HADDR_UNDEF == (new_addr = H5FD_alloc(file, type, dxpl_id, new_size)))
- HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, HADDR_UNDEF, "file allocation failed")
- H5_CHECK_OVERFLOW(old_size,hsize_t,size_t);
- if(old_size > sizeof(_buf) && NULL == (buf = H5MM_malloc((size_t)old_size))) {
- (void)H5FD_free(file, type, dxpl_id, new_addr, new_size);
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, "memory allocation failed")
- } /* end if */
- if(H5FD_read(file, type, dxpl_id, old_addr, (size_t)old_size, buf) < 0 ||
- H5FD_write(file, type, dxpl_id, new_addr, (size_t)old_size, buf) < 0) {
- (void)H5FD_free(file, type, dxpl_id, new_addr, new_size);
- if(buf != _buf)
- H5MM_xfree(buf);
- HGOTO_ERROR(H5E_FILE, H5E_READERROR, HADDR_UNDEF, "unable to move file block")
- } /* end if */
-
- if(buf != _buf)
- H5MM_xfree(buf);
- if(H5FD_free(file, type, dxpl_id, old_addr, old_size) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "file deallocation request failed")
- } /* end else */
-
- /* Set return value */
- ret_value = new_addr;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_realloc() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_can_extend
- *
- * Purpose: Check if a block in the file can be extended.
- *
- * Return: Success: TRUE(1)/FALSE(0)
- *
- * Failure: FAIL
- *
- * Programmer: Quincey Koziol
- * Friday, June 11, 2004
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-htri_t
-H5FD_can_extend(const H5FD_t *file, H5FD_mem_t type, haddr_t addr, hsize_t size, hsize_t extra_requested)
-{
- haddr_t eoa; /* End of address space in the file */
- htri_t ret_value=FALSE; /* Return value */
-
- FUNC_ENTER_NOAPI(H5FD_can_extend, FAIL)
-
- /* Retrieve the end of the address space */
- if(HADDR_UNDEF==(eoa=H5FD_get_eoa(file, type)))
- HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver get_eoa request failed")
-
- /* Check if the block is exactly at the end of the file */
- if((addr+size)==eoa)
- HGOTO_DONE(TRUE)
- else {
- H5FD_free_t *curr; /* Current free block being inspected */
- H5FD_mem_t mapped_type; /* Memory type, after mapping */
- haddr_t end; /* End of block in file */
-
- /* Map request type to free list */
- if(H5FD_MEM_DEFAULT==file->cls->fl_map[type])
- mapped_type = type;
- else
- mapped_type = file->cls->fl_map[type];
-
- /* Check if block is inside the metadata or small data accumulator */
- if(mapped_type!=H5FD_MEM_DRAW) {
- if(file->feature_flags & H5FD_FEAT_AGGREGATE_METADATA) {
- /* If the metadata block is at the end of the file, and
- * the block to test adjoins the beginning of the metadata
- * block, then it's extendable
- */
- if(file->eoma + file->cur_meta_block_size == eoa &&
- (addr+size)==file->eoma)
- HGOTO_DONE(TRUE)
- } /* end if */
- } /* end if */
- else {
- if(file->feature_flags & H5FD_FEAT_AGGREGATE_SMALLDATA) {
- /* If the small data block is at the end of the file, and
- * the block to test adjoins the beginning of the small data
- * block, then it's extendable
- */
- if(file->eosda + file->cur_sdata_block_size == eoa &&
- (addr+size)==file->eosda)
- HGOTO_DONE(TRUE)
- } /* end if */
- } /* end else */
-
- /* Scan through the existing blocks for the mapped type to see if we can extend one */
- if(mapped_type >= H5FD_MEM_DEFAULT) {
- curr = file->fl[mapped_type];
- end = addr + size;
- while(curr != NULL) {
- if(end == curr->addr) {
- if(extra_requested <= curr->size)
- HGOTO_DONE(TRUE)
- else
- HGOTO_DONE(FALSE)
- } /* end if */
-
- /* Advance to next node in list */
- curr=curr->next;
- } /* end while */
- } /* end if */
- } /* end else */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_can_extend() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_extend
- *
- * Purpose: Extend a block in the file.
- *
- * Return: Success: Non-negative
- *
- * Failure: Negative
- *
- * Programmer: Quincey Koziol
- * Saturday, June 12, 2004
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5FD_extend(H5FD_t *file, H5FD_mem_t type, haddr_t addr, hsize_t size, hsize_t extra_requested)
-{
- haddr_t eoa; /* End of address space in the file */
- haddr_t end; /* End of block in file */
- hbool_t update_eoma=FALSE; /* Whether we need to update the eoma */
- hbool_t update_eosda=FALSE; /* Whether we need to update the eosda */
- hbool_t at_end=FALSE; /* Block is at end of file */
- H5FD_mem_t mapped_type; /* Memory type, after mapping */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5FD_extend, FAIL)
-#ifdef H5FD_ALLOC_DEBUG
-HDfprintf(stderr, "%s: type = %u, addr = %a, size = %Hu, extra_requested = %Hu\n", FUNC, (unsigned)type, addr, size, extra_requested);
-#endif /* H5FD_ALLOC_DEBUG */
-
- /* Retrieve the end of the address space */
- if(HADDR_UNDEF==(eoa=H5FD_get_eoa(file, type)))
- HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver get_eoa request failed")
-
- /* Map request type to free list */
- if(H5FD_MEM_DEFAULT==file->cls->fl_map[type])
- mapped_type = type;
- else
- mapped_type = file->cls->fl_map[type];
-
- /* Compute end of block */
- end = addr + size;
-
- /* Check if the block is exactly at the end of the file */
- if(end == eoa)
- at_end = TRUE;
- else {
- /* (Check if block is inside the metadata or small data accumulator) */
- if(mapped_type!=H5FD_MEM_DRAW) {
- if(file->feature_flags & H5FD_FEAT_AGGREGATE_METADATA)
- /* If the metadata block is at the end of the file, and
- * the block to test adjoins the beginning of the metadata
- * block, then it's extendable
- */
- if((file->eoma + file->cur_meta_block_size) == eoa &&
- end == file->eoma)
- update_eoma=TRUE;
- } /* end if */
- else {
- if(file->feature_flags & H5FD_FEAT_AGGREGATE_SMALLDATA)
- /* If the small data block is at the end of the file, and
- * the block to test adjoins the beginning of the small data
- * block, then it's extendable
- */
- if((file->eosda + file->cur_sdata_block_size) == eoa &&
- end == file->eosda)
- update_eosda=TRUE;
- } /* end else */
- } /* end else */
-
- /* Block is at end of file, we are extending the eoma or eosda */
- if(update_eoma || update_eosda || at_end) {
- /* Check for overflowing the file */
- if(H5F_addr_overflow(eoa, extra_requested) || eoa + extra_requested > file->maxaddr)
- HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, FAIL, "file allocation request failed")
-
- /* Extend the file */
- eoa += extra_requested;
- if(file->cls->set_eoa(file, type, eoa) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, FAIL, "file allocation request failed")
-
- /* Update the metadata and/or small data block */
- assert(!(update_eoma && update_eosda));
- if(update_eoma)
- file->eoma+=extra_requested;
- if(update_eosda)
- file->eosda+=extra_requested;
- } /* end if */
- /* If the block we are extending isn't at the end of the file, find a free block to extend into */
- else {
- H5FD_free_t *curr; /* Current free block being inspected */
- H5FD_free_t *prev; /* Current free block being inspected */
-
- /* Walk through free list, looking for block to merge with */
- curr = file->fl[mapped_type];
- prev = NULL;
- while(curr!=NULL) {
- /* Found block that ajoins end of block to extend */
- if(end == curr->addr) {
- /* Check if free space is large enough */
- if(extra_requested <= curr->size) {
- /* Check for exact match */
- if(extra_requested == curr->size) {
- /* Unlink node from free list */
- if(prev == NULL)
- file->fl[mapped_type] = curr->next;
- else
- prev->next = curr->next;
-
- /* Free the memory for the used block */
- H5FL_FREE(H5FD_free_t, curr);
- } /* end if */
- else {
- curr->addr += extra_requested;
- curr->size -= extra_requested;
- } /* end else */
-
- /* Leave now */
- break;
- } /* end if */
- else
- HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, FAIL, "can't extend block")
- } /* end if */
-
- /* Advance to next node in list */
- prev = curr;
- curr = curr->next;
- } /* end while */
-
- /* Couldn't find block to extend */
- if(curr == NULL)
- HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, FAIL, "can't extend block")
- } /* end else */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_extend() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5FDget_eoa
*
* Purpose: Returns the address of the first byte after the last
* allocated memory in the file.
*
* Return: Success: First byte after allocated memory.
- *
* Failure: HADDR_UNDEF
*
* Programmer: Robb Matzke
* Friday, July 30, 1999
*
- * Modifications:
- * Raymond Lu
- * 21 Dec. 2006
- * Added the parameter TYPE. It's only used for MULTI driver.
- *
*-------------------------------------------------------------------------
*/
haddr_t
@@ -2930,52 +1523,19 @@ H5FDget_eoa(H5FD_t *file, H5FD_mem_t type)
/* Check args */
if(!file || !file->cls)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, HADDR_UNDEF, "invalid file pointer")
- if(type<H5FD_MEM_DEFAULT || type >= H5FD_MEM_NTYPES)
+ if(type < H5FD_MEM_DEFAULT || type >= H5FD_MEM_NTYPES)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, HADDR_UNDEF, "invalid file type")
/* The real work */
- if(HADDR_UNDEF==(ret_value=H5FD_get_eoa(file, type)))
+ if(HADDR_UNDEF == (ret_value = H5FD_get_eoa(file, type)))
HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "file get eoa request failed")
-done:
- FUNC_LEAVE_API(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_get_eoa
- *
- * Purpose: Private version of H5FDget_eoa()
- *
- * Return: Success: First byte after allocated memory.
- *
- * Failure: HADDR_UNDEF
- *
- * Programmer: Robb Matzke
- * Wednesday, August 4, 1999
- *
- * Modifications:
- * Raymond Lu
- * 21 Dec. 2006
- * Added the parameter TYPE. It's only used for MULTI driver.
- *
- *-------------------------------------------------------------------------
- */
-haddr_t
-H5FD_get_eoa(const H5FD_t *file, H5FD_mem_t type)
-{
- haddr_t ret_value;
-
- FUNC_ENTER_NOAPI(H5FD_get_eoa, HADDR_UNDEF)
- assert(file && file->cls);
-
- /* Dispatch to driver */
- if(HADDR_UNDEF==(ret_value=(file->cls->get_eoa)(file, type)))
- HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "driver get_eoa request failed")
+ /* (Note compensating for base address subtraction in internal routine) */
+ ret_value += file->base_addr;
done:
- FUNC_LEAVE_NOAPI(ret_value)
-}
+ FUNC_LEAVE_API(ret_value)
+} /* end H5FDget_eoa() */
/*-------------------------------------------------------------------------
@@ -2995,23 +1555,17 @@ done:
* and the driver didn't supply an allocation callback.
*
* Return: Success: Non-negative
- *
* Failure: Negative, no side effect
*
* Programmer: Robb Matzke
* Friday, July 30, 1999
*
- * Modifications:
- * Raymond Lu
- * 21 Dec. 2006
- * Added the parameter TYPE. It's only used for MULTI driver.
- *
*-------------------------------------------------------------------------
*/
herr_t
H5FDset_eoa(H5FD_t *file, H5FD_mem_t type, haddr_t addr)
{
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(H5FDset_eoa, FAIL)
H5TRACE3("e", "*xMta", file, type, addr);
@@ -3019,57 +1573,19 @@ H5FDset_eoa(H5FD_t *file, H5FD_mem_t type, haddr_t addr)
/* Check args */
if(!file || !file->cls)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file pointer")
- if(type<H5FD_MEM_DEFAULT || type >= H5FD_MEM_NTYPES)
+ if(type < H5FD_MEM_DEFAULT || type >= H5FD_MEM_NTYPES)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file type")
-
- if(!H5F_addr_defined(addr) || addr>file->maxaddr)
+ if(!H5F_addr_defined(addr) || addr > file->maxaddr)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid end-of-address value")
/* The real work */
- if(H5FD_set_eoa(file, type, addr) < 0)
+ /* (Note compensating for base address addition in internal routine) */
+ if(H5FD_set_eoa(file, type, addr - file->base_addr) < 0)
HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "file set eoa request failed")
done:
FUNC_LEAVE_API(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_set_eoa
- *
- * Purpose: Private version of H5FDset_eoa()
- *
- * Return: Success: Non-negative
- *
- * Failure: Negative, no side effect
- *
- * Programmer: Robb Matzke
- * Wednesday, August 4, 1999
- *
- * Modifications:
- * Raymond Lu
- * 21 Dec. 2006
- * Added the parameter TYPE. It's only used for MULTI driver.
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5FD_set_eoa(H5FD_t *file, H5FD_mem_t UNUSED type, haddr_t addr)
-{
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5FD_set_eoa, FAIL)
-
- assert(file && file->cls);
- assert(H5F_addr_defined(addr) && addr<=file->maxaddr);
-
- /* Dispatch to driver */
- if((file->cls->set_eoa)(file, type, addr) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver set_eoa request failed")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FDset_eoa() */
/*-------------------------------------------------------------------------
@@ -3111,50 +1627,113 @@ H5FDget_eof(H5FD_t *file)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, HADDR_UNDEF, "invalid file pointer")
/* The real work */
- if(HADDR_UNDEF==(ret_value=H5FD_get_eof(file)))
+ if(HADDR_UNDEF == (ret_value = H5FD_get_eof(file)))
HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "file get eof request failed")
+ /* (Note compensating for base address subtraction in internal routine) */
+ ret_value += file->base_addr;
+
done:
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5FDget_eof() */
/*-------------------------------------------------------------------------
- * Function: H5FD_get_eof
+ * Function: H5FD_get_maxaddr
*
* Purpose: Private version of H5FDget_eof()
*
- * Return: Success: The EOF address.
- *
+ * Return: Success: The maximum address allowed in the file.
* Failure: HADDR_UNDEF
*
- * Programmer: Robb Matzke
- * Wednesday, August 4, 1999
- *
- * Modifications:
+ * Programmer: Quincey Koziol
+ * Thursday, January 3, 2008
*
*-------------------------------------------------------------------------
*/
haddr_t
-H5FD_get_eof(const H5FD_t *file)
+H5FD_get_maxaddr(const H5FD_t *file)
{
- haddr_t ret_value;
+ haddr_t ret_value; /* Return value */
- FUNC_ENTER_NOAPI(H5FD_get_eof, HADDR_UNDEF)
+ FUNC_ENTER_NOAPI(H5FD_get_maxaddr, HADDR_UNDEF)
- assert(file && file->cls);
+ HDassert(file);
- /* Dispatch to driver */
- if(file->cls->get_eof) {
- if(HADDR_UNDEF==(ret_value=(file->cls->get_eof)(file)))
- HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "driver get_eof request failed")
- } else {
- ret_value = file->maxaddr;
- }
+ /* Set return value */
+ ret_value = file->maxaddr;
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_get_maxaddr() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_get_feature_flags
+ *
+ * Purpose: Retrieve the feature flags for the VFD
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, January 8, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FD_get_feature_flags(const H5FD_t *file, unsigned long *feature_flags)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_get_feature_flags)
+
+ HDassert(file);
+ HDassert(feature_flags);
+
+ /* Set feature flags to return */
+ *feature_flags = file->feature_flags;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5FD_get_feature_flags() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_get_fs_type_map
+ *
+ * Purpose: Retrieve the free space type mapping for the VFD
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, January 17, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FD_get_fs_type_map(const H5FD_t *file, H5FD_mem_t *type_map)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5FD_get_fs_type_map, FAIL)
+
+ /* Sanity check */
+ HDassert(file);
+ HDassert(file && file->cls);
+ HDassert(type_map);
+
+ /* Check for VFD class providing a type map retrieval rouine */
+ if(file->cls->get_type_map) {
+ /* Retrieve type mapping for this file */
+ if((file->cls->get_type_map)(file, type_map) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "driver get type map failed")
+ } /* end if */
+ else
+ /* Copy class's default free space type mapping */
+ HDmemcpy(type_map, file->cls->fl_map, sizeof(file->cls->fl_map));
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_get_fs_type_map() */
/*-------------------------------------------------------------------------
@@ -3182,7 +1761,7 @@ herr_t
H5FDread(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size,
void *buf/*out*/)
{
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(H5FDread, FAIL)
H5TRACE6("e", "*xMtiazx", file, type, dxpl_id, addr, size, buf);
@@ -3195,206 +1774,76 @@ H5FDread(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size
if(H5P_DEFAULT == dxpl_id)
dxpl_id= H5P_DATASET_XFER_DEFAULT;
else
- if(TRUE!=H5P_isa_class(dxpl_id,H5P_DATASET_XFER))
+ if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list")
if(!buf)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "null result buffer")
/* Do the real work */
- if(H5FD_read(file, type, dxpl_id, addr, size, buf) < 0)
+ /* (Note compensating for base address addition in internal routine) */
+ if(H5FD_read(file, dxpl_id, type, addr - file->base_addr, size, buf) < 0)
HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "file read request failed")
done:
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5FDread() */
/*-------------------------------------------------------------------------
- * Function: H5FD_read
+ * Function: H5FDwrite
*
- * Purpose: Private version of H5FDread()
+ * Purpose: Writes SIZE bytes to FILE beginning at address ADDR according
+ * to the data transfer property list DXPL_ID (which may be the
+ * constant H5P_DEFAULT). The bytes to be written come from the
+ * buffer BUF.
*
* Return: Success: Non-negative
*
* Failure: Negative
*
* Programmer: Robb Matzke
- * Wednesday, August 4, 1999
+ * Thursday, July 29, 1999
*
* Modifications:
- * Albert Cheng, 2000-11-21
- * Disable the code that does early return when size==0 for
- * Parallel mode since a collective call would require the process
- * to continue on with "nothing" to transfer.
*
*-------------------------------------------------------------------------
*/
herr_t
-H5FD_read(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size,
- void *buf/*out*/)
+H5FDwrite(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size,
+ const void *buf)
{
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5FD_read, FAIL)
-
- assert(file && file->cls);
- assert(H5I_GENPROP_LST==H5I_get_type(dxpl_id));
- assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER));
- assert(buf);
-
-#ifndef H5_HAVE_PARALLEL
- /* Do not return early for Parallel mode since the I/O could be a */
- /* collective transfer. */
- /* The no-op case */
- if(0==size)
- HGOTO_DONE(SUCCEED)
-#endif /* H5_HAVE_PARALLEL */
-
- /* Check if this information is in the metadata accumulator */
- if((file->feature_flags&H5FD_FEAT_ACCUMULATE_METADATA) && type!=H5FD_MEM_DRAW) {
- /* Current read overlaps with metadata accumulator */
- if(H5F_addr_overlap(addr,size,file->accum_loc,file->accum_size)) {
- unsigned char *read_buf=(unsigned char *)buf; /* Pointer to the buffer being read in */
- size_t amount_read; /* Amount to read at a time */
-#ifndef NDEBUG
- hsize_t tempamount_read; /* Amount to read at a time */
-#endif /* NDEBUG */
- hsize_t read_off; /* Offset to read from */
-
- /* Double check that we aren't reading raw data */
- assert(type!=H5FD_MEM_DRAW);
-
- /* Read the part before the metadata accumulator */
- if(addr<file->accum_loc) {
- /* Set the amount to read */
- H5_ASSIGN_OVERFLOW(amount_read,file->accum_loc-addr,hsize_t,size_t);
-
- /* Dispatch to driver */
- if((file->cls->read)(file, type, dxpl_id, addr, amount_read, read_buf) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read request failed")
-
- /* Adjust the buffer, address & size */
- read_buf+=amount_read;
- addr+=amount_read;
- size-=amount_read;
- } /* end if */
-
- /* Copy the part overlapping the metadata accumulator */
- if(size>0 && (addr>=file->accum_loc && addr<(file->accum_loc+file->accum_size))) {
- /* Set the offset to "read" from */
- read_off=addr-file->accum_loc;
-
- /* Set the amount to "read" */
-#ifndef NDEBUG
- tempamount_read = file->accum_size-read_off;
- H5_CHECK_OVERFLOW(tempamount_read,hsize_t,size_t);
- amount_read = MIN(size, (size_t)tempamount_read);
-#else /* NDEBUG */
- amount_read = MIN(size, (size_t)(file->accum_size-read_off));
-#endif /* NDEBUG */
-
- /* Copy the data out of the buffer */
- HDmemcpy(read_buf,file->meta_accum+read_off,amount_read);
-
- /* Adjust the buffer, address & size */
- read_buf+=amount_read;
- addr+=amount_read;
- size-=amount_read;
- } /* end if */
+ herr_t ret_value = SUCCEED; /* Return value */
- /* Read the part after the metadata accumulator */
- if(size>0 && addr>=(file->accum_loc+file->accum_size)) {
- /* Dispatch to driver */
- if((file->cls->read)(file, type, dxpl_id, addr, size, read_buf) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read request failed")
+ FUNC_ENTER_API(H5FDwrite, FAIL)
+ H5TRACE6("e", "*xMtiaz*x", file, type, dxpl_id, addr, size, buf);
- /* Adjust the buffer, address & size */
- read_buf+=size;
- addr+=size;
- size-=size;
- } /* end if */
+ /* Check args */
+ if(!file || !file->cls)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file pointer")
+ /* Get the default dataset transfer property list if the user didn't provide one */
+ if(H5P_DEFAULT == dxpl_id)
+ dxpl_id = H5P_DATASET_XFER_DEFAULT;
+ else
+ if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list")
+ if(!buf)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "null buffer")
- /* Make certain we've read it all */
- assert(size==0);
- } /* end if */
- /* Current read doesn't overlap with metadata accumulator, read it into accumulator */
- else {
- /* Only update the metadata accumulator if it is not dirty or if
- * we are allowed to write the accumulator out during reads (when
- * it is dirty)
- */
- if(file->feature_flags&H5FD_FEAT_ACCUMULATE_METADATA_READ || !file->accum_dirty) {
- /* Flush current contents, if dirty */
- if(file->accum_dirty) {
- if((file->cls->write)(file, H5FD_MEM_DEFAULT, dxpl_id, file->accum_loc, file->accum_size, file->meta_accum) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "driver write request failed")
-
- /* Reset accumulator dirty flag */
- file->accum_dirty=FALSE;
- } /* end if */
-
- /* Cache the new piece of metadata */
- /* Check if we need to resize the buffer */
- if(size>file->accum_buf_size) {
- /* Grow the metadata accumulator buffer */
- if((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
-
- /* Note the new buffer size */
- file->accum_buf_size=size;
- } /* end if */
- else {
- /* Check if we should shrink the accumulator buffer */
- if(size<(file->accum_buf_size/H5FD_ACCUM_THROTTLE) &&
- file->accum_buf_size>H5FD_ACCUM_THRESHOLD) {
- size_t new_size=(file->accum_buf_size/H5FD_ACCUM_THROTTLE); /* New size of accumulator buffer */
-
- /* Shrink the accumulator buffer */
- if((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,new_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
-
- /* Note the new buffer size */
- file->accum_buf_size=new_size;
- } /* end if */
- } /* end else */
-
- /* Update accumulator information */
- file->accum_loc=addr;
- file->accum_size=size;
- file->accum_dirty=FALSE;
-
- /* Read into accumulator */
- if((file->cls->read)(file, H5FD_MEM_DEFAULT, dxpl_id, file->accum_loc, file->accum_size, file->meta_accum) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read request failed")
-
- /* Copy into buffer */
- HDmemcpy(buf,file->meta_accum,size);
- } /* end if */
- else {
- /* Dispatch to driver */
- if((file->cls->read)(file, type, dxpl_id, addr, size, buf) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read request failed")
- } /* end else */
- } /* end else */
- } /* end if */
- else {
- /* Dispatch to driver */
- if((file->cls->read)(file, type, dxpl_id, addr, size, buf) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read request failed")
- } /* end else */
+ /* The real work */
+ /* (Note compensating for base address addition in internal routine) */
+ if(H5FD_write(file, dxpl_id, type, addr - file->base_addr, size, buf) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "file write request failed")
done:
- FUNC_LEAVE_NOAPI(ret_value)
-}
+ FUNC_LEAVE_API(ret_value)
+} /* end H5FDwrite() */
/*-------------------------------------------------------------------------
- * Function: H5FDwrite
+ * Function: H5FDflush
*
- * Purpose: Writes SIZE bytes to FILE beginning at address ADDR according
- * to the data transfer property list DXPL_ID (which may be the
- * constant H5P_DEFAULT). The bytes to be written come from the
- * buffer BUF.
+ * Purpose: Notify driver to flush all cached data. If the driver has no
+ * flush method then nothing happens.
*
* Return: Success: Non-negative
*
@@ -3404,33 +1853,31 @@ done:
* Thursday, July 29, 1999
*
* Modifications:
+ * Quincey Koziol, May 20, 2002
+ * Added 'closing' parameter
*
*-------------------------------------------------------------------------
*/
herr_t
-H5FDwrite(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size,
- const void *buf)
+H5FDflush(H5FD_t *file, hid_t dxpl_id, unsigned closing)
{
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_API(H5FDwrite, FAIL)
- H5TRACE6("e", "*xMtiaz*x", file, type, dxpl_id, addr, size, buf);
+ FUNC_ENTER_API(H5FDflush, FAIL)
+ H5TRACE3("e", "*xiIu", file, dxpl_id, closing);
/* Check args */
if(!file || !file->cls)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file pointer")
- /* Get the default dataset transfer property list if the user didn't provide one */
if(H5P_DEFAULT == dxpl_id)
- dxpl_id= H5P_DATASET_XFER_DEFAULT;
+ dxpl_id = H5P_DATASET_XFER_DEFAULT;
else
- if(TRUE!=H5P_isa_class(dxpl_id,H5P_DATASET_XFER))
+ if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list")
- if(!buf)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "null buffer")
- /* The real work */
- if(H5FD_write(file, type, dxpl_id, addr, size, buf) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "file write request failed")
+ /* Do the real work */
+ if(H5FD_flush(file, dxpl_id, closing) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTFLUSH, FAIL, "file flush request failed")
done:
FUNC_LEAVE_API(ret_value)
@@ -3438,303 +1885,68 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5FD_write
+ * Function: H5FD_flush
*
- * Purpose: Private version of H5FDwrite()
+ * Purpose: Private version of H5FDflush()
*
* Return: Success: Non-negative
- *
* Failure: Negative
*
* Programmer: Robb Matzke
* Wednesday, August 4, 1999
*
- * Modifications:
- * Albert Cheng, 2000-11-21
- * Disable the code that does early return when size==0 for
- * Parallel mode since a collective call would require the process
- * to continue on with "nothing" to transfer.
- *
*-------------------------------------------------------------------------
*/
herr_t
-H5FD_write(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size,
- const void *buf)
+H5FD_flush(H5FD_t *file, hid_t dxpl_id, unsigned closing)
{
- size_t new_size; /* New size of the accumulator buffer */
- size_t old_offset; /* Offset of old data within the accumulator buffer */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5FD_write, FAIL)
-
- assert(file && file->cls);
- assert(H5I_GENPROP_LST==H5I_get_type(dxpl_id));
- assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER));
- assert(buf);
-
-#ifndef H5_HAVE_PARALLEL
- /* Do not return early for Parallel mode since the I/O could be a */
- /* collective transfer. */
- /* The no-op case */
- if(0==size)
- HGOTO_DONE(SUCCEED)
-#endif /* H5_HAVE_PARALLEL */
+ herr_t ret_value = SUCCEED; /* Return value */
- /* Check for accumulating metadata */
- if((file->feature_flags&H5FD_FEAT_ACCUMULATE_METADATA) && type!=H5FD_MEM_DRAW) {
- /* Check if there is already metadata in the accumulator */
- if(file->accum_size>0) {
- /* Check if the piece of metadata being written adjoins or is inside the metadata accumulator */
- if((addr>=file->accum_loc && addr<=(file->accum_loc+file->accum_size))
- || ((addr+size)>file->accum_loc && (addr+size)<=(file->accum_loc+file->accum_size))
- || (addr<file->accum_loc && (addr+size)>=file->accum_loc)) {
-
- /* Check if the new metadata adjoins the beginning of the current accumulator */
- if((addr+size)==file->accum_loc) {
- /* Check if we need more buffer space */
- if((size+file->accum_size)>file->accum_buf_size) {
- /* Adjust the buffer size, by doubling it */
- file->accum_buf_size = MAX(file->accum_buf_size*2,size+file->accum_size);
-
- /* Reallocate the metadata accumulator buffer */
- if((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,file->accum_buf_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
-#ifdef H5_CLEAR_MEMORY
-HDmemset(file->meta_accum + file->accum_size, 0, (file->accum_buf_size - (file->accum_size + size)));
-#endif /* H5_CLEAR_MEMORY */
- } /* end if */
-
- /* Move the existing metadata to the proper location */
- HDmemmove(file->meta_accum+size,file->meta_accum,file->accum_size);
-
- /* Copy the new metadata at the front */
- HDmemcpy(file->meta_accum,buf,size);
-
- /* Set the new size & location of the metadata accumulator */
- file->accum_loc=addr;
- file->accum_size=file->accum_size+size;
-
- /* Mark it as written to */
- file->accum_dirty=TRUE;
- } /* end if */
- /* Check if the new metadata adjoins the end of the current accumulator */
- else if(addr==(file->accum_loc+file->accum_size)) {
- /* Check if we need more buffer space */
- if((size+file->accum_size)>file->accum_buf_size) {
- /* Adjust the buffer size, by doubling it */
- file->accum_buf_size = MAX(file->accum_buf_size*2,size+file->accum_size);
-
- /* Reallocate the metadata accumulator buffer */
- if((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,file->accum_buf_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
-#ifdef H5_CLEAR_MEMORY
-HDmemset(file->meta_accum + file->accum_size + size, 0, (file->accum_buf_size - (file->accum_size + size)));
-#endif /* H5_CLEAR_MEMORY */
- } /* end if */
-
- /* Copy the new metadata to the end */
- HDmemcpy(file->meta_accum+file->accum_size,buf,size);
-
- /* Set the new size of the metadata accumulator */
- file->accum_size=file->accum_size+size;
-
- /* Mark it as written to */
- file->accum_dirty=TRUE;
- } /* end if */
- /* Check if the new metadata is entirely within the current accumulator */
- else if(addr>=file->accum_loc && (addr+size)<=(file->accum_loc+file->accum_size)) {
- /* Copy the new metadata to the proper location within the accumulator */
- HDmemcpy(file->meta_accum+(addr-file->accum_loc),buf,size);
-
- /* Mark it as written to */
- file->accum_dirty=TRUE;
- } /* end if */
- /* Check if the new metadata overlaps the beginning of the current accumulator */
- else if(addr<file->accum_loc && (addr+size)<=(file->accum_loc+file->accum_size)) {
- /* Calculate the new accumulator size, based on the amount of overlap */
- H5_ASSIGN_OVERFLOW(new_size,(file->accum_loc-addr)+file->accum_size,hsize_t,size_t);
-
- /* Check if we need more buffer space */
- if(new_size>file->accum_buf_size) {
- /* Adjust the buffer size, by doubling it */
- file->accum_buf_size = MAX(file->accum_buf_size*2,new_size);
-
- /* Reallocate the metadata accumulator buffer */
- if((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,file->accum_buf_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
-#ifdef H5_CLEAR_MEMORY
-HDmemset(file->meta_accum + file->accum_size, 0, (file->accum_buf_size - file->accum_size));
-#endif /* H5_CLEAR_MEMORY */
- } /* end if */
-
- /* Calculate the proper offset of the existing metadata */
- H5_ASSIGN_OVERFLOW(old_offset,(addr+size)-file->accum_loc,hsize_t,size_t);
-
- /* Move the existing metadata to the proper location */
- HDmemmove(file->meta_accum+size,file->meta_accum+old_offset,(file->accum_size-old_offset));
-
- /* Copy the new metadata at the front */
- HDmemcpy(file->meta_accum,buf,size);
-
- /* Set the new size & location of the metadata accumulator */
- file->accum_loc=addr;
- file->accum_size=new_size;
-
- /* Mark it as written to */
- file->accum_dirty=TRUE;
- } /* end if */
- /* Check if the new metadata overlaps the end of the current accumulator */
- else if(addr>=file->accum_loc && (addr+size)>(file->accum_loc+file->accum_size)) {
- /* Calculate the new accumulator size, based on the amount of overlap */
- H5_ASSIGN_OVERFLOW(new_size,(addr-file->accum_loc)+size,hsize_t,size_t);
-
- /* Check if we need more buffer space */
- if(new_size>file->accum_buf_size) {
- /* Adjust the buffer size, by doubling it */
- file->accum_buf_size = MAX(file->accum_buf_size*2,new_size);
-
- /* Reallocate the metadata accumulator buffer */
- if((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,file->accum_buf_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
-#ifdef H5_CLEAR_MEMORY
-HDmemset(file->meta_accum + file->accum_size, 0, (file->accum_buf_size - file->accum_size));
-#endif /* H5_CLEAR_MEMORY */
- } /* end if */
-
- /* Copy the new metadata to the end */
- HDmemcpy(file->meta_accum+(addr-file->accum_loc),buf,size);
-
- /* Set the new size & location of the metadata accumulator */
- file->accum_size=new_size;
-
- /* Mark it as written to */
- file->accum_dirty=TRUE;
- } /* end if */
- else {
- assert(0 && "New metadata overlapped both beginning and end of existing metadata accumulator!");
- } /* end else */
- } /* end if */
- /* New piece of metadata doesn't adjoin or overlap the existing accumulator */
- else {
- /* Write out the existing metadata accumulator, with dispatch to driver */
- if(file->accum_dirty) {
- if((file->cls->write)(file, H5FD_MEM_DEFAULT, dxpl_id, file->accum_loc, file->accum_size, file->meta_accum) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "driver write request failed")
- /* Reset accumulator dirty flag */
- file->accum_dirty=FALSE;
- } /* end if */
-
- /* Cache the new piece of metadata */
- /* Check if we need to resize the buffer */
- if(size>file->accum_buf_size) {
- /* Grow the metadata accumulator buffer */
- if((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
-
- /* Note the new buffer size */
- file->accum_buf_size=size;
-#ifdef H5_CLEAR_MEMORY
-{
-size_t clear_size = MAX(file->accum_size, size);
-HDmemset(file->meta_accum + clear_size, 0, (file->accum_buf_size - clear_size));
-}
-#endif /* H5_CLEAR_MEMORY */
- } /* end if */
- else {
- /* Check if we should shrink the accumulator buffer */
- if(size<(file->accum_buf_size/H5FD_ACCUM_THROTTLE) &&
- file->accum_buf_size>H5FD_ACCUM_THRESHOLD) {
- size_t tmp_size=(file->accum_buf_size/H5FD_ACCUM_THROTTLE); /* New size of accumulator buffer */
-
- /* Shrink the accumulator buffer */
- if((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,tmp_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
-
- /* Note the new buffer size */
- file->accum_buf_size=tmp_size;
- } /* end if */
- } /* end else */
-
- /* Update the metadata accumulator information */
- file->accum_loc=addr;
- file->accum_size=size;
- file->accum_dirty=TRUE;
-
- /* Store the piece of metadata in the accumulator */
- HDmemcpy(file->meta_accum,buf,size);
- } /* end else */
- } /* end if */
- /* No metadata in the accumulator, grab this piece and keep it */
- else {
- /* Check if we need to reallocate the buffer */
- if(size>file->accum_buf_size) {
- /* Reallocate the metadata accumulator buffer */
- if((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
-
- /* Note the new buffer size */
- file->accum_buf_size=size;
- } /* end if */
+ FUNC_ENTER_NOAPI(H5FD_flush, FAIL)
- /* Update the metadata accumulator information */
- file->accum_loc=addr;
- file->accum_size=size;
- file->accum_dirty=TRUE;
+ HDassert(file && file->cls);
- /* Store the piece of metadata in the accumulator */
- HDmemcpy(file->meta_accum,buf,size);
- } /* end else */
- } /* end if */
- else {
- /* Dispatch to driver */
- if((file->cls->write)(file, type, dxpl_id, addr, size, buf) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "driver write request failed")
- } /* end else */
+ if(file->cls->flush && (file->cls->flush)(file, dxpl_id, closing) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver flush request failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_flush() */
/*-------------------------------------------------------------------------
- * Function: H5FDflush
+ * Function: H5FDtruncate
*
- * Purpose: Notify driver to flush all cached data. If the driver has no
- * flush method then nothing happens.
+ * Purpose: Notify driver to truncate the file back to the allocated size.
*
* Return: Success: Non-negative
- *
* Failure: Negative
*
- * Programmer: Robb Matzke
- * Thursday, July 29, 1999
- *
- * Modifications:
- * Quincey Koziol, May 20, 2002
- * Added 'closing' parameter
+ * Programmer: Quincey Koziol
+ * Thursday, January 31, 2008
*
*-------------------------------------------------------------------------
*/
herr_t
-H5FDflush(H5FD_t *file, hid_t dxpl_id, unsigned closing)
+H5FDtruncate(H5FD_t *file, hid_t dxpl_id, unsigned closing)
{
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_API(H5FDflush, FAIL)
+ FUNC_ENTER_API(H5FDtruncate, FAIL)
H5TRACE3("e", "*xiIu", file, dxpl_id, closing);
/* Check args */
if(!file || !file->cls)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file pointer")
if(H5P_DEFAULT == dxpl_id)
- dxpl_id= H5P_DATASET_XFER_DEFAULT;
+ dxpl_id = H5P_DATASET_XFER_DEFAULT;
else
- if(TRUE!=H5P_isa_class(dxpl_id,H5P_DATASET_XFER))
+ if(TRUE != H5P_isa_class(dxpl_id,H5P_DATASET_XFER))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list")
/* Do the real work */
- if(H5FD_flush(file,dxpl_id,closing) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "file flush request failed")
+ if(H5FD_truncate(file, dxpl_id, closing) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTUPDATE, FAIL, "file flush request failed")
done:
FUNC_LEAVE_API(ret_value)
@@ -3742,49 +1954,33 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5FD_flush
+ * Function: H5FD_truncate
*
- * Purpose: Private version of H5FDflush()
+ * Purpose: Private version of H5FDtruncate()
*
* Return: Success: Non-negative
- *
* Failure: Negative
*
- * Programmer: Robb Matzke
- * Wednesday, August 4, 1999
- *
- * Modifications:
- * Quincey Koziol, May 20, 2002
- * Added 'closing' parameter
+ * Programmer: Quincey Koziol
+ * Thursday, January 31, 2008
*
*-------------------------------------------------------------------------
*/
herr_t
-H5FD_flush(H5FD_t *file, hid_t dxpl_id, unsigned closing)
+H5FD_truncate(H5FD_t *file, hid_t dxpl_id, unsigned closing)
{
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5FD_flush, FAIL)
-
- assert(file && file->cls);
+ herr_t ret_value = SUCCEED; /* Return value */
- /* Check if we need to flush out the metadata accumulator */
- if((file->feature_flags&H5FD_FEAT_ACCUMULATE_METADATA) && file->accum_dirty && file->accum_size>0) {
- /* Flush the metadata contents */
- /* Not certain if the type and dxpl should be the way they are... -QAK */
- if((file->cls->write)(file, H5FD_MEM_DEFAULT, dxpl_id, file->accum_loc, file->accum_size, file->meta_accum) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver write request failed")
+ FUNC_ENTER_NOAPI(H5FD_truncate, FAIL)
- /* Reset the dirty flag */
- file->accum_dirty=FALSE;
- } /* end if */
+ HDassert(file && file->cls);
- if(file->cls->flush && (file->cls->flush)(file,dxpl_id,closing) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver flush request failed")
+ if(file->cls->truncate && (file->cls->truncate)(file, dxpl_id, closing) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTUPDATE, FAIL, "driver truncate request failed")
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_truncate() */
/*-------------------------------------------------------------------------
@@ -3799,22 +1995,20 @@ done:
* Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
* March 27, 2002
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
herr_t
H5FD_get_fileno(const H5FD_t *file, unsigned long *filenum)
{
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5FD_get_fileno, FAIL)
- assert(file);
- assert(filenum);
+ HDassert(file);
+ HDassert(filenum);
/* Retrieve the file's serial number */
- HDmemcpy(filenum,&file->fileno,sizeof(file->fileno));
+ *filenum = file->fileno;
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -3888,102 +2082,32 @@ done:
} /* end H5FD_get_vfd_handle() */
-/*-------------------------------------------------------------------------
- * Function: H5FD_get_freespace
+/*--------------------------------------------------------------------------
+ * Function: H5FD_set_base_addr
*
- * Purpose: Retrieve the amount of free space in a file.
+ * Purpose: Set the base address for the file
*
- * Return: Success: Amount of free space in file
- * Failure: Negative
+ * Return: Non-negative if succeed; negative if fails.
*
* Programmer: Quincey Koziol
- * Monday, October 6, 2003
+ * Jan. 17, 2008
*
- * Modifications:
- * Raymond Lu
- * 5 January 2007
- * Due to the complexity EOA for Multi driver, this function
- * is made failed for now.
- *
- *-------------------------------------------------------------------------
+ *--------------------------------------------------------------------------
*/
-hssize_t
-H5FD_get_freespace(const H5FD_t *file)
+herr_t
+H5FD_set_base_addr(H5FD_t *file, haddr_t base_addr)
{
- H5FD_free_t *free_node; /* Pointer to node on free list */
- H5FD_mem_t type; /* Type of memory */
- haddr_t ma_addr = HADDR_UNDEF; /* Base "metadata aggregator" address */
- hsize_t ma_size = 0; /* Size of "metadata aggregator" */
- haddr_t sda_addr = HADDR_UNDEF; /* Base "small data aggregator" address */
- hsize_t sda_size = 0; /* Size of "small data aggregator" */
- haddr_t eoa = 0; /* End of allocated space in the file */
- hssize_t ret_value = 0; /* Return value */
+ herr_t ret_value = SUCCEED;
- FUNC_ENTER_NOAPI(H5FD_get_freespace, FAIL)
+ FUNC_ENTER_NOAPI(H5FD_set_base_addr, FAIL)
- /* check args */
HDassert(file);
- HDassert(file->cls);
-
- /* Multi driver doesn't support this function because of the complexity.
- * It doesn't have eoa for the whole file. */
- if(file->driver_id == H5FD_MULTI)
- HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "Multi driver doesn't support this function")
-
- /* Retrieve the 'eoa' for the file */
- eoa = file->cls->get_eoa(file, H5FD_MEM_DEFAULT);
-
- /* Check for aggregating metadata allocations */
- if(file->feature_flags & H5FD_FEAT_AGGREGATE_METADATA) {
- ma_addr = file->eoma;
- ma_size = file->cur_meta_block_size;
- } /* end if */
+ HDassert(H5F_addr_defined(base_addr));
- /* Check for aggregating small data allocations */
- if(file->feature_flags & H5FD_FEAT_AGGREGATE_SMALLDATA) {
- sda_addr = file->eosda;
- sda_size = file->cur_sdata_block_size;
- } /* end if */
-
- /* Iterate over all the types of memory, to retrieve amount of free space for each */
- for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t,type)) {
- /* Iterate through the free list, accumulating the amount of free space for this type */
- free_node = file->fl[type];
- while(free_node) {
- /* Check for current node adjoining the metadata & small data aggregators */
- if(H5F_addr_eq(free_node->addr + free_node->size, ma_addr)) {
- ma_addr -= free_node->size;
- ma_size += free_node->size;
- } else if(H5F_addr_eq(free_node->addr + free_node->size, sda_addr)) {
- sda_addr -= free_node->size;
- sda_size += free_node->size;
- } else if(H5F_addr_eq(ma_addr + ma_size, free_node->addr))
- ma_size += free_node->size;
- else if(H5F_addr_eq(sda_addr + sda_size, free_node->addr))
- sda_size += free_node->size;
- else
- ret_value += (hssize_t)free_node->size;
- free_node = free_node->next;
- } /* end while */
- } /* end for */
-
- /* Check for aggregating metadata allocations */
- if(H5F_addr_defined(ma_addr)) {
- /* Add in the reserved space for metadata to the available free space */
- /* (if it's not at the tail of the file) */
- if(H5F_addr_ne(ma_addr + ma_size, eoa))
- ret_value += ma_size;
- } /* end if */
-
- /* Check for aggregating small data allocations */
- if(H5F_addr_defined(sda_addr)) {
- /* Add in the reserved space for metadata to the available free space */
- /* (if it's not at the tail of the file) */
- if(H5F_addr_ne(sda_addr + sda_size, eoa))
- ret_value += sda_size;
- } /* end if */
+ /* Set the file's base address */
+ file->base_addr = base_addr;
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_get_freespace() */
+} /* end H5FD_set_base_addr() */
diff --git a/src/H5FDcore.c b/src/H5FDcore.c
index 4c468b6..68a0655 100644
--- a/src/H5FDcore.c
+++ b/src/H5FDcore.c
@@ -91,6 +91,7 @@ static H5FD_t *H5FD_core_open(const char *name, unsigned flags, hid_t fapl_id,
haddr_t maxaddr);
static herr_t H5FD_core_close(H5FD_t *_file);
static int H5FD_core_cmp(const H5FD_t *_f1, const H5FD_t *_f2);
+static herr_t H5FD_core_query(const H5FD_t *_f1, unsigned long *flags);
static haddr_t H5FD_core_get_eoa(const H5FD_t *_file, H5FD_mem_t type);
static herr_t H5FD_core_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t addr);
static haddr_t H5FD_core_get_eof(const H5FD_t *_file);
@@ -100,6 +101,7 @@ static herr_t H5FD_core_read(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, hadd
static herr_t H5FD_core_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr,
size_t size, const void *buf);
static herr_t H5FD_core_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing);
+static herr_t H5FD_core_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
static const H5FD_class_t H5FD_core_g = {
"core", /*name */
@@ -118,7 +120,8 @@ static const H5FD_class_t H5FD_core_g = {
H5FD_core_open, /*open */
H5FD_core_close, /*close */
H5FD_core_cmp, /*cmp */
- NULL, /*query */
+ H5FD_core_query, /*query */
+ NULL, /*get_type_map */
NULL, /*alloc */
NULL, /*free */
H5FD_core_get_eoa, /*get_eoa */
@@ -128,6 +131,7 @@ static const H5FD_class_t H5FD_core_g = {
H5FD_core_read, /*read */
H5FD_core_write, /*write */
H5FD_core_flush, /*flush */
+ H5FD_core_truncate, /*truncate */
NULL, /*lock */
NULL, /*unlock */
H5FD_FLMAP_SINGLE /*fl_map */
@@ -181,7 +185,7 @@ H5FD_core_init(void)
FUNC_ENTER_NOAPI(H5FD_core_init, FAIL)
if (H5I_VFL!=H5Iget_type(H5FD_CORE_g))
- H5FD_CORE_g = H5FD_register(&H5FD_core_g,sizeof(H5FD_class_t));
+ H5FD_CORE_g = H5FD_register(&H5FD_core_g,sizeof(H5FD_class_t),FALSE);
/* Set return value */
ret_value=H5FD_CORE_g;
@@ -297,11 +301,11 @@ H5Pget_fapl_core(hid_t fapl_id, size_t *increment/*out*/,
FUNC_ENTER_API(H5Pget_fapl_core, FAIL)
H5TRACE3("e", "ixx", fapl_id, increment, backing_store);
- if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS)))
+ if(NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")
- if (H5FD_CORE!=H5P_get_driver(plist))
+ if(H5FD_CORE != H5P_get_driver(plist))
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "incorrect VFL driver")
- if (NULL==(fa=H5P_get_driver_info(plist)))
+ if(NULL == (fa = (H5FD_core_fapl_t *)H5P_get_driver_info(plist)))
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "bad VFL driver info")
if (increment)
@@ -334,16 +338,16 @@ static void *
H5FD_core_fapl_get(H5FD_t *_file)
{
H5FD_core_t *file = (H5FD_core_t*)_file;
- H5FD_core_fapl_t *fa = NULL;
+ H5FD_core_fapl_t *fa;
void *ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5FD_core_fapl_get, NULL)
- if (NULL==(fa=H5MM_calloc(sizeof(H5FD_core_fapl_t))))
+ if(NULL == (fa = (H5FD_core_fapl_t *)H5MM_calloc(sizeof(H5FD_core_fapl_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
fa->increment = file->increment;
- fa->backing_store = (file->fd>=0);
+ fa->backing_store = (hbool_t)(file->fd >= 0);
/* Set return value */
ret_value=fa;
@@ -370,9 +374,9 @@ done:
* Modifications:
* Robb Matzke, 1999-10-19
* The backing store file is created and opened if specified.
- *
+ *
* Raymond Lu, 2006-11-30
- * Enabled the driver to read an existing file depending on
+ * Enabled the driver to read an existing file depending on
* the setting of the backing_store and file open flags.
*-------------------------------------------------------------------------
*/
@@ -395,12 +399,12 @@ H5FD_core_open(const char *name, unsigned flags, hid_t fapl_id,
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid file name")
if (0==maxaddr || HADDR_UNDEF==maxaddr)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "bogus maxaddr")
- if (ADDR_OVERFLOW(maxaddr))
+ if(ADDR_OVERFLOW(maxaddr))
HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, NULL, "maxaddr overflow")
- if (H5P_DEFAULT!=fapl_id) {
- if(NULL == (plist = H5I_object(fapl_id)))
+ if(H5P_DEFAULT != fapl_id) {
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list")
- fa = H5P_get_driver_info(plist);
+ fa = (H5FD_core_fapl_t *)H5P_get_driver_info(plist);
} /* end if */
/* Build the open flags */
@@ -417,10 +421,10 @@ H5FD_core_open(const char *name, unsigned flags, hid_t fapl_id,
}
/* Create the new file struct */
- if (NULL==(file=H5MM_calloc(sizeof(H5FD_core_t))))
+ if(NULL == (file = (H5FD_core_t *)H5MM_calloc(sizeof(H5FD_core_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate file struct")
file->fd = fd;
- if (name && *name)
+ if(name && *name)
file->name = H5MM_xstrdup(name);
/*
@@ -557,6 +561,42 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5FD_core_query
+ *
+ * Purpose: Set the flags that this VFL driver is capable of supporting.
+ * (listed in H5FDpublic.h)
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, October 7, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static herr_t
+H5FD_core_query(const H5FD_t UNUSED * _f, unsigned long *flags /* out */)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5FD_core_query, FAIL)
+
+ /* Set the VFL feature flags that this driver supports */
+ if(flags) {
+ *flags = 0;
+ *flags |= H5FD_FEAT_AGGREGATE_METADATA; /* OK to aggregate metadata allocations */
+ *flags |= H5FD_FEAT_ACCUMULATE_METADATA; /* OK to accumulate metadata for faster writes */
+ *flags |= H5FD_FEAT_DATA_SIEVE; /* OK to perform data sieving for faster raw data reads & writes */
+ *flags |= H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_core_query() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5FD_core_get_eoa
*
* Purpose: Gets the end-of-address marker for the file. The EOA marker
@@ -619,18 +659,18 @@ static herr_t
H5FD_core_set_eoa(H5FD_t *_file, H5FD_mem_t UNUSED type, haddr_t addr)
{
H5FD_core_t *file = (H5FD_core_t*)_file;
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5FD_core_set_eoa, FAIL)
- if (ADDR_OVERFLOW(addr))
+ if(ADDR_OVERFLOW(addr))
HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "address overflow")
file->eoa = addr;
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_core_set_eoa() */
/*-------------------------------------------------------------------------
@@ -794,18 +834,18 @@ static herr_t
H5FD_core_write(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, haddr_t addr,
size_t size, const void *buf)
{
- H5FD_core_t *file = (H5FD_core_t*)_file;
- herr_t ret_value=SUCCEED; /* Return value */
+ H5FD_core_t *file = (H5FD_core_t*)_file;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5FD_core_write, FAIL)
- assert(file && file->pub.cls);
- assert(buf);
+ HDassert(file && file->pub.cls);
+ HDassert(buf);
/* Check for overflow conditions */
- if (REGION_OVERFLOW(addr, size))
+ if(REGION_OVERFLOW(addr, size))
HGOTO_ERROR(H5E_IO, H5E_OVERFLOW, FAIL, "file address overflowed")
- if (addr+size>file->eoa)
+ if(addr + size > file->eoa)
HGOTO_ERROR(H5E_IO, H5E_OVERFLOW, FAIL, "file address overflowed")
/*
@@ -814,34 +854,33 @@ H5FD_core_write(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, had
* careful of non-Posix realloc() that doesn't understand what to do when
* the first argument is null.
*/
- if (addr+size>file->eof) {
+ if(addr + size > file->eof) {
unsigned char *x;
size_t new_eof;
- H5_ASSIGN_OVERFLOW(new_eof,file->increment*((addr+size)/file->increment),hsize_t,size_t);
-
- if ((addr+size) % file->increment)
+ /* Determine new size of memory buffer */
+ H5_ASSIGN_OVERFLOW(new_eof, file->increment * ((addr + size) / file->increment), hsize_t, size_t);
+ if((addr + size) % file->increment)
new_eof += file->increment;
- if (NULL==file->mem)
- x = H5MM_malloc(new_eof);
- else
- x = H5MM_realloc(file->mem, new_eof);
+
+ /* (Re)allocate memory for the file buffer */
+ if(NULL == (x = (unsigned char *)H5MM_realloc(file->mem, new_eof)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory block")
#ifdef H5_CLEAR_MEMORY
HDmemset(x + file->eof, 0, (size_t)(new_eof - file->eof));
#endif /* H5_CLEAR_MEMORY */
- if (!x)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory block")
file->mem = x;
+
file->eof = new_eof;
- }
+ } /* end if */
/* Write from BUF to memory */
- HDmemcpy(file->mem+addr, buf, size);
+ HDmemcpy(file->mem + addr, buf, size);
file->dirty = TRUE;
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_core_write() */
/*-------------------------------------------------------------------------
@@ -860,7 +899,7 @@ done:
* Modifications:
* Raymond Lu, 2006-11-30
* Added a condition check for backing store flag, for an
- * existing file can be opened for read and write now.
+ * existing file can be opened for read and write now.
*-------------------------------------------------------------------------
*/
/* ARGSUSED */
@@ -898,3 +937,63 @@ H5FD_core_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing)
done:
FUNC_LEAVE_NOAPI(ret_value)
}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_core_truncate
+ *
+ * Purpose: Makes sure that the true file size is the same (or larger)
+ * than the end-of-address.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, October 7, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static herr_t
+H5FD_core_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t UNUSED closing)
+{
+ H5FD_core_t *file = (H5FD_core_t*)_file;
+ size_t new_eof; /* New size of memory buffer */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5FD_core_truncate, FAIL)
+
+ HDassert(file);
+
+ /* Determine new size of memory buffer */
+ H5_ASSIGN_OVERFLOW(new_eof, file->increment * (file->eoa / file->increment), hsize_t, size_t);
+ if(file->eoa % file->increment)
+ new_eof += file->increment;
+
+ /* Extend the file to make sure it's large enough */
+ if(!H5F_addr_eq((haddr_t)new_eof, file->eof)) {
+ unsigned char *x; /* Pointer to new buffer for file data */
+
+ /* (Re)allocate memory for the file buffer */
+ if(NULL == (x = (unsigned char *)H5MM_realloc(file->mem, new_eof)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory block")
+#ifdef H5_CLEAR_MEMORY
+if(file->eof < new_eof)
+ HDmemset(x + file->eof, 0, (size_t)(new_eof - file->eof));
+#endif /* H5_CLEAR_MEMORY */
+ file->mem = x;
+
+ /* Update backing store, if using it */
+ if(file->fd >= 0 && file->backing_store) {
+ if(-1 == HDftruncate(file->fd, (off_t)new_eof))
+ HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
+ } /* end if */
+
+ /* Update the eof value */
+ file->eof = new_eof;
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_core_truncate() */
+
diff --git a/src/H5FDdirect.c b/src/H5FDdirect.c
index 23ff0fe..61eb318 100644
--- a/src/H5FDdirect.c
+++ b/src/H5FDdirect.c
@@ -18,7 +18,7 @@
* Wednesday, 20 September 2006
*
* Purpose: The Direct I/O file driver forces the data to be written to
- * the file directly without being copied into system kernel
+ * the file directly without being copied into system kernel
* buffer. The main system support this feature is Linux.
*/
@@ -163,14 +163,14 @@ static herr_t H5FD_direct_close(H5FD_t *_file);
static int H5FD_direct_cmp(const H5FD_t *_f1, const H5FD_t *_f2);
static herr_t H5FD_direct_query(const H5FD_t *_f1, unsigned long *flags);
static haddr_t H5FD_direct_get_eoa(const H5FD_t *_file, H5FD_mem_t type);
-static herr_t H5FD_direct_set_eoa(H5FD_t *_file, H5FD_mem_t UNUSED type, haddr_t addr);
+static herr_t H5FD_direct_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t addr);
static haddr_t H5FD_direct_get_eof(const H5FD_t *_file);
static herr_t H5FD_direct_get_handle(H5FD_t *_file, hid_t fapl, void** file_handle);
static herr_t H5FD_direct_read(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr,
size_t size, void *buf);
static herr_t H5FD_direct_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr,
size_t size, const void *buf);
-static herr_t H5FD_direct_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing);
+static herr_t H5FD_direct_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
static const H5FD_class_t H5FD_direct_g = {
"direct", /*name */
@@ -190,6 +190,7 @@ static const H5FD_class_t H5FD_direct_g = {
H5FD_direct_close, /*close */
H5FD_direct_cmp, /*cmp */
H5FD_direct_query, /*query */
+ NULL, /*get_type_map */
NULL, /*alloc */
NULL, /*free */
H5FD_direct_get_eoa, /*get_eoa */
@@ -198,7 +199,8 @@ static const H5FD_class_t H5FD_direct_g = {
H5FD_direct_get_handle, /*get_handle */
H5FD_direct_read, /*read */
H5FD_direct_write, /*write */
- H5FD_direct_flush, /*flush */
+ NULL, /*flush */
+ H5FD_direct_truncate, /*truncate */
NULL, /*lock */
NULL, /*unlock */
H5FD_FLMAP_SINGLE /*fl_map */
@@ -255,7 +257,7 @@ H5FD_direct_init(void)
FUNC_ENTER_NOAPI(H5FD_direct_init, FAIL)
if (H5I_VFL!=H5I_get_type(H5FD_DIRECT_g))
- H5FD_DIRECT_g = H5FD_register(&H5FD_direct_g,sizeof(H5FD_class_t));
+ H5FD_DIRECT_g = H5FD_register(&H5FD_direct_g,sizeof(H5FD_class_t),FALSE);
/* Set return value */
ret_value=H5FD_DIRECT_g;
@@ -322,7 +324,7 @@ H5Pset_fapl_direct(hid_t fapl_id, size_t boundary, size_t block_size, size_t cbu
if(boundary != 0)
fa.mboundary = boundary;
- else
+ else
fa.mboundary = MBOUNDARY_DEF;
if(block_size != 0)
fa.fbsize = block_size;
@@ -365,7 +367,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5Pget_fapl_direct(hid_t fapl_id, size_t *boundary/*out*/, size_t *block_size/*out*/,
+H5Pget_fapl_direct(hid_t fapl_id, size_t *boundary/*out*/, size_t *block_size/*out*/,
size_t *cbuf_size/*out*/)
{
H5FD_direct_fapl_t *fa;
@@ -573,7 +575,7 @@ H5FD_direct_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxadd
if(write(file->fd, (void*)buf1, sizeof(int))<0) {
if(write(file->fd, (void*)buf2, file->fa.fbsize)<0)
HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, NULL, "file system may not support Direct I/O")
- else
+ else
file->fa.must_align = TRUE;
} else {
file->fa.must_align = FALSE;
@@ -583,7 +585,7 @@ H5FD_direct_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxadd
if(read(file->fd, (void*)buf1, sizeof(int))<0) {
if(read(file->fd, (void*)buf2, file->fa.fbsize)<0)
HGOTO_ERROR(H5E_FILE, H5E_READERROR, NULL, "file system may not support Direct I/O")
- else
+ else
file->fa.must_align = TRUE;
} else
file->fa.must_align = FALSE;
@@ -929,20 +931,20 @@ H5FD_direct_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, ha
if (addr+size>file->eoa)
HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "addr overflow")
- /* If the system doesn't require data to be aligned, read the data in
+ /* If the system doesn't require data to be aligned, read the data in
* the same way as sec2 driver.
*/
_must_align = file->fa.must_align;
- /* Get the memory boundary for alignment, file system block size, and maximal
+ /* Get the memory boundary for alignment, file system block size, and maximal
* copy buffer size.
*/
_boundary = file->fa.mboundary;
_fbsize = file->fa.fbsize;
_cbsize = file->fa.cbsize;
- /* if the data is aligned or the system doesn't require data to be aligned,
- * read it directly from the file. If not, read a bigger
+ /* if the data is aligned or the system doesn't require data to be aligned,
+ * read it directly from the file. If not, read a bigger
* and aligned data first, then copy the data into memory buffer.
*/
if(!_must_align || ((addr%_fbsize==0) && (size%_fbsize==0) && ((size_t)buf%_boundary==0))) {
@@ -950,7 +952,7 @@ H5FD_direct_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, ha
if ((addr!=file->pos || OP_READ!=file->op) &&
file_seek(file->fd, (file_offset_t)addr, SEEK_SET)<0)
HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position")
- /* Read the aligned data in file first, being careful of interrupted
+ /* Read the aligned data in file first, being careful of interrupted
* system calls and partial results. */
while (size>0) {
do {
@@ -972,11 +974,11 @@ H5FD_direct_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, ha
buf = (char*)buf + nbytes;
}
} else {
- /* allocate memory needed for the Direct IO option up to the maximal
- * copy buffer size. Make a bigger buffer for aligned I/O if size is
+ /* allocate memory needed for the Direct IO option up to the maximal
+ * copy buffer size. Make a bigger buffer for aligned I/O if size is
* smaller than maximal copy buffer. */
if(size < _cbsize)
- alloc_size = (size / _fbsize + 1) * _fbsize + _fbsize;
+ alloc_size = ((size / _fbsize) * _fbsize) + _fbsize;
else
alloc_size = _cbsize;
if (HDposix_memalign(&copy_buf, _boundary, alloc_size) != 0)
@@ -987,15 +989,15 @@ H5FD_direct_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, ha
HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position")
/*
- * Read the aligned data in file into aligned buffer first, then copy the data
+ * Read the aligned data in file into aligned buffer first, then copy the data
* into the final buffer. If the data size is bigger than maximal copy buffer
* size, do the reading by segment (the outer while loop). If not, do one step
- * reading.
+ * reading.
*/
p3 = buf;
do {
- /* Read the aligned data in file first. Not able to handle interrupted
- * system calls and partial results like sec2 driver does because the
+ /* Read the aligned data in file first. Not able to handle interrupted
+ * system calls and partial results like sec2 driver does because the
* data may no longer be aligned. It's expecially true when the data in
* file is smaller than ALLOC_SIZE. */
HDmemset(copy_buf, 0, alloc_size);
@@ -1008,7 +1010,7 @@ H5FD_direct_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, ha
HSYS_GOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file read failed")
/* look for the right position and copy the data to the original buffer.
- * Consider all possible situations here: file address is not aligned on
+ * Consider all possible situations here: file address is not aligned on
* file block size; the end of data address is not aligned; the end of data
* address is aligned; data size is smaller or bigger than maximal copy size.*/
p2 = (unsigned char*)copy_buf + (size_t)(copy_addr % _fbsize);
@@ -1018,7 +1020,7 @@ H5FD_direct_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, ha
HDmemcpy(p3, p2, copy_size);
else if(size >= _cbsize && copy_size > (alloc_size-(size_t)(copy_addr%_fbsize))) {
HDmemcpy(p3, p2, (alloc_size - (size_t)(copy_addr % _fbsize)));
- p3 = (unsigned char*)p3 + (alloc_size - (size_t)(copy_addr % _fbsize));
+ p3 = (unsigned char*)p3 + (alloc_size - (size_t)(copy_addr % _fbsize));
}
/* update the size and address of data being read. */
@@ -1099,20 +1101,20 @@ H5FD_direct_write(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, h
if (addr+size>file->eoa)
HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "addr overflow")
- /* If the system doesn't require data to be aligned, read the data in
+ /* If the system doesn't require data to be aligned, read the data in
* the same way as sec2 driver.
*/
_must_align = file->fa.must_align;
- /* Get the memory boundary for alignment, file system block size, and maximal
+ /* Get the memory boundary for alignment, file system block size, and maximal
* copy buffer size.
*/
_boundary = file->fa.mboundary;
_fbsize = file->fa.fbsize;
_cbsize = file->fa.cbsize;
- /* if the data is aligned or the system doesn't require data to be aligned,
- * write it directly to the file. If not, read a bigger and aligned data
+ /* if the data is aligned or the system doesn't require data to be aligned,
+ * write it directly to the file. If not, read a bigger and aligned data
* first, update buffer with user data, then write the data out.
*/
if(!_must_align || ((addr%_fbsize==0) && (size%_fbsize==0) && ((size_t)buf%_boundary==0))) {
@@ -1140,8 +1142,8 @@ H5FD_direct_write(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, h
* copy buffer size. Make a bigger buffer for aligned I/O if size is
* smaller than maximal copy buffer.
*/
- if(size < _cbsize)
- alloc_size = (size / _fbsize + 1) * _fbsize + _fbsize;
+ if(size < _cbsize)
+ alloc_size = ((size / _fbsize) * _fbsize) + _fbsize;
else
alloc_size = _cbsize;
@@ -1156,8 +1158,8 @@ H5FD_direct_write(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, h
do {
/*
* Read the aligned data first if the aligned region doesn't fall
- * entirely in the range to be writen. Not able to handle interrupted
- * system calls and partial results like sec2 driver does because the
+ * entirely in the range to be writen. Not able to handle interrupted
+ * system calls and partial results like sec2 driver does because the
* data may no longer be aligned. It's expecially true when the data in
* file is smaller than ALLOC_SIZE.
*/
@@ -1172,7 +1174,7 @@ H5FD_direct_write(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, h
HSYS_GOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file read failed")
}
- /* look for the right position and append or copy the data to be written to
+ /* look for the right position and append or copy the data to be written to
* the aligned buffer.
* Consider all possible situations here: file address is not aligned on
* file block size; the end of data address is not aligned; the end of data
@@ -1187,13 +1189,13 @@ H5FD_direct_write(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, h
HDmemcpy(p1, p3, (alloc_size - (size_t)(copy_addr % _fbsize)));
p3 = (unsigned char*)p3 + (alloc_size - (size_t)(copy_addr % _fbsize));
}
-
+
/*look for the aligned position for writing the data*/
if(file_seek(file->fd, (file_offset_t)(copy_addr - copy_addr % _fbsize), SEEK_SET) < 0)
HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position")
/*
- * Write the data. It doesn't truncate the extra data introduced by
+ * Write the data. It doesn't truncate the extra data introduced by
* alignment because that step is done in H5FD_direct_flush.
*/
do {
@@ -1215,7 +1217,7 @@ H5FD_direct_write(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, h
/*Update the address and size*/
addr += (haddr_t)size;
buf = (const char*)buf + size;
-
+
if(copy_buf)
HDfree(copy_buf);
}
@@ -1238,7 +1240,7 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5FD_direct_flush
+ * Function: H5FD_direct_truncate
*
* Purpose: Makes sure that the true file size is the same (or larger)
* than the end-of-address.
@@ -1250,17 +1252,15 @@ done:
* Programmer: Raymond Lu
* Thursday, 21 September 2006
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static herr_t
-H5FD_direct_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing)
+H5FD_direct_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t UNUSED closing)
{
H5FD_direct_t *file = (H5FD_direct_t*)_file;
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5FD_direct_flush, FAIL)
+ FUNC_ENTER_NOAPI(H5FD_direct_truncate, FAIL)
assert(file);
@@ -1290,16 +1290,17 @@ H5FD_direct_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing)
/* Reset last file I/O information */
file->pos = HADDR_UNDEF;
file->op = OP_UNKNOWN;
- }
- else if (file->fa.must_align){
+ }
+ else if (file->fa.must_align){
/*Even though eof is equal to eoa, file is still truncated because Direct I/O
*write introduces some extra data for alignment.
*/
if (-1==file_truncate(file->fd, (file_offset_t)file->eof))
HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
}
-
+
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_direct_truncate() */
#endif /* H5_HAVE_DIRECT */
+
diff --git a/src/H5FDdirect.h b/src/H5FDdirect.h
index 79886e7..26c70f3 100644
--- a/src/H5FDdirect.h
+++ b/src/H5FDdirect.h
@@ -43,9 +43,9 @@ extern "C" {
H5_DLL hid_t H5FD_direct_init(void);
H5_DLL void H5FD_direct_term(void);
-H5_DLL herr_t H5Pset_fapl_direct(hid_t fapl_id, size_t alignment, size_t block_size,
+H5_DLL herr_t H5Pset_fapl_direct(hid_t fapl_id, size_t alignment, size_t block_size,
size_t cbuf_size);
-H5_DLL herr_t H5Pget_fapl_direct(hid_t fapl_id, size_t *boundary/*out*/,
+H5_DLL herr_t H5Pget_fapl_direct(hid_t fapl_id, size_t *boundary/*out*/,
size_t *block_size/*out*/, size_t *cbuf_size/*out*/);
#ifdef __cplusplus
diff --git a/src/H5FDfamily.c b/src/H5FDfamily.c
index 34360e5..cfad5e3 100644
--- a/src/H5FDfamily.c
+++ b/src/H5FDfamily.c
@@ -107,6 +107,7 @@ static herr_t H5FD_family_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, ha
static herr_t H5FD_family_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr,
size_t size, const void *_buf);
static herr_t H5FD_family_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing);
+static herr_t H5FD_family_truncate(H5FD_t *_file, hid_t dxpl_id, unsigned closing);
/* The class struct */
static const H5FD_class_t H5FD_family_g = {
@@ -127,6 +128,7 @@ static const H5FD_class_t H5FD_family_g = {
H5FD_family_close, /*close */
H5FD_family_cmp, /*cmp */
H5FD_family_query, /*query */
+ NULL, /*get_type_map */
NULL, /*alloc */
NULL, /*free */
H5FD_family_get_eoa, /*get_eoa */
@@ -136,6 +138,7 @@ static const H5FD_class_t H5FD_family_g = {
H5FD_family_read, /*read */
H5FD_family_write, /*write */
H5FD_family_flush, /*flush */
+ H5FD_family_truncate, /*truncate */
NULL, /*lock */
NULL, /*unlock */
H5FD_FLMAP_SINGLE /*fl_map */
@@ -189,7 +192,7 @@ H5FD_family_init(void)
FUNC_ENTER_NOAPI(H5FD_family_init, FAIL)
if (H5I_VFL!=H5Iget_type(H5FD_FAMILY_g))
- H5FD_FAMILY_g = H5FD_register(&H5FD_family_g,sizeof(H5FD_class_t));
+ H5FD_FAMILY_g = H5FD_register(&H5FD_family_g,sizeof(H5FD_class_t),FALSE);
/* Set return value */
ret_value=H5FD_FAMILY_g;
@@ -277,7 +280,7 @@ H5Pset_fapl_family(hid_t fapl_id, hsize_t msize, hid_t memb_fapl_id)
fa.memb_size = msize;
fa.memb_fapl_id = memb_fapl_id;
- if(NULL == (plist = H5I_object(fapl_id)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")
ret_value= H5P_set_driver(plist, H5FD_FAMILY, &fa);
@@ -321,16 +324,16 @@ H5Pget_fapl_family(hid_t fapl_id, hsize_t *msize/*out*/,
if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access list")
- if (H5FD_FAMILY!=H5P_get_driver(plist))
+ if(H5FD_FAMILY != H5P_get_driver(plist))
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "incorrect VFL driver")
- if (NULL==(fa=H5P_get_driver_info(plist)))
+ if(NULL == (fa = (H5FD_family_fapl_t *)H5P_get_driver_info(plist)))
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "bad VFL driver info")
- if (msize)
+ if(msize)
*msize = fa->memb_size;
- if (memb_fapl_id) {
- if(NULL == (plist = H5I_object(fa->memb_fapl_id)))
+ if(memb_fapl_id) {
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(fa->memb_fapl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access list")
- *memb_fapl_id = H5P_copy_plist(plist);
+ *memb_fapl_id = H5P_copy_plist(plist, TRUE);
} /* end if */
done:
@@ -365,13 +368,13 @@ H5FD_family_fapl_get(H5FD_t *_file)
FUNC_ENTER_NOAPI(H5FD_family_fapl_get, NULL)
- if (NULL==(fa=H5MM_calloc(sizeof(H5FD_family_fapl_t))))
+ if(NULL == (fa = (H5FD_family_fapl_t *)H5MM_calloc(sizeof(H5FD_family_fapl_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
fa->memb_size = file->memb_size;
- if(NULL == (plist = H5I_object(file->memb_fapl_id)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(file->memb_fapl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list")
- fa->memb_fapl_id = H5P_copy_plist(plist);
+ fa->memb_fapl_id = H5P_copy_plist(plist, FALSE);
/* Set return value */
ret_value=fa;
@@ -411,7 +414,7 @@ H5FD_family_fapl_copy(const void *_old_fa)
FUNC_ENTER_NOAPI(H5FD_family_fapl_copy, NULL)
- if (NULL==(new_fa=H5MM_malloc(sizeof(H5FD_family_fapl_t))))
+ if(NULL == (new_fa = (H5FD_family_fapl_t *)H5MM_malloc(sizeof(H5FD_family_fapl_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Copy the fields of the structure */
@@ -419,13 +422,13 @@ H5FD_family_fapl_copy(const void *_old_fa)
/* Deep copy the property list objects in the structure */
if(old_fa->memb_fapl_id==H5P_FILE_ACCESS_DEFAULT) {
- if(H5I_inc_ref(new_fa->memb_fapl_id)<0)
+ if(H5I_inc_ref(new_fa->memb_fapl_id, FALSE)<0)
HGOTO_ERROR(H5E_VFL, H5E_CANTINC, NULL, "unable to increment ref count on VFL driver")
} /* end if */
else {
- if(NULL == (plist = H5I_object(old_fa->memb_fapl_id)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(old_fa->memb_fapl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list")
- new_fa->memb_fapl_id = H5P_copy_plist(plist);
+ new_fa->memb_fapl_id = H5P_copy_plist(plist, FALSE);
} /* end else */
/* Set return value */
@@ -464,7 +467,7 @@ H5FD_family_fapl_free(void *_fa)
FUNC_ENTER_NOAPI(H5FD_family_fapl_free, FAIL)
- if(H5I_dec_ref(fa->memb_fapl_id)<0)
+ if(H5I_dec_ref(fa->memb_fapl_id, FALSE)<0)
HGOTO_ERROR(H5E_VFL, H5E_CANTDEC, FAIL, "can't close driver ID")
H5MM_xfree(fa);
@@ -499,19 +502,19 @@ H5FD_family_dxpl_copy(const void *_old_dx)
FUNC_ENTER_NOAPI(H5FD_family_dxpl_copy, NULL)
- if (NULL==(new_dx=H5MM_malloc(sizeof(H5FD_family_dxpl_t))))
+ if(NULL == (new_dx = (H5FD_family_dxpl_t *)H5MM_malloc(sizeof(H5FD_family_dxpl_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- memcpy(new_dx, old_dx, sizeof(H5FD_family_dxpl_t));
+ HDmemcpy(new_dx, old_dx, sizeof(H5FD_family_dxpl_t));
- if(old_dx->memb_dxpl_id==H5P_DATASET_XFER_DEFAULT) {
- if(H5I_inc_ref(new_dx->memb_dxpl_id)<0)
+ if(old_dx->memb_dxpl_id == H5P_DATASET_XFER_DEFAULT) {
+ if(H5I_inc_ref(new_dx->memb_dxpl_id, FALSE)<0)
HGOTO_ERROR(H5E_VFL, H5E_CANTINC, NULL, "unable to increment ref count on VFL driver")
} /* end if */
else {
- if(NULL == (plist = H5I_object(old_dx->memb_dxpl_id)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(old_dx->memb_dxpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list")
- new_dx->memb_dxpl_id = H5P_copy_plist(plist);
+ new_dx->memb_dxpl_id = H5P_copy_plist(plist, FALSE);
} /* end else */
/* Set return value */
@@ -550,7 +553,7 @@ H5FD_family_dxpl_free(void *_dx)
FUNC_ENTER_NOAPI(H5FD_family_dxpl_free, FAIL)
- if(H5I_dec_ref(dx->memb_dxpl_id)<0)
+ if(H5I_dec_ref(dx->memb_dxpl_id, FALSE)<0)
HGOTO_ERROR(H5E_VFL, H5E_CANTDEC, FAIL, "can't close driver ID")
H5MM_xfree(dx);
@@ -740,27 +743,29 @@ H5FD_family_open(const char *name, unsigned flags, hid_t fapl_id,
FUNC_ENTER_NOAPI(H5FD_family_open, NULL)
/* Check arguments */
- if (!name || !*name)
+ if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid file name")
- if (0==maxaddr || HADDR_UNDEF==maxaddr)
+ if(0 == maxaddr || HADDR_UNDEF == maxaddr)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "bogus maxaddr")
/* Initialize file from file access properties */
- if (NULL==(file=H5MM_calloc(sizeof(H5FD_family_t))))
+ if(NULL == (file = (H5FD_family_t *)H5MM_calloc(sizeof(H5FD_family_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate file struct")
- if (H5P_FILE_ACCESS_DEFAULT==fapl_id) {
+ if(H5P_FILE_ACCESS_DEFAULT==fapl_id) {
file->memb_fapl_id = H5P_FILE_ACCESS_DEFAULT;
- if(H5I_inc_ref(file->memb_fapl_id)<0)
+ if(H5I_inc_ref(file->memb_fapl_id, FALSE) < 0)
HGOTO_ERROR(H5E_VFL, H5E_CANTINC, NULL, "unable to increment ref count on VFL driver")
- file->memb_size = 1024*1024*1024; /*1GB. Actual member size to be updated later */
- file->pmem_size = 1024*1024*1024; /*1GB. Member size passed in through property */
+ file->memb_size = 1024 * 1024 * 1024; /*1GB. Actual member size to be updated later */
+ file->pmem_size = 1024 * 1024 * 1024; /*1GB. Member size passed in through property */
file->mem_newsize = 0; /*New member size used by h5repart only */
- } else {
+ } /* end if */
+ else {
H5FD_family_fapl_t *fa;
- if(NULL == (plist = H5I_object(fapl_id)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list")
- fa = H5P_get_driver_info(plist);
+ fa = (H5FD_family_fapl_t *)H5P_get_driver_info(plist);
+ HDassert(fa);
/* New family file size. It's used by h5repart only. */
if(H5P_exist_plist(plist, H5F_ACS_FAMILY_NEWSIZE_NAME) > 0)
@@ -768,19 +773,19 @@ H5FD_family_open(const char *name, unsigned flags, hid_t fapl_id,
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get new family member size")
if(fa->memb_fapl_id==H5P_FILE_ACCESS_DEFAULT) {
- if(H5I_inc_ref(fa->memb_fapl_id)<0)
+ if(H5I_inc_ref(fa->memb_fapl_id, FALSE)<0)
HGOTO_ERROR(H5E_VFL, H5E_CANTINC, NULL, "unable to increment ref count on VFL driver")
file->memb_fapl_id = fa->memb_fapl_id;
} /* end if */
else {
- if(NULL == (plist = H5I_object(fa->memb_fapl_id)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(fa->memb_fapl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list")
- file->memb_fapl_id = H5P_copy_plist(plist);
+ file->memb_fapl_id = H5P_copy_plist(plist, FALSE);
} /* end else */
file->memb_size = fa->memb_size; /* Actual member size to be updated later */
file->pmem_size = fa->memb_size; /* Member size passed in through property */
file->mem_newsize = fam_newsize; /* New member size passed in through property */
- }
+ } /* end else */
file->name = H5MM_strdup(name);
file->flags = flags;
@@ -792,19 +797,19 @@ H5FD_family_open(const char *name, unsigned flags, hid_t fapl_id,
HGOTO_ERROR(H5E_FILE, H5E_FILEEXISTS, NULL, "file names not unique")
/* Open all the family members */
- while (1) {
+ while(1) {
sprintf(memb_name, name, file->nmembs);
/* Enlarge member array */
- if (file->nmembs>=file->amembs) {
- unsigned n = MAX(64, 2*file->amembs);
- H5FD_t **x = H5MM_realloc(file->memb, n*sizeof(H5FD_t*));
+ if(file->nmembs >= file->amembs) {
+ unsigned n = MAX(64, 2 * file->amembs);
+ H5FD_t **x = (H5FD_t **)H5MM_realloc(file->memb, n * sizeof(H5FD_t *));
- if (!x)
+ if(!x)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to reallocate members")
file->amembs = n;
file->memb = x;
- }
+ } /* end if */
/*
* Attempt to open file. If the first file cannot be opened then fail;
@@ -849,7 +854,7 @@ done:
if (file->memb)
H5MM_xfree(file->memb);
- if(H5I_dec_ref(file->memb_fapl_id)<0)
+ if(H5I_dec_ref(file->memb_fapl_id, FALSE)<0)
HDONE_ERROR(H5E_VFL, H5E_CANTDEC, NULL, "can't close driver ID")
if (file->name)
H5MM_xfree(file->name);
@@ -901,7 +906,7 @@ H5FD_family_close(H5FD_t *_file)
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close member files")
/* Clean up other stuff */
- if(H5I_dec_ref(file->memb_fapl_id)<0)
+ if(H5I_dec_ref(file->memb_fapl_id, FALSE)<0)
HGOTO_ERROR(H5E_VFL, H5E_CANTDEC, FAIL, "can't close driver ID")
if (file->memb)
H5MM_xfree(file->memb);
@@ -972,24 +977,22 @@ done:
static herr_t
H5FD_family_query(const H5FD_t UNUSED * _f, unsigned long *flags /* out */)
{
- herr_t ret_value=SUCCEED;
+ herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(H5FD_family_query, FAIL)
/* Set the VFL feature flags that this driver supports */
if(flags) {
- *flags=0;
- *flags|=H5FD_FEAT_AGGREGATE_METADATA; /* OK to aggregate metadata allocations */
- /**flags|=H5FD_FEAT_ACCUMULATE_METADATA;*/ /* OK to accumulate metadata for faster writes.
- * - Turn it off temporarily because there's a bug
- * when trying to flush metadata during closing. */
- *flags|=H5FD_FEAT_DATA_SIEVE; /* OK to perform data sieving for faster raw data reads & writes */
- *flags|=H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */
- }
+ *flags = 0;
+ *flags |= H5FD_FEAT_AGGREGATE_METADATA; /* OK to aggregate metadata allocations */
+ *flags |= H5FD_FEAT_ACCUMULATE_METADATA; /* OK to accumulate metadata for faster writes. */
+ *flags |= H5FD_FEAT_DATA_SIEVE; /* OK to perform data sieving for faster raw data reads & writes */
+ *flags |= H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */
+ } /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_family_query() */
/*-------------------------------------------------------------------------
@@ -1049,56 +1052,59 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5FD_family_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t eoa)
+H5FD_family_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t abs_eoa)
{
H5FD_family_t *file = (H5FD_family_t*)_file;
- haddr_t addr=eoa;
+ haddr_t addr = abs_eoa;
char memb_name[4096];
- unsigned u; /* Local index variable */
- herr_t ret_value=SUCCEED; /* Return value */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5FD_family_set_eoa, FAIL)
- for (u=0; addr || u<file->nmembs; u++) {
+ for(u = 0; addr || u < file->nmembs; u++) {
/* Enlarge member array */
- if (u>=file->amembs) {
- unsigned n = MAX(64, 2*file->amembs);
- H5FD_t **x = H5MM_realloc(file->memb, n*sizeof(H5FD_t*));
- if (!x)
+ if(u >= file->amembs) {
+ unsigned n = MAX(64, 2 * file->amembs);
+ H5FD_t **x = (H5FD_t **)H5MM_realloc(file->memb, n * sizeof(H5FD_t *));
+
+ if(!x)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory block")
file->amembs = n;
file->memb = x;
file->nmembs = u;
- }
+ } /* end if */
/* Create another file if necessary */
- if (u>=file->nmembs || !file->memb[u]) {
+ if(u >= file->nmembs || !file->memb[u]) {
file->nmembs = MAX(file->nmembs, u+1);
sprintf(memb_name, file->name, u);
H5E_BEGIN_TRY {
- H5_CHECK_OVERFLOW(file->memb_size,hsize_t,haddr_t);
- file->memb[u] = H5FDopen(memb_name, file->flags|H5F_ACC_CREAT,
+ H5_CHECK_OVERFLOW(file->memb_size, hsize_t, haddr_t);
+ file->memb[u] = H5FDopen(memb_name, file->flags | H5F_ACC_CREAT,
file->memb_fapl_id, (haddr_t)file->memb_size);
} H5E_END_TRY;
- if (NULL==file->memb[u])
+ if(NULL == file->memb[u])
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to open member file")
- }
+ } /* end if */
/* Set the EOA marker for the member */
- H5_CHECK_OVERFLOW(file->memb_size,hsize_t,haddr_t);
- if (addr>(haddr_t)file->memb_size) {
- if(H5FD_set_eoa(file->memb[u], type, (haddr_t)file->memb_size)<0)
+ /* (Note compensating for base address addition in internal routine) */
+ H5_CHECK_OVERFLOW(file->memb_size, hsize_t, haddr_t);
+ if(addr > (haddr_t)file->memb_size) {
+ if(H5FD_set_eoa(file->memb[u], type, ((haddr_t)file->memb_size - file->pub.base_addr)) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to set file eoa")
addr -= file->memb_size;
- } else {
- if(H5FD_set_eoa(file->memb[u], type, addr)<0)
+ } /* end if */
+ else {
+ if(H5FD_set_eoa(file->memb[u], type, (addr - file->pub.base_addr)) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to set file eoa")
addr = 0;
- }
- }
+ } /* end else */
+ } /* end for */
- file->eoa = eoa;
+ file->eoa = abs_eoa;
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1139,13 +1145,16 @@ H5FD_family_get_eof(const H5FD_t *_file)
* with `i' equal to that member. If all members have zero EOF then exit
* loop with i==0.
*/
- assert(file->nmembs>0);
- for (i=(int)file->nmembs-1; i>=0; --i) {
- if ((eof=H5FD_get_eof(file->memb[i]))!=0)
+ HDassert(file->nmembs > 0);
+ for(i = (int)file->nmembs - 1; i >= 0; --i) {
+ if((eof = H5FD_get_eof(file->memb[i])) != 0)
break;
- if (0==i)
+ if(0 == i)
break;
- }
+ } /* end for */
+
+ /* Adjust for base address for file */
+ eof += file->pub.base_addr;
/*
* The file size is the number of members before the i'th member plus the
@@ -1154,7 +1163,7 @@ H5FD_family_get_eof(const H5FD_t *_file)
eof += ((unsigned)i)*file->memb_size;
/* Set return value */
- ret_value=MAX(eof, file->eoa);
+ ret_value = MAX(eof, file->eoa);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1192,7 +1201,7 @@ H5FD_family_get_handle(H5FD_t *_file, hid_t fapl, void** file_handle)
if(H5P_get(plist, H5F_ACS_FAMILY_OFFSET_NAME, &offset) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get offset for family driver")
- if(offset>(file->memb_size*file->nmembs))
+ if(offset > (file->memb_size * file->nmembs))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "offset is bigger than file size")
memb = (int)(offset/file->memb_size);
@@ -1242,18 +1251,18 @@ H5FD_family_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, si
* Get the member data transfer property list. If the transfer property
* list does not belong to this driver then assume defaults
*/
- if(NULL == (plist = H5I_object(dxpl_id)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")
- if (H5P_DATASET_XFER_DEFAULT!=dxpl_id && H5FD_FAMILY==H5P_get_driver(plist)) {
- H5FD_family_dxpl_t *dx = H5P_get_driver_info(plist);
+ if(H5P_DATASET_XFER_DEFAULT != dxpl_id && H5FD_FAMILY == H5P_get_driver(plist)) {
+ H5FD_family_dxpl_t *dx = (H5FD_family_dxpl_t *)H5P_get_driver_info(plist);
- assert(TRUE==H5P_isa_class(dxpl_id, H5P_DATASET_XFER));
+ HDassert(TRUE == H5P_isa_class(dxpl_id, H5P_DATASET_XFER));
assert(dx);
memb_dxpl_id = dx->memb_dxpl_id;
- }
+ } /* end if */
/* Read from each member */
- while (size>0) {
+ while(size > 0) {
H5_ASSIGN_OVERFLOW(u,addr /file->memb_size,hsize_t,unsigned);
sub = addr % file->memb_size;
@@ -1311,7 +1320,7 @@ H5FD_family_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, s
hsize_t tempreq;
unsigned u; /* Local index variable */
H5P_genplist_t *plist; /* Property list pointer */
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5FD_family_write, FAIL)
@@ -1319,15 +1328,15 @@ H5FD_family_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, s
* Get the member data transfer property list. If the transfer property
* list does not belong to this driver then assume defaults.
*/
- if(NULL == (plist = H5I_object(dxpl_id)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")
- if (H5P_DATASET_XFER_DEFAULT!=dxpl_id && H5FD_FAMILY==H5P_get_driver(plist)) {
- H5FD_family_dxpl_t *dx = H5P_get_driver_info(plist);
+ if(H5P_DATASET_XFER_DEFAULT != dxpl_id && H5FD_FAMILY == H5P_get_driver(plist)) {
+ H5FD_family_dxpl_t *dx = (H5FD_family_dxpl_t *)H5P_get_driver_info(plist);
- assert(TRUE==H5P_isa_class(dxpl_id, H5P_DATASET_XFER));
- assert(dx);
+ HDassert(TRUE == H5P_isa_class(dxpl_id, H5P_DATASET_XFER));
+ HDassert(dx);
memb_dxpl_id = dx->memb_dxpl_id;
- }
+ } /* end if */
/* Write to each member */
while (size>0) {
@@ -1364,32 +1373,65 @@ done:
* Purpose: Flushes all family members.
*
* Return: Success: 0
- *
* Failure: -1, as many files flushed as possible.
*
* Programmer: Robb Matzke
* Wednesday, August 4, 1999
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static herr_t
H5FD_family_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing)
{
H5FD_family_t *file = (H5FD_family_t*)_file;
- unsigned u, nerrors=0;
- herr_t ret_value=SUCCEED; /* Return value */
+ unsigned u, nerrors = 0;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5FD_family_flush, FAIL)
- for (u=0; u<file->nmembs; u++)
- if (file->memb[u] && H5FD_flush(file->memb[u], dxpl_id, closing)<0)
+ for(u = 0; u < file->nmembs; u++)
+ if(file->memb[u] && H5FD_flush(file->memb[u], dxpl_id, closing) < 0)
nerrors++;
- if (nerrors)
+ if(nerrors)
HGOTO_ERROR(H5E_IO, H5E_BADVALUE, FAIL, "unable to flush member files")
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_family_flush() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_family_truncate
+ *
+ * Purpose: Truncates all family members.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1, as many files truncated as possible.
+ *
+ * Programmer: Quincey Koziol
+ * Saturday, February 23, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_family_truncate(H5FD_t *_file, hid_t dxpl_id, unsigned closing)
+{
+ H5FD_family_t *file = (H5FD_family_t*)_file;
+ unsigned u, nerrors = 0;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5FD_family_truncate, FAIL)
+
+ for(u = 0; u < file->nmembs; u++)
+ if(file->memb[u] && H5FD_truncate(file->memb[u], dxpl_id, closing) < 0)
+ nerrors++;
+
+ if(nerrors)
+ HGOTO_ERROR(H5E_IO, H5E_BADVALUE, FAIL, "unable to flush member files")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_family_truncate() */
+
diff --git a/src/H5FDint.c b/src/H5FDint.c
new file mode 100644
index 0000000..aa375e2
--- /dev/null
+++ b/src/H5FDint.c
@@ -0,0 +1,297 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5FDint.c
+ * Jan 17 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: Internal routine for VFD operations
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5FD_PACKAGE /*suppress error about including H5FDpkg */
+
+/* Interface initialization */
+#define H5_INTERFACE_INIT_FUNC H5FD_int_init_interface
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fprivate.h" /* File access */
+#include "H5FDpkg.h" /* File Drivers */
+#include "H5Iprivate.h" /* IDs */
+#include "H5Pprivate.h" /* Property lists */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+
+/*--------------------------------------------------------------------------
+NAME
+ H5FD_int_init_interface -- Initialize interface-specific information
+USAGE
+ herr_t H5FD_int_init_interface()
+
+RETURNS
+ Non-negative on success/Negative on failure
+DESCRIPTION
+ Initializes any interface-specific data or routines. (Just calls
+ H5FD_init_iterface currently).
+
+--------------------------------------------------------------------------*/
+static herr_t
+H5FD_int_init_interface(void)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_int_init_interface)
+
+ FUNC_LEAVE_NOAPI(H5FD_init())
+} /* H5FD_int_init_interface() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_read
+ *
+ * Purpose: Private version of H5FDread()
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, August 4, 1999
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FD_read(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr,
+ size_t size, void *buf/*out*/)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5FD_read, FAIL)
+
+ HDassert(file && file->cls);
+ HDassert(H5I_GENPROP_LST == H5I_get_type(dxpl_id));
+ HDassert(TRUE == H5P_isa_class(dxpl_id, H5P_DATASET_XFER));
+ HDassert(buf);
+
+#ifndef H5_HAVE_PARALLEL
+ /* Do not return early for Parallel mode since the I/O could be a */
+ /* collective transfer. */
+ /* The no-op case */
+ if(0 == size)
+ HGOTO_DONE(SUCCEED)
+#endif /* H5_HAVE_PARALLEL */
+
+ /* Dispatch to driver */
+ if((file->cls->read)(file, type, dxpl_id, addr + file->base_addr, size, buf) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read request failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_read() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_write
+ *
+ * Purpose: Private version of H5FDwrite()
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, August 4, 1999
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FD_write(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr,
+ size_t size, const void *buf)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5FD_write, FAIL)
+
+ HDassert(file && file->cls);
+ HDassert(H5I_GENPROP_LST == H5I_get_type(dxpl_id));
+ HDassert(TRUE == H5P_isa_class(dxpl_id, H5P_DATASET_XFER));
+ HDassert(buf);
+
+#ifndef H5_HAVE_PARALLEL
+ /* Do not return early for Parallel mode since the I/O could be a */
+ /* collective transfer. */
+ /* The no-op case */
+ if(0 == size)
+ HGOTO_DONE(SUCCEED)
+#endif /* H5_HAVE_PARALLEL */
+
+ /* Dispatch to driver */
+ if((file->cls->write)(file, type, dxpl_id, addr + file->base_addr, size, buf) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "driver write request failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_write() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_set_eoa
+ *
+ * Purpose: Private version of H5FDset_eoa()
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative, no side effect
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, August 4, 1999
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FD_set_eoa(H5FD_t *file, H5FD_mem_t type, haddr_t addr)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5FD_set_eoa, FAIL)
+
+ HDassert(file && file->cls);
+ HDassert(H5F_addr_defined(addr) && addr <= file->maxaddr);
+
+ /* Dispatch to driver */
+ if((file->cls->set_eoa)(file, type, addr + file->base_addr) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver set_eoa request failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_set_eoa() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_get_eoa
+ *
+ * Purpose: Private version of H5FDget_eoa()
+ *
+ * Return: Success: First byte after allocated memory.
+ * Failure: HADDR_UNDEF
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, August 4, 1999
+ *
+ *-------------------------------------------------------------------------
+ */
+haddr_t
+H5FD_get_eoa(const H5FD_t *file, H5FD_mem_t type)
+{
+ haddr_t ret_value;
+
+ FUNC_ENTER_NOAPI(H5FD_get_eoa, HADDR_UNDEF)
+
+ HDassert(file && file->cls);
+
+ /* Dispatch to driver */
+ if(HADDR_UNDEF == (ret_value = (file->cls->get_eoa)(file, type)))
+ HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "driver get_eoa request failed")
+
+ /* Adjust for base address in file */
+ ret_value -= file->base_addr;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_get_eoa() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_get_eof
+ *
+ * Purpose: Private version of H5FDget_eof()
+ *
+ * Return: Success: The EOF address.
+ *
+ * Failure: HADDR_UNDEF
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, August 4, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+haddr_t
+H5FD_get_eof(const H5FD_t *file)
+{
+ haddr_t ret_value;
+
+ FUNC_ENTER_NOAPI(H5FD_get_eof, HADDR_UNDEF)
+
+ HDassert(file && file->cls);
+
+ /* Dispatch to driver */
+ if(file->cls->get_eof) {
+ if(HADDR_UNDEF == (ret_value = (file->cls->get_eof)(file)))
+ HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "driver get_eof request failed")
+ } /* end if */
+ else
+ ret_value = file->maxaddr;
+
+ /* Adjust for base address in file */
+ ret_value -= file->base_addr;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_get_eof() */
+
diff --git a/src/H5FDlog.c b/src/H5FDlog.c
index 3109e09..f7eb349 100644
--- a/src/H5FDlog.c
+++ b/src/H5FDlog.c
@@ -190,8 +190,9 @@ static herr_t H5FD_log_read(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr
size_t size, void *buf);
static herr_t H5FD_log_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr,
size_t size, const void *buf);
-static herr_t H5FD_log_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing);
+static herr_t H5FD_log_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
+#ifdef OLD_WAY
/*
* The free list map which causes each request type to use no free lists
*/
@@ -204,6 +205,7 @@ static herr_t H5FD_log_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing);
H5FD_MEM_NOLIST, /*lheap*/ \
H5FD_MEM_NOLIST /*ohdr*/ \
}
+#endif /* OLD_WAY */
static const H5FD_class_t H5FD_log_g = {
"log", /*name */
@@ -223,6 +225,7 @@ static const H5FD_class_t H5FD_log_g = {
H5FD_log_close, /*close */
H5FD_log_cmp, /*cmp */
H5FD_log_query, /*query */
+ NULL, /*get_type_map */
H5FD_log_alloc, /*alloc */
NULL, /*free */
H5FD_log_get_eoa, /*get_eoa */
@@ -231,10 +234,11 @@ static const H5FD_class_t H5FD_log_g = {
H5FD_log_get_handle, /*get_handle */
H5FD_log_read, /*read */
H5FD_log_write, /*write */
- H5FD_log_flush, /*flush */
+ NULL, /*flush */
+ H5FD_log_truncate, /*truncate */
NULL, /*lock */
NULL, /*unlock */
- H5FD_FLMAP_NOLIST /*fl_map */
+ H5FD_FLMAP_SINGLE /*fl_map */
};
@@ -285,7 +289,7 @@ H5FD_log_init(void)
FUNC_ENTER_NOAPI(H5FD_log_init, FAIL)
if (H5I_VFL!=H5Iget_type(H5FD_LOG_g))
- H5FD_LOG_g = H5FD_register(&H5FD_log_g,sizeof(H5FD_class_t));
+ H5FD_LOG_g = H5FD_register(&H5FD_log_g,sizeof(H5FD_class_t),FALSE);
/* Set return value */
ret_value=H5FD_LOG_g;
@@ -354,14 +358,14 @@ H5Pset_fapl_log(hid_t fapl_id, const char *logfile, unsigned flags, size_t buf_s
if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")
- fa.logfile=(char*)logfile;
- fa.flags=flags;
- fa.buf_size=buf_size;
- ret_value= H5P_set_driver(plist, H5FD_LOG, &fa);
+ fa.logfile = (char *)logfile;
+ fa.flags = flags;
+ fa.buf_size = buf_size;
+ ret_value = H5P_set_driver(plist, H5FD_LOG, &fa);
done:
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5Pset_fapl_log() */
/*-------------------------------------------------------------------------
@@ -419,12 +423,12 @@ static void *
H5FD_log_fapl_copy(const void *_old_fa)
{
const H5FD_log_fapl_t *old_fa = (const H5FD_log_fapl_t*)_old_fa;
- H5FD_log_fapl_t *new_fa = H5MM_malloc(sizeof(H5FD_log_fapl_t));
+ H5FD_log_fapl_t *new_fa = (H5FD_log_fapl_t *)H5MM_malloc(sizeof(H5FD_log_fapl_t));
void *ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5FD_log_fapl_copy, NULL)
- assert(new_fa);
+ HDassert(new_fa);
/* Copy the general information */
HDmemcpy(new_fa, old_fa, sizeof(H5FD_log_fapl_t));
@@ -533,16 +537,17 @@ H5FD_log_open(const char *name, unsigned flags, hid_t fapl_id,
HGOTO_ERROR(H5E_FILE, H5E_BADFILE, NULL, "unable to fstat file")
/* Create the new file struct */
- if (NULL==(file=H5MM_calloc(sizeof(H5FD_log_t))))
+ if(NULL == (file = (H5FD_log_t *)H5MM_calloc(sizeof(H5FD_log_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate file struct")
/* Get the driver specific information */
if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list")
- fa = H5P_get_driver_info(plist);
+ fa = (H5FD_log_fapl_t *)H5P_get_driver_info(plist);
+ HDassert(fa);
file->fd = fd;
- H5_ASSIGN_OVERFLOW(file->eof,sb.st_size,h5_stat_size_t,haddr_t);
+ H5_ASSIGN_OVERFLOW(file->eof, sb.st_size, h5_stat_size_t, haddr_t);
file->pos = HADDR_UNDEF;
file->op = OP_UNKNOWN;
#ifdef _WIN32
@@ -559,32 +564,32 @@ H5FD_log_open(const char *name, unsigned flags, hid_t fapl_id,
file->fa.flags=fa->flags;
/* Check if we are doing any logging at all */
- if(file->fa.flags!=0) {
- file->iosize=fa->buf_size;
- if(file->fa.flags&H5FD_LOG_FILE_READ) {
- file->nread=H5MM_calloc(file->iosize);
- assert(file->nread);
+ if(file->fa.flags != 0) {
+ file->iosize = fa->buf_size;
+ if(file->fa.flags & H5FD_LOG_FILE_READ) {
+ file->nread = (unsigned char *)H5MM_calloc(file->iosize);
+ HDassert(file->nread);
} /* end if */
- if(file->fa.flags&H5FD_LOG_FILE_WRITE) {
- file->nwrite=H5MM_calloc(file->iosize);
- assert(file->nwrite);
+ if(file->fa.flags & H5FD_LOG_FILE_WRITE) {
+ file->nwrite = (unsigned char *)H5MM_calloc(file->iosize);
+ HDassert(file->nwrite);
} /* end if */
- if(file->fa.flags&H5FD_LOG_FLAVOR) {
- file->flavor=H5MM_calloc(file->iosize);
- assert(file->flavor);
+ if(file->fa.flags & H5FD_LOG_FLAVOR) {
+ file->flavor = (unsigned char *)H5MM_calloc(file->iosize);
+ HDassert(file->flavor);
} /* end if */
if(fa->logfile)
- file->logfp=HDfopen(fa->logfile,"w");
+ file->logfp = HDfopen(fa->logfile, "w");
else
- file->logfp=stderr;
+ file->logfp = stderr;
} /* end if */
/* Set return value */
- ret_value=(H5FD_t*)file;
+ ret_value = (H5FD_t*)file;
done:
- if(ret_value==NULL) {
- if(fd>=0)
+ if(NULL == ret_value) {
+ if(fd >= 0)
HDclose(fd);
} /* end if */
@@ -624,7 +629,7 @@ H5FD_log_close(H5FD_t *_file)
if(file->fa.flags&H5FD_LOG_TIME_CLOSE)
HDgettimeofday(&timeval_start,NULL);
#endif /* H5_HAVE_GETTIMEOFDAY */
- if (close(file->fd)<0)
+ if (HDclose(file->fd)<0)
HGOTO_ERROR(H5E_IO, H5E_CANTCLOSEFILE, FAIL, "unable to close file")
#ifdef H5_HAVE_GETTIMEOFDAY
if(file->fa.flags&H5FD_LOG_TIME_CLOSE)
@@ -702,13 +707,13 @@ H5FD_log_close(H5FD_t *_file)
} /* end if */
/* Free the logging information */
- if(file->fa.flags&H5FD_LOG_FILE_WRITE)
- file->nwrite=H5MM_xfree(file->nwrite);
- if(file->fa.flags&H5FD_LOG_FILE_READ)
- file->nread=H5MM_xfree(file->nread);
- if(file->fa.flags&H5FD_LOG_FLAVOR)
- file->flavor=H5MM_xfree(file->flavor);
- if(file->logfp!=stderr)
+ if(file->fa.flags & H5FD_LOG_FILE_WRITE)
+ file->nwrite = (unsigned char *)H5MM_xfree(file->nwrite);
+ if(file->fa.flags & H5FD_LOG_FILE_READ)
+ file->nread = (unsigned char *)H5MM_xfree(file->nread);
+ if(file->fa.flags & H5FD_LOG_FLAVOR)
+ file->flavor = (unsigned char *)H5MM_xfree(file->flavor);
+ if(file->logfp != stderr)
fclose(file->logfp);
} /* end if */
@@ -1299,35 +1304,32 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5FD_log_flush
+ * Function: H5FD_log_truncate
*
* Purpose: Makes sure that the true file size is the same (or larger)
* than the end-of-address.
*
* Return: Success: Non-negative
- *
* Failure: Negative
*
* Programmer: Robb Matzke
* Wednesday, August 4, 1999
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
/* ARGSUSED */
static herr_t
-H5FD_log_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing)
+H5FD_log_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing)
{
H5FD_log_t *file = (H5FD_log_t*)_file;
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5FD_log_flush, FAIL)
+ FUNC_ENTER_NOAPI(H5FD_log_truncate, FAIL)
if(file->eoa>file->eof) {
if(-1 == file_seek(file->fd, (file_offset_t)(file->eoa - 1), SEEK_SET))
HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position")
- if(write(file->fd, "", (size_t)1) != 1)
+ if(HDwrite(file->fd, "", (size_t)1) != 1)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
file->eof = file->eoa;
file->pos = file->eoa;
@@ -1336,4 +1338,5 @@ H5FD_log_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing)
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_log_truncate() */
+
diff --git a/src/H5FDmpi.h b/src/H5FDmpi.h
index 90aa0e2..b9998dd 100644
--- a/src/H5FDmpi.h
+++ b/src/H5FDmpi.h
@@ -22,8 +22,8 @@
#ifndef H5FDmpi_H
#define H5FDmpi_H
-/***** Macros for One linked collective IO case. *****/
-/* The default value to do one linked collective IO for all chunks.
+/***** Macros for One linked collective IO case. *****/
+/* The default value to do one linked collective IO for all chunks.
If the average number of chunks per process is greater than this value,
the library will create an MPI derived datatype to link all chunks to do collective IO.
The user can set this value through an API. */
@@ -42,14 +42,14 @@ typedef enum H5FD_mpio_xfer_t {
H5FD_MPIO_COLLECTIVE
} H5FD_mpio_xfer_t;
-/* Type of I/O for data transfer properties */
+/* Type of chunked dataset I/O */
typedef enum H5FD_mpio_chunk_opt_t {
H5FD_MPIO_CHUNK_DEFAULT = 0,
H5FD_MPIO_CHUNK_ONE_IO, /*zero is the default*/
H5FD_MPIO_CHUNK_MULTI_IO
} H5FD_mpio_chunk_opt_t;
-/* Type of I/O for data transfer properties */
+/* Type of collective I/O */
typedef enum H5FD_mpio_collective_opt_t {
H5FD_MPIO_COLLECTIVE_IO = 0,
H5FD_MPIO_INDIVIDUAL_IO /*zero is the default*/
@@ -120,3 +120,4 @@ H5_DLL MPI_Comm H5FD_mpi_get_comm(const H5FD_t *_file);
#endif /* H5_HAVE_PARALLEL */
#endif /* H5FDmpi_H */
+
diff --git a/src/H5FDmpio.c b/src/H5FDmpio.c
index 5d5f092..57da069 100644
--- a/src/H5FDmpio.c
+++ b/src/H5FDmpio.c
@@ -82,6 +82,7 @@ static herr_t H5FD_mpio_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, hadd
static herr_t H5FD_mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr,
size_t size, const void *buf);
static herr_t H5FD_mpio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing);
+static herr_t H5FD_mpio_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
static int H5FD_mpio_mpi_rank(const H5FD_t *_file);
static int H5FD_mpio_mpi_size(const H5FD_t *_file);
static MPI_Comm H5FD_mpio_communicator(const H5FD_t *_file);
@@ -112,6 +113,7 @@ static const H5FD_class_mpi_t H5FD_mpio_g = {
H5FD_mpio_close, /*close */
NULL, /*cmp */
H5FD_mpio_query, /*query */
+ NULL, /*get_type_map */
NULL, /*alloc */
NULL, /*free */
H5FD_mpio_get_eoa, /*get_eoa */
@@ -121,6 +123,7 @@ static const H5FD_class_mpi_t H5FD_mpio_g = {
H5FD_mpio_read, /*read */
H5FD_mpio_write, /*write */
H5FD_mpio_flush, /*flush */
+ H5FD_mpio_truncate, /*truncate */
NULL, /*lock */
NULL, /*unlock */
H5FD_FLMAP_SINGLE /*fl_map */
@@ -201,7 +204,7 @@ H5FD_mpio_init(void)
FUNC_ENTER_NOAPI(H5FD_mpio_init, FAIL)
if (H5I_VFL!=H5I_get_type(H5FD_MPIO_g))
- H5FD_MPIO_g = H5FD_register((const H5FD_class_t *)&H5FD_mpio_g,sizeof(H5FD_class_mpi_t));
+ H5FD_MPIO_g = H5FD_register((const H5FD_class_t *)&H5FD_mpio_g,sizeof(H5FD_class_mpi_t),FALSE);
#ifdef H5FDmpio_DEBUG
if (!H5FD_mpio_Debug_inited)
@@ -322,13 +325,13 @@ H5Pset_fapl_mpio(hid_t fapl_id, MPI_Comm comm, MPI_Info info)
FUNC_ENTER_API(H5Pset_fapl_mpio, FAIL)
H5TRACE3("e", "iMcMi", fapl_id, comm, info);
- if(fapl_id==H5P_DEFAULT)
+ if(fapl_id == H5P_DEFAULT)
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list")
/* Check arguments */
- if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS)))
+ if(NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS)))
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a file access list")
- if (MPI_COMM_NULL == comm)
+ if(MPI_COMM_NULL == comm)
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a valid communicator")
/* Initialize driver specific properties */
@@ -393,11 +396,11 @@ H5Pget_fapl_mpio(hid_t fapl_id, MPI_Comm *comm/*out*/, MPI_Info *info/*out*/)
FUNC_ENTER_API(H5Pget_fapl_mpio, FAIL)
H5TRACE3("e", "ixx", fapl_id, comm, info);
- if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS)))
+ if(NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS)))
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a file access list")
- if (H5FD_MPIO!=H5P_get_driver(plist))
+ if(H5FD_MPIO != H5P_get_driver(plist))
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "incorrect VFL driver")
- if (NULL==(fa=H5P_get_driver_info(plist)))
+ if(NULL == (fa = (H5FD_mpio_fapl_t *)H5P_get_driver_info(plist)))
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "bad VFL driver info")
/* Store the duplicated communicator in a temporary variable for error */
@@ -471,9 +474,9 @@ H5Pset_dxpl_mpio(hid_t dxpl_id, H5FD_mpio_xfer_t xfer_mode)
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list")
/* Check arguments */
- if(NULL == (plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER)))
+ if(NULL == (plist = H5P_object_verify(dxpl_id, H5P_DATASET_XFER)))
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl")
- if (H5FD_MPIO_INDEPENDENT!=xfer_mode && H5FD_MPIO_COLLECTIVE!=xfer_mode)
+ if(H5FD_MPIO_INDEPENDENT != xfer_mode && H5FD_MPIO_COLLECTIVE != xfer_mode)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "incorrect xfer_mode")
/* Set the transfer mode */
@@ -517,9 +520,9 @@ H5Pget_dxpl_mpio(hid_t dxpl_id, H5FD_mpio_xfer_t *xfer_mode/*out*/)
FUNC_ENTER_API(H5Pget_dxpl_mpio, FAIL)
H5TRACE2("e", "ix", dxpl_id, xfer_mode);
- if(NULL == (plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER)))
+ if(NULL == (plist = H5P_object_verify(dxpl_id, H5P_DATASET_XFER)))
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl")
- if (H5FD_MPIO!=H5P_get_driver(plist))
+ if(H5FD_MPIO != H5P_get_driver(plist))
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "incorrect VFL driver")
/* Get the transfer mode */
@@ -544,14 +547,14 @@ Description:
The library won't behave as it asks for only when we find
that the low-level MPI-IO package doesn't support this.
-Parameters:
+Parameters:
hid_t dxpl_id in: Data transfer property list identifier
H5FD_mpio_chunk_opt_t in: The optimization flag for linked chunk IO
or multi-chunk IO.
-
-Returns:
-Returns a non-negative value if successful. Otherwise returns a negative value.
+
+Returns:
+Returns a non-negative value if successful. Otherwise returns a negative value.
*
*-------------------------------------------------------------------------
*/
@@ -563,25 +566,24 @@ H5Pset_dxpl_mpio_collective_opt(hid_t dxpl_id, H5FD_mpio_collective_opt_t opt_mo
FUNC_ENTER_API(H5Pset_dxpl_mpio_collective_opt, FAIL)
H5TRACE2("e", "iDc", dxpl_id, opt_mode);
-/* H5TRACE2("e","iDt",dxpl_id,xfer_mode);*/
- if(dxpl_id==H5P_DEFAULT)
+ if(dxpl_id == H5P_DEFAULT)
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list")
/* Check arguments */
- if(NULL == (plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER)))
+ if(NULL == (plist = H5P_object_verify(dxpl_id, H5P_DATASET_XFER)))
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl")
/* Set the transfer mode */
- if (H5P_set(plist,H5D_XFER_MPIO_COLLECTIVE_OPT_NAME,&opt_mode)<0)
+ if(H5P_set(plist, H5D_XFER_MPIO_COLLECTIVE_OPT_NAME, &opt_mode) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set value")
/* Initialize driver-specific properties */
- ret_value= H5P_set_driver(plist, H5FD_MPIO, NULL);
+ ret_value = H5P_set_driver(plist, H5FD_MPIO, NULL);
done:
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5Pset_dxpl_mpio_collective_opt() */
/*-------------------------------------------------------------------------
@@ -597,14 +599,14 @@ Description:
The library won't behave as it asks for only when we find
that the low-level MPI-IO package doesn't support this.
-Parameters:
+Parameters:
hid_t dxpl_id in: Data transfer property list identifier
H5FD_mpio_chunk_opt_t in: The optimization flag for linked chunk IO
or multi-chunk IO.
-
-Returns:
-Returns a non-negative value if successful. Otherwise returns a negative value.
+
+Returns:
+Returns a non-negative value if successful. Otherwise returns a negative value.
*
*-------------------------------------------------------------------------
*/
@@ -616,13 +618,12 @@ H5Pset_dxpl_mpio_chunk_opt(hid_t dxpl_id, H5FD_mpio_chunk_opt_t opt_mode)
FUNC_ENTER_API(H5Pset_dxpl_mpio_chunk_opt, FAIL)
H5TRACE2("e", "iDh", dxpl_id, opt_mode);
-/* H5TRACE2("e","iDt",dxpl_id,xfer_mode);*/
- if(dxpl_id==H5P_DEFAULT)
+ if(dxpl_id == H5P_DEFAULT)
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list")
/* Check arguments */
- if(NULL == (plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER)))
+ if(NULL == (plist = H5P_object_verify(dxpl_id, H5P_DATASET_XFER)))
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl")
/* Set the transfer mode */
@@ -645,15 +646,15 @@ Purpose:
To set a threshold for doing linked chunk IO
Description:
- If the number is greater than the threshold set by the user,
+ If the number is greater than the threshold set by the user,
the library will do linked chunk IO; otherwise, IO will be done for every chunk.
-Parameters:
+Parameters:
hid_t dxpl_id in: Data transfer property list identifier
- unsigned num_proc_per_chunk in: the threshold of the average number of chunks selected by each process
+ unsigned num_proc_per_chunk in: the threshold of the average number of chunks selected by each process
-Returns:
-Returns a non-negative value if successful. Otherwise returns a negative value.
+Returns:
+Returns a non-negative value if successful. Otherwise returns a negative value.
*
*-------------------------------------------------------------------------
*/
@@ -666,11 +667,11 @@ H5Pset_dxpl_mpio_chunk_opt_num(hid_t dxpl_id, unsigned num_chunk_per_proc)
FUNC_ENTER_API(H5Pset_dxpl_mpio_chunk_opt_num, FAIL)
H5TRACE2("e", "iIu", dxpl_id, num_chunk_per_proc);
- if(dxpl_id==H5P_DEFAULT)
+ if(dxpl_id == H5P_DEFAULT)
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list")
/* Check arguments */
- if(NULL == (plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER)))
+ if(NULL == (plist = H5P_object_verify(dxpl_id, H5P_DATASET_XFER)))
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl")
/* Set the transfer mode */
@@ -692,13 +693,13 @@ Purpose:
To set a threshold for doing collective IO for each chunk
Description:
The library will calculate the percentage of the number of process holding selections at each chunk. If that percentage of number of process in the individual chunk is greater than the threshold set by the user, the library will do collective chunk IO for this chunk; otherwise, independent IO will be done for this chunk.
-Parameters:
- hid_t dxpl_id
+Parameters:
+ hid_t dxpl_id
in: Data transfer property list identifier
- unsigned percent_num_proc_per_chunk
+ unsigned percent_num_proc_per_chunk
in: the threshold of the percentage of the number of process holding selections per chunk
-Returns:
-Returns a non-negative value if successful. Otherwise returns a negative value.
+Returns:
+Returns a non-negative value if successful. Otherwise returns a negative value.
*
@@ -713,11 +714,11 @@ H5Pset_dxpl_mpio_chunk_opt_ratio(hid_t dxpl_id, unsigned percent_num_proc_per_ch
FUNC_ENTER_API(H5Pset_dxpl_mpio_chunk_opt_ratio, FAIL)
H5TRACE2("e", "iIu", dxpl_id, percent_num_proc_per_chunk);
- if(dxpl_id==H5P_DEFAULT)
+ if(dxpl_id == H5P_DEFAULT)
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list")
/* Check arguments */
- if(NULL == (plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER)))
+ if(NULL == (plist = H5P_object_verify(dxpl_id, H5P_DATASET_XFER)))
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl")
/* Set the transfer mode */
@@ -761,19 +762,18 @@ H5FD_mpio_fapl_get(H5FD_t *_file)
FUNC_ENTER_NOAPI(H5FD_mpio_fapl_get, NULL)
- assert(file);
- assert(H5FD_MPIO==file->pub.driver_id);
+ HDassert(file);
+ HDassert(H5FD_MPIO == file->pub.driver_id);
- if (NULL==(fa=H5MM_calloc(sizeof(H5FD_mpio_fapl_t))))
+ if(NULL == (fa = (H5FD_mpio_fapl_t *)H5MM_calloc(sizeof(H5FD_mpio_fapl_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Duplicate communicator and Info object. */
- if (FAIL==H5FD_mpi_comm_info_dup(file->comm, file->info,
- &fa->comm, &fa->info))
+ if(FAIL == H5FD_mpi_comm_info_dup(file->comm, file->info, &fa->comm, &fa->info))
HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOPY, NULL, "Communicator/Info duplicate failed")
/* Set return value */
- ret_value=fa;
+ ret_value = fa;
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -809,15 +809,14 @@ if (H5FD_mpio_Debug[(int)'t'])
fprintf(stderr, "enter H5FD_mpio_fapl_copy\n");
#endif
- if (NULL==(new_fa=H5MM_malloc(sizeof(H5FD_mpio_fapl_t))))
+ if(NULL == (new_fa = (H5FD_mpio_fapl_t *)H5MM_malloc(sizeof(H5FD_mpio_fapl_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Copy the general information */
HDmemcpy(new_fa, old_fa, sizeof(H5FD_mpio_fapl_t));
/* Duplicate communicator and Info object. */
- if (FAIL==H5FD_mpi_comm_info_dup(old_fa->comm, old_fa->info,
- &new_fa->comm, &new_fa->info))
+ if(FAIL == H5FD_mpi_comm_info_dup(old_fa->comm, old_fa->info, &new_fa->comm, &new_fa->info))
HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOPY, NULL, "Communicator/Info duplicate failed")
ret_value = new_fa;
@@ -945,7 +944,7 @@ H5FD_mpio_open(const char *name, unsigned flags, hid_t fapl_id,
#ifndef H5_HAVE_MPI_GET_SIZE
struct stat stat_buf;
#endif
-
+
FUNC_ENTER_NOAPI(H5FD_mpio_open, NULL)
#ifdef H5FDmpio_DEBUG
@@ -956,14 +955,14 @@ H5FD_mpio_open(const char *name, unsigned flags, hid_t fapl_id,
#endif
/* Obtain a pointer to mpio-specific file access properties */
- if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS)))
+ if(NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list")
- if (H5P_FILE_ACCESS_DEFAULT==fapl_id || H5FD_MPIO!=H5P_get_driver(plist)) {
+ if(H5P_FILE_ACCESS_DEFAULT == fapl_id || H5FD_MPIO != H5P_get_driver(plist)) {
_fa.comm = MPI_COMM_SELF; /*default*/
_fa.info = MPI_INFO_NULL; /*default*/
fa = &_fa;
} else {
- fa = H5P_get_driver_info(plist);
+ fa = (const H5FD_mpio_fapl_t *)H5P_get_driver_info(plist);
assert(fa);
}
@@ -998,7 +997,7 @@ H5FD_mpio_open(const char *name, unsigned flags, hid_t fapl_id,
#endif
/*OKAY: CAST DISCARDS CONST*/
- if (MPI_SUCCESS != (mpi_code=MPI_File_open(comm_dup, (char*)name, mpi_amode, info_dup, &fh)))
+ if(MPI_SUCCESS != (mpi_code = MPI_File_open(comm_dup, (char*)name, mpi_amode, info_dup, &fh)))
HMPI_GOTO_ERROR(NULL, "MPI_File_open failed", mpi_code)
file_opened=1;
@@ -1009,7 +1008,7 @@ H5FD_mpio_open(const char *name, unsigned flags, hid_t fapl_id,
HMPI_GOTO_ERROR(NULL, "MPI_Comm_size failed", mpi_code)
/* Build the return value and initialize it */
- if (NULL==(file=H5MM_calloc(sizeof(H5FD_mpio_t))))
+ if(NULL == (file = (H5FD_mpio_t *)H5MM_calloc(sizeof(H5FD_mpio_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
file->f = fh;
file->comm = comm_dup;
@@ -1020,7 +1019,7 @@ H5FD_mpio_open(const char *name, unsigned flags, hid_t fapl_id,
/* Only processor p0 will get the filesize and broadcast it. */
if (mpi_rank == 0) {
/* Get current file size. If MPI_File_get_size is disabled in configuration
- * because it doesn't return correct value (SGI Altix Propack 4),
+ * because it doesn't return correct value (SGI Altix Propack 4),
* use stat to get the file size. */
#ifdef H5_HAVE_MPI_GET_SIZE
if (MPI_SUCCESS != (mpi_code=MPI_File_get_size(fh, &size)))
@@ -1034,7 +1033,7 @@ H5FD_mpio_open(const char *name, unsigned flags, hid_t fapl_id,
} /* end if */
/* Broadcast file size */
- if (MPI_SUCCESS != (mpi_code=MPI_Bcast(&size, sizeof(MPI_Offset), MPI_BYTE, 0, comm_dup)))
+ if(MPI_SUCCESS != (mpi_code = MPI_Bcast(&size, (int)sizeof(MPI_Offset), MPI_BYTE, 0, comm_dup)))
HMPI_GOTO_ERROR(NULL, "MPI_Bcast failed", mpi_code)
/* Determine if the file should be truncated */
@@ -1417,8 +1416,8 @@ H5FD_mpio_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t dxpl_id, haddr_t add
int type_size; /* MPI datatype used for I/O's size */
int io_size; /* Actual number of bytes requested */
H5P_genplist_t *plist; /* Property list pointer */
- unsigned use_view_this_time=0;
- herr_t ret_value=SUCCEED;
+ hbool_t use_view_this_time = FALSE;
+ herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(H5FD_mpio_read, FAIL)
@@ -1454,9 +1453,9 @@ H5FD_mpio_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t dxpl_id, haddr_t add
H5FD_mpio_xfer_t xfer_mode; /* I/O tranfer mode */
/* Obtain the data transfer properties */
- if(NULL == (plist = H5I_object(dxpl_id)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")
- xfer_mode=(H5FD_mpio_xfer_t)H5P_peek_unsigned(plist, H5D_XFER_IO_XFER_MODE_NAME);
+ xfer_mode = (H5FD_mpio_xfer_t)H5P_peek_unsigned(plist, H5D_XFER_IO_XFER_MODE_NAME);
/*
* Set up for a fancy xfer using complex types, or single byte block. We
@@ -1468,7 +1467,7 @@ H5FD_mpio_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t dxpl_id, haddr_t add
MPI_Datatype file_type;
/* Remember that views are used */
- use_view_this_time=TRUE;
+ use_view_this_time = TRUE;
/* prepare for a full-blown xfer using btype, ftype, and disp */
if(H5P_get(plist,H5FD_MPI_XFER_MEM_MPI_TYPE_NAME,&buf_type)<0)
@@ -1491,47 +1490,42 @@ H5FD_mpio_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t dxpl_id, haddr_t add
} /* end if */
/* Read the data. */
- if (use_view_this_time) {
+ if(use_view_this_time) {
H5FD_mpio_collective_opt_t coll_opt_mode;
- H5FD_mpio_collective_opt_t xfer_opt_mode;
+
#ifdef H5FDmpio_DEBUG
if (H5FD_mpio_Debug[(int)'t'])
fprintf(stdout, "H5FD_mpio_read: using MPIO collective mode\n");
#endif
/* Peek the collective_opt property to check whether the application wants to do IO individually. */
- coll_opt_mode=(H5FD_mpio_collective_opt_t)H5P_peek_unsigned(plist,H5D_XFER_MPIO_COLLECTIVE_OPT_NAME);
+ coll_opt_mode = (H5FD_mpio_collective_opt_t)H5P_peek_unsigned(plist, H5D_XFER_MPIO_COLLECTIVE_OPT_NAME);
- /* Peek the xfer_opt_mode property to check whether the application wants to do IO individually. */
- xfer_opt_mode=(H5FD_mpio_collective_opt_t)H5P_peek_unsigned(plist,H5D_XFER_IO_XFER_OPT_MODE_NAME);
-
- if(coll_opt_mode == H5FD_MPIO_COLLECTIVE_IO && xfer_opt_mode == H5FD_MPIO_COLLECTIVE_IO) {
+ if(coll_opt_mode == H5FD_MPIO_COLLECTIVE_IO) {
#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'t'])
- fprintf(stdout, "H5FD_mpio_read: doing MPI collective IO\n");
+ if(H5FD_mpio_Debug[(int)'t'])
+ fprintf(stdout, "H5FD_mpio_read: doing MPI collective IO\n");
#endif
-/* Temporarily change to read_at_all
- if (MPI_SUCCESS!= (mpi_code=MPI_File_read_at_all(file->f, mpi_off, buf, size_i, buf_type, &mpi_stat )))*/
- if (MPI_SUCCESS!= (mpi_code=MPI_File_read_at_all(file->f, mpi_off, buf, size_i, buf_type, &mpi_stat )))
- HMPI_GOTO_ERROR(FAIL, "MPI_File_read_at_all failed", mpi_code)
- }
+ if(MPI_SUCCESS != (mpi_code = MPI_File_read_at_all(file->f, mpi_off, buf, size_i, buf_type, &mpi_stat)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_File_read_at_all failed", mpi_code)
+ } /* end if */
else {
#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'t'])
- fprintf(stdout, "H5FD_mpio_read: doing MPI independent IO\n");
+ if(H5FD_mpio_Debug[(int)'t'])
+ fprintf(stdout, "H5FD_mpio_read: doing MPI independent IO\n");
#endif
- if (MPI_SUCCESS!= (mpi_code=MPI_File_read_at(file->f, mpi_off, buf, size_i, buf_type, &mpi_stat )))
- HMPI_GOTO_ERROR(FAIL, "MPI_File_read_at failed", mpi_code)
- }
-
+ if(MPI_SUCCESS != (mpi_code = MPI_File_read_at(file->f, mpi_off, buf, size_i, buf_type, &mpi_stat)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_File_read_at failed", mpi_code)
+ } /* end else */
+
/*
* Reset the file view when we used MPI derived types
*/
/*OKAY: CAST DISCARDS CONST QUALIFIER*/
- if (MPI_SUCCESS != (mpi_code=MPI_File_set_view(file->f, 0, MPI_BYTE, MPI_BYTE, H5FD_mpi_native_g, file->info)))
+ if(MPI_SUCCESS != (mpi_code = MPI_File_set_view(file->f, (MPI_Offset)0, MPI_BYTE, MPI_BYTE, H5FD_mpi_native_g, file->info)))
HMPI_GOTO_ERROR(FAIL, "MPI_File_set_view failed", mpi_code)
} else {
- if (MPI_SUCCESS!= (mpi_code=MPI_File_read_at(file->f, mpi_off, buf, size_i, buf_type, &mpi_stat)))
+ if(MPI_SUCCESS != (mpi_code = MPI_File_read_at(file->f, mpi_off, buf, size_i, buf_type, &mpi_stat)))
HMPI_GOTO_ERROR(FAIL, "MPI_File_read_at failed", mpi_code)
}
@@ -1704,7 +1698,7 @@ H5FD_mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr,
int size_i, bytes_written;
int type_size; /* MPI datatype used for I/O's size */
int io_size; /* Actual number of bytes requested */
- unsigned use_view_this_time=0;
+ hbool_t use_view_this_time = FALSE;
H5P_genplist_t *plist; /* Property list pointer */
herr_t ret_value=SUCCEED;
@@ -1722,26 +1716,25 @@ H5FD_mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr,
assert(buf);
/* Portably initialize MPI status variable */
- HDmemset(&mpi_stat,0,sizeof(MPI_Status));
+ HDmemset(&mpi_stat, 0, sizeof(MPI_Status));
/* some numeric conversions */
- if (H5FD_mpi_haddr_to_MPIOff(addr, &mpi_off)<0)
+ if(H5FD_mpi_haddr_to_MPIOff(addr, &mpi_off) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "can't convert from haddr to MPI off")
size_i = (int)size;
- if ((hsize_t)size_i != size)
+ if((hsize_t)size_i != size)
HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "can't convert from size to size_i")
#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'w'])
- fprintf(stdout, "in H5FD_mpio_write mpi_off=%ld size_i=%d\n",
- (long)mpi_off, size_i);
+ if(H5FD_mpio_Debug[(int)'w'])
+ fprintf(stdout, "in H5FD_mpio_write mpi_off=%ld size_i=%d\n", (long)mpi_off, size_i);
#endif
/* Obtain the data transfer properties */
- if(NULL == (plist = H5I_object(dxpl_id)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")
- if(type==H5FD_MEM_DRAW) {
+ if(type == H5FD_MEM_DRAW) {
H5FD_mpio_xfer_t xfer_mode; /* I/O tranfer mode */
/* Obtain the data transfer properties */
@@ -1753,123 +1746,77 @@ H5FD_mpio_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr,
* us to test that btype=ftype=MPI_BYTE (or even MPI_TYPE_NULL, which
* could mean "use MPI_BYTE" by convention).
*/
- if(xfer_mode==H5FD_MPIO_COLLECTIVE) {
+ if(xfer_mode == H5FD_MPIO_COLLECTIVE) {
MPI_Datatype file_type;
/* Remember that views are used */
- use_view_this_time=TRUE;
+ use_view_this_time = TRUE;
/* prepare for a full-blown xfer using btype, ftype, and disp */
- if(H5P_get(plist,H5FD_MPI_XFER_MEM_MPI_TYPE_NAME,&buf_type)<0)
+ if(H5P_get(plist, H5FD_MPI_XFER_MEM_MPI_TYPE_NAME, &buf_type) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get MPI-I/O type property")
- if(H5P_get(plist,H5FD_MPI_XFER_FILE_MPI_TYPE_NAME,&file_type)<0)
+ if(H5P_get(plist, H5FD_MPI_XFER_FILE_MPI_TYPE_NAME, &file_type) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get MPI-I/O type property")
/*
* Set the file view when we are using MPI derived types
*/
/*OKAY: CAST DISCARDS CONST QUALIFIER*/
- if (MPI_SUCCESS != (mpi_code=MPI_File_set_view(file->f, mpi_off, MPI_BYTE, file_type, H5FD_mpi_native_g, file->info)))
+ if(MPI_SUCCESS != (mpi_code = MPI_File_set_view(file->f, mpi_off, MPI_BYTE, file_type, H5FD_mpi_native_g, file->info)))
HMPI_GOTO_ERROR(FAIL, "MPI_File_set_view failed", mpi_code)
/* When using types, use the address as the displacement for
* MPI_File_set_view and reset the address for the read to zero
*/
- mpi_off=0;
+ mpi_off = 0;
} /* end if */
} /* end if */
else {
- unsigned block_before_meta_write=0; /* Whether to block before a metadata write */
-
- /* Check if we need to syncronize all processes before attempting metadata write
- * (Prevents race condition where the process writing the metadata goes ahead
- * and writes the metadata to the file before all the processes have
- * read the data, "transmitting" data from the "future" to the reading
- * process. -QAK )
- *
- * The only time we don't want to block before a metadata write is when
- * we are flushing out a bunch of metadata. Then, we block before the
- * first write and don't block for further writes in the sequence.
- */
- if(H5P_exist_plist(plist,H5AC_BLOCK_BEFORE_META_WRITE_NAME)>0)
- if(H5P_get(plist,H5AC_BLOCK_BEFORE_META_WRITE_NAME,&block_before_meta_write)<0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get H5AC property")
-
-#if 0 /* JRM */
- /* The metadata cache now only writes from process 0, which makes
- * this synchronization incorrect. I'm leaving this code commented
- * out instead of deleting it to remind us that we should re-write
- * this function so that a metadata write from any other process
- * should flag an error.
- * -- JRM 9/1/05
- */
- if(block_before_meta_write)
- if (MPI_SUCCESS!= (mpi_code=MPI_Barrier(file->comm)))
- HMPI_GOTO_ERROR(FAIL, "MPI_Barrier failed", mpi_code)
-#endif /* JRM */
-
- /* Only one process will do the actual write if all procs in comm write same metadata */
- if (file->mpi_rank != H5_PAR_META_WRITE) {
-#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'w']) {
- fprintf(stdout,
- " proc %d: in H5FD_mpio_write (write omitted)\n",
- file->mpi_rank );
- }
-#endif
+ /* Only one process can do the actual metadata write */
+ if(file->mpi_rank != H5_PAR_META_WRITE)
+#ifdef LATER
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "can't write metadata from non-zero rank")
+#else /* LATER */
HGOTO_DONE(SUCCEED) /* skip the actual write */
- } /* end if */
+#endif /* LATER */
} /* end if */
/* Write the data. */
- if (use_view_this_time) {
- H5FD_mpio_collective_opt_t coll_opt_mode;
- H5FD_mpio_collective_opt_t xfer_opt_mode;
+ if(use_view_this_time) {
+ H5FD_mpio_collective_opt_t coll_opt_mode;
+
#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'t'])
+ if(H5FD_mpio_Debug[(int)'t'])
fprintf(stdout, "H5FD_mpio_write: using MPIO collective mode\n");
#endif
/* Peek the collective_opt property to check whether the application wants to do IO individually. */
- coll_opt_mode=(H5FD_mpio_collective_opt_t)H5P_peek_unsigned(plist,H5D_XFER_MPIO_COLLECTIVE_OPT_NAME);
-
- /* Peek the xfer_opt_mode property to check whether the application wants to do IO individually. */
- xfer_opt_mode=(H5FD_mpio_collective_opt_t)H5P_peek_unsigned(plist,H5D_XFER_IO_XFER_OPT_MODE_NAME);
-
-
+ coll_opt_mode = (H5FD_mpio_collective_opt_t)H5P_peek_unsigned(plist, H5D_XFER_MPIO_COLLECTIVE_OPT_NAME);
/*OKAY: CAST DISCARDS CONST QUALIFIER*/
-
- if(coll_opt_mode == H5FD_MPIO_COLLECTIVE_IO && xfer_opt_mode == H5FD_MPIO_COLLECTIVE_IO ) {
+ if(coll_opt_mode == H5FD_MPIO_COLLECTIVE_IO) {
#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'t'])
- fprintf(stdout, "H5FD_mpio_write: doing MPI collective IO\n");
+ if(H5FD_mpio_Debug[(int)'t'])
+ fprintf(stdout, "H5FD_mpio_write: doing MPI collective IO\n");
#endif
- /* Temporarily change to _at
-if (MPI_SUCCESS != (mpi_code=MPI_File_write_at_all(file->f, mpi_off, (void*)buf, size_i, buf_type, &mpi_stat)))
-*/
- if (MPI_SUCCESS != (mpi_code=MPI_File_write_at_all(file->f, mpi_off, (void*)buf, size_i, buf_type, &mpi_stat)))
- HMPI_GOTO_ERROR(FAIL, "MPI_File_write_at_all failed", mpi_code)
- }
+ if(MPI_SUCCESS != (mpi_code = MPI_File_write_at_all(file->f, mpi_off, (void*)buf, size_i, buf_type, &mpi_stat)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_File_write_at_all failed", mpi_code)
+ } /* end if */
else {
#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'t'])
- fprintf(stdout, "H5FD_mpio_write: doing MPI independent IO\n");
+ if(H5FD_mpio_Debug[(int)'t'])
+ fprintf(stdout, "H5FD_mpio_write: doing MPI independent IO\n");
#endif
-
- if (MPI_SUCCESS != (mpi_code=MPI_File_write_at(file->f, mpi_off, (void*)buf, size_i, buf_type, &mpi_stat)))
- HMPI_GOTO_ERROR(FAIL, "MPI_File_write_at failed", mpi_code)
- }
-
+ if(MPI_SUCCESS != (mpi_code = MPI_File_write_at(file->f, mpi_off, (void*)buf, size_i, buf_type, &mpi_stat)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_File_write_at failed", mpi_code)
+ } /* end else */
- /*
- * Reset the file view when we used MPI derived types
- */
+ /* Reset the file view when we used MPI derived types */
/*OKAY: CAST DISCARDS CONST QUALIFIER*/
- if (MPI_SUCCESS != (mpi_code=MPI_File_set_view(file->f, 0, MPI_BYTE, MPI_BYTE, H5FD_mpi_native_g, file->info)))
+ if(MPI_SUCCESS != (mpi_code = MPI_File_set_view(file->f, (MPI_Offset)0, MPI_BYTE, MPI_BYTE, H5FD_mpi_native_g, file->info)))
HMPI_GOTO_ERROR(FAIL, "MPI_File_set_view failed", mpi_code)
} else {
/*OKAY: CAST DISCARDS CONST QUALIFIER*/
- if (MPI_SUCCESS != (mpi_code=MPI_File_write_at(file->f, mpi_off, (void*)buf, size_i, buf_type, &mpi_stat)))
+ if(MPI_SUCCESS != (mpi_code = MPI_File_write_at(file->f, mpi_off, (void*)buf, size_i, buf_type, &mpi_stat)))
HMPI_GOTO_ERROR(FAIL, "MPI_File_write_at failed", mpi_code)
}
@@ -1879,48 +1826,31 @@ if (MPI_SUCCESS != (mpi_code=MPI_File_write_at_all(file->f, mpi_off, (void*)buf,
* datatype in this call though... (We aren't because using it causes
* the LANL "qsc" machine to dump core - 12/19/03) - QAK]
*/
- if (MPI_SUCCESS != (mpi_code=MPI_Get_elements(&mpi_stat, MPI_BYTE, &bytes_written)))
+ if(MPI_SUCCESS != (mpi_code = MPI_Get_elements(&mpi_stat, MPI_BYTE, &bytes_written)))
HMPI_GOTO_ERROR(FAIL, "MPI_Get_elements failed", mpi_code)
/* Get the type's size */
- if (MPI_SUCCESS != (mpi_code=MPI_Type_size(buf_type,&type_size)))
+ if(MPI_SUCCESS != (mpi_code = MPI_Type_size(buf_type, &type_size)))
HMPI_GOTO_ERROR(FAIL, "MPI_Type_size failed", mpi_code)
/* Compute the actual number of bytes requested */
- io_size=type_size*size_i;
+ io_size = type_size * size_i;
/* Check for write failure */
- if (bytes_written != io_size)
+ if(bytes_written != io_size)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
/* Forget the EOF value (see H5FD_mpio_get_eof()) --rpm 1999-08-06 */
file->eof = HADDR_UNDEF;
done:
-
-#if 0 /* JRM */
- /* Since metadata writes are now done by process 0 only, this broadcast
- * is no longer needed. I leave it in and commented out to remind us
- * that we need to re-work this function to reflect this reallity.
- *
- * -- JRM 9/1/05
- */
- /* if only one process writes, need to broadcast the ret_value to
- * other processes
- */
- if (type!=H5FD_MEM_DRAW) {
- if (MPI_SUCCESS != (mpi_code=MPI_Bcast(&ret_value, sizeof(ret_value), MPI_BYTE, H5_PAR_META_WRITE, file->comm)))
- HMPI_DONE_ERROR(FAIL, "MPI_Bcast failed", mpi_code)
- } /* end if */
-#endif /* JRM */
-
#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'t'])
+ if(H5FD_mpio_Debug[(int)'t'])
fprintf(stdout, "proc %d: Leaving H5FD_mpio_write with ret_value=%d\n",
file->mpi_rank, ret_value );
#endif
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_mpio_write() */
/*-------------------------------------------------------------------------
@@ -1932,68 +1862,106 @@ done:
*
* Failure: Negative
*
- * Programmer: Unknown
+ * Programmer: Robb Matzke
* January 30, 1998
*
- * Modifications:
- * Robb Matzke, 1998-02-18
- * Added the ACCESS_PARMS argument.
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_mpio_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned closing)
+{
+ H5FD_mpio_t *file = (H5FD_mpio_t*)_file;
+ int mpi_code; /* mpi return code */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(H5FD_mpio_flush, FAIL)
+
+#ifdef H5FDmpio_DEBUG
+ if(H5FD_mpio_Debug[(int)'t'])
+ HDfprintf(stdout, "Entering %s\n", FUNC);
+#endif
+ HDassert(file);
+ HDassert(H5FD_MPIO == file->pub.driver_id);
+
+ /* Only sync the file if we are not going to immediately close it */
+ if(!closing) {
+ if(MPI_SUCCESS != (mpi_code = MPI_File_sync(file->f)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_File_sync failed", mpi_code)
+ } /* end if */
+
+done:
+#ifdef H5FDmpio_DEBUG
+ if(H5FD_mpio_Debug[(int)'t'])
+ HDfprintf(stdout, "Leaving %s\n", FUNC);
+#endif
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_mpio_flush() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_mpio_truncate
*
- * Robb Matzke, 1999-08-06
- * Modified to work with the virtual file layer.
+ * Purpose: Make certain the file's size matches it's allocated size
*
- * Robb Matzke, 2000-12-29
- * Make sure file size is at least as large as the last
- * allocated byte.
+ * Return: Success: Non-negative
+ * Failure: Negative
*
- * Quincey Koziol, 2002-06-??
- * Changed file extension method to use MPI_File_set_size instead
- * read->write method.
+ * Programmer: Quincey Koziol
+ * January 31, 2008
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5FD_mpio_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned closing)
+H5FD_mpio_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t closing)
{
H5FD_mpio_t *file = (H5FD_mpio_t*)_file;
- int mpi_code; /* mpi return code */
- MPI_Offset mpi_off;
- herr_t ret_value=SUCCEED;
+ herr_t ret_value = SUCCEED;
- FUNC_ENTER_NOAPI(H5FD_mpio_flush, FAIL)
+ FUNC_ENTER_NOAPI(H5FD_mpio_truncate, FAIL)
#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'t'])
- fprintf(stdout, "Entering H5FD_mpio_flush\n" );
+ if(H5FD_mpio_Debug[(int)'t'])
+ HDfprintf(stdout, "Entering %s\n", FUNC);
#endif
- assert(file);
- assert(H5FD_MPIO==file->pub.driver_id);
+ HDassert(file);
+ HDassert(H5FD_MPIO == file->pub.driver_id);
/* Extend the file to make sure it's large enough, then sync.
* Unfortunately, keeping track of EOF is an expensive operation, so
* we can't just check whether EOF<EOA like with other drivers.
* Therefore we'll just read the byte at EOA-1 and then write it back. */
- if(file->eoa>file->last_eoa) {
+ if(file->eoa > file->last_eoa) {
+ int mpi_code; /* mpi return code */
+ MPI_Offset mpi_off;
+
#ifdef H5_MPI_FILE_SET_SIZE_BIG
- if (H5FD_mpi_haddr_to_MPIOff(file->eoa, &mpi_off)<0)
+ if(H5FD_mpi_haddr_to_MPIOff(file->eoa, &mpi_off) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "cannot convert from haddr_t to MPI_Offset")
/* Extend the file's size */
- if (MPI_SUCCESS != (mpi_code=MPI_File_set_size(file->f, mpi_off)))
+ if(MPI_SUCCESS != (mpi_code = MPI_File_set_size(file->f, mpi_off)))
HMPI_GOTO_ERROR(FAIL, "MPI_File_set_size failed", mpi_code)
#else /* H5_MPI_FILE_SET_SIZE_BIG */
- if (0==file->mpi_rank) {
- uint8_t byte=0;
+ /* Wait until all processes are here before reading/writing the byte at
+ * process 0's end of address space. The window for corruption is
+ * probably tiny, but does exist...
+ */
+ if(MPI_SUCCESS != (mpi_code = MPI_Barrier(file->comm)))
+ HMPI_GOTO_ERROR(FAIL, "MPI_Barrier failed", mpi_code)
+
+ if(0 == file->mpi_rank) {
+ uint8_t byte = 0;
MPI_Status mpi_stat;
/* Portably initialize MPI status variable */
- HDmemset(&mpi_stat,0,sizeof(MPI_Status));
+ HDmemset(&mpi_stat, 0, sizeof(MPI_Status));
- if (H5FD_mpi_haddr_to_MPIOff(file->eoa-1, &mpi_off)<0)
+ if(H5FD_mpi_haddr_to_MPIOff(file->eoa-1, &mpi_off) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL, "cannot convert from haddr_t to MPI_Offset")
- if (MPI_SUCCESS != (mpi_code=MPI_File_read_at(file->f, mpi_off, &byte, 1, MPI_BYTE, &mpi_stat)))
+ if(MPI_SUCCESS != (mpi_code = MPI_File_read_at(file->f, mpi_off, &byte, 1, MPI_BYTE, &mpi_stat)))
HMPI_GOTO_ERROR(FAIL, "MPI_File_read_at failed", mpi_code)
- if (MPI_SUCCESS != (mpi_code=MPI_File_write_at(file->f, mpi_off, &byte, 1, MPI_BYTE, &mpi_stat)))
+ if(MPI_SUCCESS != (mpi_code = MPI_File_write_at(file->f, mpi_off, &byte, 1, MPI_BYTE, &mpi_stat)))
HMPI_GOTO_ERROR(FAIL, "MPI_File_write_at failed", mpi_code)
} /* end if */
#endif /* H5_MPI_FILE_SET_SIZE_BIG */
@@ -2004,27 +1972,21 @@ H5FD_mpio_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned closing)
* it the shorter length, potentially truncating the file and dropping
* the new data written)
*/
- if (MPI_SUCCESS!= (mpi_code=MPI_Barrier(file->comm)))
+ if(MPI_SUCCESS != (mpi_code = MPI_Barrier(file->comm)))
HMPI_GOTO_ERROR(FAIL, "MPI_Barrier failed", mpi_code)
/* Update the 'last' eoa value */
- file->last_eoa=file->eoa;
- } /* end if */
-
- /* Only sync the file if we are not going to immediately close it */
- if(!closing) {
- if (MPI_SUCCESS != (mpi_code=MPI_File_sync(file->f)))
- HMPI_GOTO_ERROR(FAIL, "MPI_File_sync failed", mpi_code)
+ file->last_eoa = file->eoa;
} /* end if */
done:
#ifdef H5FDmpio_DEBUG
- if (H5FD_mpio_Debug[(int)'t'])
- fprintf(stdout, "Leaving H5FD_mpio_flush\n" );
+ if(H5FD_mpio_Debug[(int)'t'])
+ HDfprintf(stdout, "Leaving %s\n", FUNC);
#endif
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_mpio_truncate() */
/*-------------------------------------------------------------------------
diff --git a/src/H5FDmpio.h b/src/H5FDmpio.h
index 8fa1be5..41baf8d 100644
--- a/src/H5FDmpio.h
+++ b/src/H5FDmpio.h
@@ -31,7 +31,7 @@
/* Macros */
#define IS_H5FD_MPIO(f) /* (H5F_t *f) */ \
- (H5FD_MPIO==H5F_get_driver_id(f))
+ (H5FD_MPIO==H5F_DRIVER_ID(f))
#ifdef H5_HAVE_PARALLEL
/*Turn on H5FDmpio_debug if H5F_DEBUG is on */
diff --git a/src/H5FDmpiposix.c b/src/H5FDmpiposix.c
index 6c30065..245fc3e 100644
--- a/src/H5FDmpiposix.c
+++ b/src/H5FDmpiposix.c
@@ -190,7 +190,7 @@ static herr_t H5FD_mpiposix_read(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id,
size_t size, void *buf);
static herr_t H5FD_mpiposix_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr,
size_t size, const void *buf);
-static herr_t H5FD_mpiposix_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing);
+static herr_t H5FD_mpiposix_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
static int H5FD_mpiposix_mpi_rank(const H5FD_t *_file);
static int H5FD_mpiposix_mpi_size(const H5FD_t *_file);
static MPI_Comm H5FD_mpiposix_communicator(const H5FD_t *_file);
@@ -221,6 +221,7 @@ static const H5FD_class_mpi_t H5FD_mpiposix_g = {
H5FD_mpiposix_close, /*close */
H5FD_mpiposix_cmp, /*cmp */
H5FD_mpiposix_query, /*query */
+ NULL, /*get_type_map */
NULL, /*alloc */
NULL, /*free */
H5FD_mpiposix_get_eoa, /*get_eoa */
@@ -229,7 +230,8 @@ static const H5FD_class_mpi_t H5FD_mpiposix_g = {
H5FD_mpiposix_get_handle, /*get_handle */
H5FD_mpiposix_read, /*read */
H5FD_mpiposix_write, /*write */
- H5FD_mpiposix_flush, /*flush */
+ NULL, /*flush */
+ H5FD_mpiposix_truncate, /*truncate */
NULL, /*lock */
NULL, /*unlock */
H5FD_FLMAP_SINGLE /*fl_map */
@@ -287,7 +289,7 @@ H5FD_mpiposix_init(void)
FUNC_ENTER_NOAPI(H5FD_mpiposix_init, FAIL)
if (H5I_VFL!=H5Iget_type(H5FD_MPIPOSIX_g))
- H5FD_MPIPOSIX_g = H5FD_register((const H5FD_class_t *)&H5FD_mpiposix_g,sizeof(H5FD_class_mpi_t));
+ H5FD_MPIPOSIX_g = H5FD_register((const H5FD_class_t *)&H5FD_mpiposix_g,sizeof(H5FD_class_mpi_t),FALSE);
/* Set return value */
ret_value=H5FD_MPIPOSIX_g;
@@ -1365,9 +1367,10 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5FD_mpiposix_flush
+ * Function: H5FD_mpiposix_truncate
*
- * Purpose: Makes sure that all data is on disk. This is collective.
+ * Purpose: Makes sure that the true file size is the same (or larger)
+ * than the end-of-address.
*
* Return: Success: Non-negative
* Failure: Negative
@@ -1375,12 +1378,10 @@ done:
* Programmer: Quincey Koziol
* Thursday, July 11, 2002
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static herr_t
-H5FD_mpiposix_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing)
+H5FD_mpiposix_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t UNUSED closing)
{
H5FD_mpiposix_t *file = (H5FD_mpiposix_t*)_file;
#ifdef _WIN32
@@ -1388,15 +1389,15 @@ H5FD_mpiposix_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing
LARGE_INTEGER li; /* 64-bit integer for SetFilePointer() call */
#endif /* _WIN32 */
int mpi_code; /* MPI return code */
- herr_t ret_value=SUCCEED;
+ herr_t ret_value = SUCCEED;
- FUNC_ENTER_NOAPI(H5FD_mpiposix_flush, FAIL)
+ FUNC_ENTER_NOAPI(H5FD_mpiposix_truncate, FAIL)
- assert(file);
- assert(H5FD_MPIPOSIX==file->pub.driver_id);
+ HDassert(file);
+ HDassert(H5FD_MPIPOSIX == file->pub.driver_id);
/* Extend the file to make sure it's large enough */
- if(file->eoa>file->last_eoa) {
+ if(file->eoa > file->last_eoa) {
/* Use the round-robin process to truncate (extend) the file */
if(file->mpi_rank == H5_PAR_META_WRITE) {
#ifdef _WIN32
@@ -1406,8 +1407,8 @@ H5FD_mpiposix_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing
/* Translate 64-bit integers into form Windows wants */
/* [This algorithm is from the Windows documentation for SetFilePointer()] */
li.QuadPart = file->eoa;
- SetFilePointer((HANDLE)filehandle,li.LowPart,&li.HighPart,FILE_BEGIN);
- if(SetEndOfFile((HANDLE)filehandle)==0)
+ SetFilePointer((HANDLE)filehandle, li.LowPart, &li.HighPart, FILE_BEGIN);
+ if(SetEndOfFile((HANDLE)filehandle) == 0)
HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
#else /* _WIN32 */
if(-1==file_truncate(file->fd, (file_offset_t)file->eoa))
@@ -1421,11 +1422,11 @@ H5FD_mpiposix_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing
* it the shorter length, potentially truncating the file and dropping
* the new data written)
*/
- if (MPI_SUCCESS!= (mpi_code=MPI_Barrier(file->comm)))
+ if(MPI_SUCCESS != (mpi_code = MPI_Barrier(file->comm)))
HMPI_GOTO_ERROR(FAIL, "MPI_Barrier failed", mpi_code)
/* Update the 'last' eoa and eof values */
- file->last_eoa=file->eoa;
+ file->last_eoa = file->eoa;
file->eof = file->eoa;
/* Reset last file I/O information */
@@ -1435,7 +1436,7 @@ H5FD_mpiposix_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_mpiposix_flush() */
+} /* end H5FD_mpiposix_truncate() */
/*-------------------------------------------------------------------------
diff --git a/src/H5FDmpiposix.h b/src/H5FDmpiposix.h
index 70e632a..832839e 100644
--- a/src/H5FDmpiposix.h
+++ b/src/H5FDmpiposix.h
@@ -32,7 +32,7 @@
/* Macros */
#define IS_H5FD_MPIPOSIX(f) /* (H5F_t *f) */ \
- (H5FD_MPIPOSIX==H5F_get_driver_id(f))
+ (H5FD_MPIPOSIX==H5F_DRIVER_ID(f))
#ifdef H5_HAVE_PARALLEL
@@ -54,4 +54,3 @@ H5_DLL herr_t H5Pget_fapl_mpiposix(hid_t fapl_id, MPI_Comm *comm/*out*/, hbool_t
#endif /* __H5FDmpiposix_H */
-
diff --git a/src/H5FDmulti.c b/src/H5FDmulti.c
index 8c25a62..2be54f8 100644
--- a/src/H5FDmulti.c
+++ b/src/H5FDmulti.c
@@ -66,16 +66,6 @@
assert(LOOPVAR>0 && LOOPVAR<H5FD_MEM_NTYPES); \
if (_seen[LOOPVAR]++) continue;
-#ifdef LATER
-#define MAPPED_MEMBERS(MAP,LOOPVAR) { \
- H5FD_mem_t _unmapped, LOOPVAR; \
- \
- for (_unmapped=H5FD_MEM_SUPER; _unmapped<H5FD_MEM_NTYPES; _unmapped=_unmapped+1) { \
- LOOPVAR = MAP[_unmapped]; \
- if (H5FD_MEM_DEFAULT==LOOPVAR) LOOPVAR=_unmapped; \
- assert(LOOPVAR>0 && LOOPVAR<H5FD_MEM_NTYPES);
-#endif /* LATER */
-
#define ALL_MEMBERS(LOOPVAR) { \
H5FD_mem_t LOOPVAR; \
for (LOOPVAR=H5FD_MEM_DEFAULT; LOOPVAR<H5FD_MEM_NTYPES; LOOPVAR=(H5FD_mem_t)(LOOPVAR+1)) {
@@ -140,6 +130,7 @@ static H5FD_t *H5FD_multi_open(const char *name, unsigned flags,
static herr_t H5FD_multi_close(H5FD_t *_file);
static int H5FD_multi_cmp(const H5FD_t *_f1, const H5FD_t *_f2);
static herr_t H5FD_multi_query(const H5FD_t *_f1, unsigned long *flags);
+static herr_t H5FD_multi_get_type_map(const H5FD_t *file, H5FD_mem_t *type_map);
static haddr_t H5FD_multi_get_eoa(const H5FD_t *_file, H5FD_mem_t type);
static herr_t H5FD_multi_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t eoa);
static haddr_t H5FD_multi_get_eof(const H5FD_t *_file);
@@ -152,6 +143,7 @@ static herr_t H5FD_multi_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, had
static herr_t H5FD_multi_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr,
size_t size, const void *_buf);
static herr_t H5FD_multi_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing);
+static herr_t H5FD_multi_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
/* The class struct */
static const H5FD_class_t H5FD_multi_g = {
@@ -172,6 +164,7 @@ static const H5FD_class_t H5FD_multi_g = {
H5FD_multi_close, /*close */
H5FD_multi_cmp, /*cmp */
H5FD_multi_query, /*query */
+ H5FD_multi_get_type_map, /*get_type_map */
H5FD_multi_alloc, /*alloc */
H5FD_multi_free, /*free */
H5FD_multi_get_eoa, /*get_eoa */
@@ -181,6 +174,7 @@ static const H5FD_class_t H5FD_multi_g = {
H5FD_multi_read, /*read */
H5FD_multi_write, /*write */
H5FD_multi_flush, /*flush */
+ H5FD_multi_truncate, /*truncate */
NULL, /*lock */
NULL, /*unlock */
H5FD_FLMAP_DEFAULT /*fl_map */
@@ -207,9 +201,13 @@ static char *
my_strdup(const char *s)
{
char *x;
- if (!s) return NULL;
- if (NULL==(x=malloc(strlen(s)+1))) return NULL;
+
+ if(!s)
+ return NULL;
+ if(NULL == (x = (char *)malloc(strlen(s) + 1)))
+ return NULL;
strcpy(x, s);
+
return x;
}
@@ -474,7 +472,7 @@ H5Pset_fapl_multi(hid_t fapl_id, const H5FD_mem_t *memb_map,
}
if (!memb_addr) {
for (mt=H5FD_MEM_DEFAULT; mt<H5FD_MEM_NTYPES; mt=(H5FD_mem_t)(mt+1))
- _memb_addr[mt] = (mt?mt-1:0) * HADDR_MAX/H5FD_MEM_NTYPES;
+ _memb_addr[mt] = (hsize_t)(mt ? (mt - 1) : 0) * HADDR_MAX / H5FD_MEM_NTYPES;
memb_addr = _memb_addr;
}
@@ -554,9 +552,9 @@ H5Pget_fapl_multi(hid_t fapl_id, H5FD_mem_t *memb_map/*out*/,
if(H5I_GENPROP_LST != H5Iget_type(fapl_id) ||
TRUE != H5Pisa_class(fapl_id, H5P_FILE_ACCESS))
H5Epush_ret(func, H5E_ERR_CLS, H5E_PLIST, H5E_BADTYPE, "not an access list", -1)
- if (H5FD_MULTI!=H5Pget_driver(fapl_id))
+ if(H5FD_MULTI != H5Pget_driver(fapl_id))
H5Epush_ret(func, H5E_ERR_CLS, H5E_PLIST, H5E_BADVALUE, "incorrect VFL driver", -1)
- if (NULL==(fa=H5Pget_driver_info(fapl_id)))
+ if(NULL == (fa= (H5FD_multi_fapl_t *)H5Pget_driver_info(fapl_id)))
H5Epush_ret(func, H5E_ERR_CLS, H5E_PLIST, H5E_BADVALUE, "bad VFL driver info", -1)
if (memb_map)
@@ -572,7 +570,7 @@ H5Pget_fapl_multi(hid_t fapl_id, H5FD_mem_t *memb_map/*out*/,
if (memb_name) {
for (mt=H5FD_MEM_DEFAULT; mt<H5FD_MEM_NTYPES; mt=(H5FD_mem_t)(mt+1)) {
if (fa->memb_name[mt]) {
- memb_name[mt] = malloc(strlen(fa->memb_name[mt])+1);
+ memb_name[mt] = (char *)malloc(strlen(fa->memb_name[mt])+1);
strcpy(memb_name[mt], fa->memb_name[mt]);
} else
memb_name[mt] = NULL;
@@ -674,7 +672,7 @@ H5Pget_dxpl_multi(hid_t dxpl_id, hid_t *memb_dxpl/*out*/)
H5Epush_ret(func, H5E_ERR_CLS, H5E_PLIST, H5E_BADTYPE, "not a file access property list", -1)
if (H5FD_MULTI!=H5Pget_driver(dxpl_id))
H5Epush_ret(func, H5E_ERR_CLS, H5E_PLIST, H5E_BADVALUE, "incorrect VFL driver", -1)
- if (NULL==(dx=H5Pget_driver_info(dxpl_id)))
+ if(NULL == (dx = (H5FD_multi_dxpl_t *)H5Pget_driver_info(dxpl_id)))
H5Epush_ret(func, H5E_ERR_CLS, H5E_PLIST, H5E_BADVALUE, "bad VFL driver info", -1)
if (memb_dxpl) {
@@ -711,7 +709,7 @@ static hsize_t
H5FD_multi_sb_size(H5FD_t *_file)
{
H5FD_multi_t *file = (H5FD_multi_t*)_file;
- int nseen = 0;
+ unsigned nseen = 0;
hsize_t nbytes = 8; /*size of header*/
/* Clear the error stack */
@@ -797,9 +795,9 @@ H5FD_multi_sb_encode(H5FD_t *_file, char *name/*out*/,
p = buf+8;
assert(sizeof(haddr_t)<=8);
UNIQUE_MEMBERS(file->fa.memb_map, mt) {
- memb_eoa = H5FDget_eoa(file->memb[mt], mt);
memcpy(p, &(file->fa.memb_addr[mt]), sizeof(haddr_t));
p += sizeof(haddr_t);
+ memb_eoa = H5FDget_eoa(file->memb[mt], mt);
memcpy(p, &memb_eoa, sizeof(haddr_t));
p += sizeof(haddr_t);
nseen++;
@@ -818,7 +816,7 @@ H5FD_multi_sb_encode(H5FD_t *_file, char *name/*out*/,
} END_MEMBERS;
return 0;
-}
+} /* end H5FD_multi_sb_encode() */
/*-------------------------------------------------------------------------
@@ -976,7 +974,7 @@ H5FD_multi_sb_decode(H5FD_t *_file, const char *name, const unsigned char *buf)
} END_MEMBERS;
return 0;
-}
+} /* end H5FD_multi_sb_decode() */
/*-------------------------------------------------------------------------
@@ -1030,7 +1028,7 @@ static void *
H5FD_multi_fapl_copy(const void *_old_fa)
{
const H5FD_multi_fapl_t *old_fa = (const H5FD_multi_fapl_t*)_old_fa;
- H5FD_multi_fapl_t *new_fa = malloc(sizeof(H5FD_multi_fapl_t));
+ H5FD_multi_fapl_t *new_fa = (H5FD_multi_fapl_t *)malloc(sizeof(H5FD_multi_fapl_t));
int nerrors = 0;
static const char *func="H5FD_multi_fapl_copy"; /* Function Name for error reporting */
@@ -1046,7 +1044,7 @@ H5FD_multi_fapl_copy(const void *_old_fa)
if (new_fa->memb_fapl[mt]<0) nerrors++;
}
if (old_fa->memb_name[mt]) {
- new_fa->memb_name[mt] = malloc(strlen(old_fa->memb_name[mt])+1);
+ new_fa->memb_name[mt] = (char *)malloc(strlen(old_fa->memb_name[mt])+1);
assert(new_fa->memb_name[mt]);
strcpy(new_fa->memb_name[mt], old_fa->memb_name[mt]);
}
@@ -1122,7 +1120,7 @@ static void *
H5FD_multi_dxpl_copy(const void *_old_dx)
{
const H5FD_multi_dxpl_t *old_dx = (const H5FD_multi_dxpl_t*)_old_dx;
- H5FD_multi_dxpl_t *new_dx = malloc(sizeof(H5FD_multi_dxpl_t));
+ H5FD_multi_dxpl_t *new_dx = (H5FD_multi_dxpl_t *)malloc(sizeof(H5FD_multi_dxpl_t));
int nerrors = 0;
static const char *func="H5FD_multi_dxpl_copy"; /* Function Name for error reporting */
@@ -1227,14 +1225,14 @@ H5FD_multi_open(const char *name, unsigned flags, hid_t fapl_id,
* Initialize the file from the file access properties, using default
* values if necessary.
*/
- if (NULL==(file=calloc((size_t)1, sizeof(H5FD_multi_t))))
+ if(NULL == (file = (H5FD_multi_t *)calloc((size_t)1, sizeof(H5FD_multi_t))))
H5Epush_ret(func, H5E_ERR_CLS, H5E_RESOURCE, H5E_NOSPACE, "memory allocation failed", NULL)
- if (H5P_FILE_ACCESS_DEFAULT==fapl_id || H5FD_MULTI!=H5Pget_driver(fapl_id)) {
+ if(H5P_FILE_ACCESS_DEFAULT==fapl_id || H5FD_MULTI!=H5Pget_driver(fapl_id)) {
close_fapl = fapl_id = H5Pcreate(H5P_FILE_ACCESS);
if(H5Pset_fapl_multi(fapl_id, NULL, NULL, NULL, NULL, TRUE)<0)
H5Epush_goto(func, H5E_ERR_CLS, H5E_FILE, H5E_CANTSET, "can't set property value", error)
}
- fa = H5Pget_driver_info(fapl_id);
+ fa = (H5FD_multi_fapl_t *)H5Pget_driver_info(fapl_id);
assert(fa);
ALL_MEMBERS(mt) {
file->fa.memb_map[mt] = fa->memb_map[mt];
@@ -1418,13 +1416,38 @@ H5FD_multi_query(const H5FD_t *_f, unsigned long *flags /* out */)
/* Set the VFL feature flags that this driver supports */
if(flags) {
- *flags=0;
- *flags|=H5FD_FEAT_DATA_SIEVE; /* OK to perform data sieving for faster raw data reads & writes */
- *flags|=H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */
- }
+ *flags = 0;
+ *flags |= H5FD_FEAT_DATA_SIEVE; /* OK to perform data sieving for faster raw data reads & writes */
+ *flags |= H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */
+ } /* end if */
return(0);
-}
+} /* end H5FD_multi_query() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_multi_get_type_map
+ *
+ * Purpose: Retrieve the memory type mapping for this file
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, October 9, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_multi_get_type_map(const H5FD_t *_file, H5FD_mem_t *type_map)
+{
+ const H5FD_multi_t *file = (const H5FD_multi_t*)_file;
+
+ /* Copy file's free space type mapping */
+ memcpy(type_map, file->fa.memb_map, sizeof(file->fa.memb_map));
+
+ return(0);
+} /* end H5FD_multi_get_type_map() */
/*-------------------------------------------------------------------------
@@ -1457,7 +1480,7 @@ H5FD_multi_get_eoa(const H5FD_t *_file, H5FD_mem_t type)
const H5FD_multi_t *file = (const H5FD_multi_t*)_file;
haddr_t eoa = 0;
haddr_t memb_eoa = 0;
- static const char *func="H5FD_multi_eof"; /* Function Name for error reporting */
+ static const char *func="H5FD_multi_get_eoa"; /* Function Name for error reporting */
/* Clear the error stack */
H5Eclear2(H5E_DEFAULT);
@@ -1466,8 +1489,8 @@ H5FD_multi_get_eoa(const H5FD_t *_file, H5FD_mem_t type)
* taken out because it makes little sense for MULTI files.
* However, the library sometimes queries it through H5F_get_eoa.
* Here the code finds the biggest EOA for individual file if
- * the query is from H5F_get_eoa (TYPE is H5FD_MEM_DEFAULT).
- */
+ * the query is for TYPE == H5FD_MEM_DEFAULT.
+ */
if(H5FD_MEM_DEFAULT == type) {
UNIQUE_MEMBERS(file->fa.memb_map, mt) {
if (file->memb[mt]) {
@@ -1494,7 +1517,7 @@ H5FD_multi_get_eoa(const H5FD_t *_file, H5FD_mem_t type)
} END_MEMBERS;
} else {
H5FD_mem_t mmt = file->fa.memb_map[type];
- if (H5FD_MEM_DEFAULT==mmt) mmt = type;
+ if (H5FD_MEM_DEFAULT==mmt) mmt = type;
if (file->memb[mmt]) {
H5E_BEGIN_TRY {
@@ -1503,6 +1526,7 @@ H5FD_multi_get_eoa(const H5FD_t *_file, H5FD_mem_t type)
if (HADDR_UNDEF==eoa)
H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "member file has unknown eoa", HADDR_UNDEF)
+ if (eoa>0) eoa += file->fa.memb_addr[mmt];
} else if (file->fa.relax) {
/*
* The member is not open yet (maybe it doesn't exist). Make the
@@ -1516,7 +1540,7 @@ H5FD_multi_get_eoa(const H5FD_t *_file, H5FD_mem_t type)
}
return eoa;
-}
+} /* end H5FD_multi_get_eoa() */
/*-------------------------------------------------------------------------
@@ -1547,20 +1571,28 @@ static herr_t
H5FD_multi_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t eoa)
{
H5FD_multi_t *file = (H5FD_multi_t*)_file;
+ H5FD_mem_t mmt;
herr_t status;
static const char *func="H5FD_multi_set_eoa"; /* Function Name for error reporting */
/* Clear the error stack */
H5Eclear2(H5E_DEFAULT);
+ mmt = file->fa.memb_map[type];
+ if(H5FD_MEM_DEFAULT == mmt)
+ mmt = type;
+
+ assert(eoa >= file->fa.memb_addr[mmt]);
+ assert(eoa < file->memb_next[mmt]);
+
H5E_BEGIN_TRY {
- status = H5FDset_eoa(file->memb[type], type, eoa);
+ status = H5FDset_eoa(file->memb[mmt], mmt, (eoa - file->fa.memb_addr[mmt]));
} H5E_END_TRY;
if (status<0)
H5Epush_ret(func, H5E_ERR_CLS, H5E_FILE, H5E_BADVALUE, "member H5FDset_eoa failed", -1)
return 0;
-}
+} /* end H5FD_multi_set_eoa() */
/*-------------------------------------------------------------------------
@@ -1592,7 +1624,7 @@ H5FD_multi_get_eof(const H5FD_t *_file)
const H5FD_multi_t *file = (const H5FD_multi_t*)_file;
haddr_t eof=0, tmp_eof;
haddr_t eoa=0, tmp_eoa;
- static const char *func="H5FD_multi_eof"; /* Function Name for error reporting */
+ static const char *func="H5FD_multi_get_eof"; /* Function Name for error reporting */
/* Clear the error stack */
H5Eclear2(H5E_DEFAULT);
@@ -1615,6 +1647,7 @@ H5FD_multi_get_eof(const H5FD_t *_file)
if (HADDR_UNDEF==tmp_eoa)
H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "member file has unknown eoa", HADDR_UNDEF)
+ if (tmp_eoa>0) tmp_eoa += file->fa.memb_addr[mt];
} else if (file->fa.relax) {
/*
* The member is not open yet (maybe it doesn't exist). Make the
@@ -1697,7 +1730,7 @@ H5FD_multi_alloc(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size)
mmt = file->fa.memb_map[type];
if (H5FD_MEM_DEFAULT==mmt) mmt = type;
- if (HADDR_UNDEF==(addr=H5FDalloc(file->memb[mmt], type, dxpl_id, size)))
+ if (HADDR_UNDEF==(addr=H5FDalloc(file->memb[mmt], mmt, dxpl_id, size)))
H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "member file can't alloc", HADDR_UNDEF)
addr += file->fa.memb_addr[mmt];
@@ -1749,7 +1782,7 @@ H5FD_multi_free(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsi
assert(addr>=file->fa.memb_addr[mmt]);
assert(addr+size<=file->memb_next[mmt]);
- return H5FDfree(file->memb[mmt], type, dxpl_id, addr-file->fa.memb_addr[mmt], size);
+ return H5FDfree(file->memb[mmt], mmt, dxpl_id, addr-file->fa.memb_addr[mmt], size);
}
@@ -1785,15 +1818,15 @@ H5FD_multi_read(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, siz
H5Eclear2(H5E_DEFAULT);
/* Get the data transfer properties */
- if (H5P_FILE_ACCESS_DEFAULT!=dxpl_id && H5FD_MULTI==H5Pget_driver(dxpl_id)) {
- dx = H5Pget_driver_info(dxpl_id);
- }
+ if(H5P_FILE_ACCESS_DEFAULT != dxpl_id && H5FD_MULTI == H5Pget_driver(dxpl_id))
+ dx = (H5FD_multi_dxpl_t *)H5Pget_driver_info(dxpl_id);
/* Find the file to which this address belongs */
- for (mt=H5FD_MEM_SUPER; mt<H5FD_MEM_NTYPES; mt=(H5FD_mem_t)(mt+1)) {
+ for(mt = H5FD_MEM_SUPER; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) {
mmt = file->fa.memb_map[mt];
- if (H5FD_MEM_DEFAULT==mmt) mmt = mt;
- assert(mmt>0 && mmt<H5FD_MEM_NTYPES);
+ if(H5FD_MEM_DEFAULT == mmt)
+ mmt = mt;
+ assert(mmt > 0 && mmt < H5FD_MEM_NTYPES);
if (file->fa.memb_addr[mmt]>addr) continue;
if (file->fa.memb_addr[mmt]>=start_addr) {
@@ -1840,14 +1873,14 @@ H5FD_multi_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, si
H5Eclear2(H5E_DEFAULT);
/* Get the data transfer properties */
- if (H5P_FILE_ACCESS_DEFAULT!=dxpl_id && H5FD_MULTI==H5Pget_driver(dxpl_id)) {
- dx = H5Pget_driver_info(dxpl_id);
- }
+ if(H5P_FILE_ACCESS_DEFAULT != dxpl_id && H5FD_MULTI == H5Pget_driver(dxpl_id))
+ dx = (H5FD_multi_dxpl_t *)H5Pget_driver_info(dxpl_id);
/* Find the file to which this address belongs */
- for (mt=H5FD_MEM_SUPER; mt<H5FD_MEM_NTYPES; mt=(H5FD_mem_t)(mt+1)) {
+ for(mt = H5FD_MEM_SUPER; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) {
mmt = file->fa.memb_map[mt];
- if (H5FD_MEM_DEFAULT==mmt) mmt = mt;
+ if(H5FD_MEM_DEFAULT == mmt)
+ mmt = mt;
assert(mmt>0 && mmt<H5FD_MEM_NTYPES);
if (file->fa.memb_addr[mmt]>addr) continue;
@@ -1939,6 +1972,46 @@ H5FD_multi_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing)
/*-------------------------------------------------------------------------
+ * Function: H5FD_multi_truncate
+ *
+ * Purpose: Truncates all multi members.
+ *
+ * Return: Success: 0
+ * Failure: -1, as many files truncated as possible.
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, January 31, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_multi_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing)
+{
+ H5FD_multi_t *file = (H5FD_multi_t*)_file;
+ H5FD_mem_t mt;
+ int nerrors=0;
+ static const char *func="H5FD_multi_truncate"; /* Function Name for error reporting */
+
+ /* Clear the error stack */
+ H5Eclear2(H5E_DEFAULT);
+
+ /* Truncate each file */
+ for(mt = H5FD_MEM_SUPER; mt < H5FD_MEM_NTYPES; mt = (H5FD_mem_t)(mt + 1)) {
+ if(file->memb[mt]) {
+ H5E_BEGIN_TRY {
+ if(H5FDtruncate(file->memb[mt], dxpl_id, closing) < 0)
+ nerrors++;
+ } H5E_END_TRY;
+ }
+ }
+ if(nerrors)
+ H5Epush_ret(func, H5E_ERR_CLS, H5E_INTERNAL, H5E_BADVALUE, "error truncating member files", -1)
+
+ return 0;
+} /* end H5FD_multi_truncate() */
+
+
+/*-------------------------------------------------------------------------
* Function: compute_next
*
* Purpose: Compute the memb_next[] values of the file based on the
diff --git a/src/H5FDpkg.h b/src/H5FDpkg.h
new file mode 100644
index 0000000..9401b52
--- /dev/null
+++ b/src/H5FDpkg.h
@@ -0,0 +1,63 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Programmer: Quincey Koziol <koziol@hdfgroup.org>
+ * Thursday, January 3, 2008
+ *
+ * Purpose: This file contains declarations which are visible only within
+ * the H5FD package. Source files outside the H5FD package should
+ * include H5FDprivate.h instead.
+ */
+#ifndef H5FD_PACKAGE
+#error "Do not include this file outside the H5FD package!"
+#endif
+
+#ifndef _H5FDpkg_H
+#define _H5FDpkg_H
+
+/* Get package's private header */
+#include "H5FDprivate.h" /* File drivers */
+
+/* Other private headers needed by this file */
+#include "H5FLprivate.h" /* Free lists */
+
+/**************************/
+/* Package Private Macros */
+/**************************/
+
+
+/****************************/
+/* Package Private Typedefs */
+/****************************/
+
+
+/*****************************/
+/* Package Private Variables */
+/*****************************/
+
+
+/******************************/
+/* Package Private Prototypes */
+/******************************/
+H5_DLL herr_t H5FD_init(void);
+
+
+/* Testing routines */
+#ifdef H5FD_TESTING
+#endif /* H5FD_TESTING */
+
+#endif /* _H5FDpkg_H */
+
diff --git a/src/H5FDprivate.h b/src/H5FDprivate.h
index 202b7d1..25b2f24 100644
--- a/src/H5FDprivate.h
+++ b/src/H5FDprivate.h
@@ -49,30 +49,31 @@ H5_DLL herr_t H5FD_fapl_close(hid_t driver_id, void *fapl);
H5_DLL herr_t H5FD_dxpl_open(struct H5P_genplist_t *plist, hid_t driver_id, const void *driver_info);
H5_DLL herr_t H5FD_dxpl_copy(hid_t driver_id, const void *dxpl, void **copied_dxpl);
H5_DLL herr_t H5FD_dxpl_close(hid_t driver_id, void *dxpl);
-H5_DLL hid_t H5FD_register(const void *cls, size_t size);
+H5_DLL hid_t H5FD_register(const void *cls, size_t size, hbool_t app_ref);
H5_DLL H5FD_t *H5FD_open(const char *name, unsigned flags, hid_t fapl_id,
haddr_t maxaddr);
H5_DLL herr_t H5FD_close(H5FD_t *file);
H5_DLL int H5FD_cmp(const H5FD_t *f1, const H5FD_t *f2);
H5_DLL int H5FD_query(const H5FD_t *f, unsigned long *flags/*out*/);
-H5_DLL haddr_t H5FD_alloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size);
-H5_DLL herr_t H5FD_free(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t size);
-H5_DLL haddr_t H5FD_realloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t old_addr,
- hsize_t old_size, hsize_t new_size);
+H5_DLL haddr_t H5FD_alloc(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type, hsize_t size, haddr_t *align_addr, hsize_t *align_size);
+H5_DLL herr_t H5FD_free(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr, hsize_t size);
+H5_DLL htri_t H5FD_try_extend(H5FD_t *file, H5FD_mem_t type, haddr_t blk_end,
+ hsize_t extra_requested);
H5_DLL haddr_t H5FD_get_eoa(const H5FD_t *file, H5FD_mem_t type);
H5_DLL herr_t H5FD_set_eoa(H5FD_t *file, H5FD_mem_t type, haddr_t addr);
H5_DLL haddr_t H5FD_get_eof(const H5FD_t *file);
-H5_DLL herr_t H5FD_read(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size,
- void *buf/*out*/);
-H5_DLL herr_t H5FD_write(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size,
- const void *buf);
+H5_DLL haddr_t H5FD_get_maxaddr(const H5FD_t *file);
+H5_DLL herr_t H5FD_get_feature_flags(const H5FD_t *file, unsigned long *feature_flags);
+H5_DLL herr_t H5FD_get_fs_type_map(const H5FD_t *file, H5FD_mem_t *type_map);
+H5_DLL herr_t H5FD_read(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type,
+ haddr_t addr, size_t size, void *buf/*out*/);
+H5_DLL herr_t H5FD_write(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type,
+ haddr_t addr, size_t size, const void *buf);
H5_DLL herr_t H5FD_flush(H5FD_t *file, hid_t dxpl_id, unsigned closing);
+H5_DLL herr_t H5FD_truncate(H5FD_t *file, hid_t dxpl_id, hbool_t closing);
H5_DLL herr_t H5FD_get_fileno(const H5FD_t *file, unsigned long *filenum);
H5_DLL herr_t H5FD_get_vfd_handle(H5FD_t *file, hid_t fapl, void** file_handle);
-H5_DLL hssize_t H5FD_get_freespace(const H5FD_t *file);
-H5_DLL htri_t H5FD_can_extend(const H5FD_t *file, H5FD_mem_t type, haddr_t addr,
- hsize_t size, hsize_t extra_requested);
-H5_DLL herr_t H5FD_extend(H5FD_t *file, H5FD_mem_t type, haddr_t addr,
- hsize_t size, hsize_t extra_requested);
+H5_DLL herr_t H5FD_set_base_addr(H5FD_t *file, haddr_t base_addr);
#endif /* !_H5FDprivate_H */
+
diff --git a/src/H5FDpublic.h b/src/H5FDpublic.h
index ebf006b..b1e1482 100644
--- a/src/H5FDpublic.h
+++ b/src/H5FDpublic.h
@@ -89,6 +89,27 @@ typedef enum H5FD_mem_t {
#define H5FD_MEM_SOHM_TABLE H5FD_MEM_OHDR
#define H5FD_MEM_SOHM_INDEX H5FD_MEM_BTREE
+/* Map "extensible array" header blocks to 'ohdr' type file memory, since its
+ * a fair amount of work to add a new kind of file memory and they are similar
+ * enough to object headers and probably too minor to deserve their own type.
+ *
+ * Map "extensible array" index blocks to 'ohdr' type file memory, since they
+ * are similar to extensible array header blocks.
+ *
+ * Map "extensible array" super blocks to 'btree' type file memory, since they
+ * are similar enough to B-tree nodes.
+ *
+ * Map "extensible array" data blocks & pages to 'lheap' type file memory, since
+ * they are similar enough to local heap info.
+ *
+ * -QAK
+ */
+#define H5FD_MEM_EARRAY_HDR H5FD_MEM_OHDR
+#define H5FD_MEM_EARRAY_IBLOCK H5FD_MEM_OHDR
+#define H5FD_MEM_EARRAY_SBLOCK H5FD_MEM_BTREE
+#define H5FD_MEM_EARRAY_DBLOCK H5FD_MEM_LHEAP
+#define H5FD_MEM_EARRAY_DBLK_PAGE H5FD_MEM_LHEAP
+
/*
* A free-list map which maps all types of allocation requests to a single
* free list. This is useful for drivers that don't really care about
@@ -198,6 +219,7 @@ typedef struct H5FD_class_t {
herr_t (*close)(H5FD_t *file);
int (*cmp)(const H5FD_t *f1, const H5FD_t *f2);
herr_t (*query)(const H5FD_t *f1, unsigned long *flags);
+ herr_t (*get_type_map)(const H5FD_t *file, H5FD_mem_t *type_map);
haddr_t (*alloc)(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size);
herr_t (*free)(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id,
haddr_t addr, hsize_t size);
@@ -210,6 +232,7 @@ typedef struct H5FD_class_t {
herr_t (*write)(H5FD_t *file, H5FD_mem_t type, hid_t dxpl,
haddr_t addr, size_t size, const void *buffer);
herr_t (*flush)(H5FD_t *file, hid_t dxpl_id, unsigned closing);
+ herr_t (*truncate)(H5FD_t *file, hid_t dxpl_id, hbool_t closing);
herr_t (*lock)(H5FD_t *file, unsigned char *oid, unsigned lock_type, hbool_t last);
herr_t (*unlock)(H5FD_t *file, unsigned char *oid, hbool_t last);
H5FD_mem_t fl_map[H5FD_MEM_NTYPES];
@@ -229,48 +252,14 @@ typedef struct H5FD_free_t {
struct H5FD_t {
hid_t driver_id; /*driver ID for this file */
const H5FD_class_t *cls; /*constant class info */
- unsigned long fileno; /* File serial number */
+ unsigned long fileno; /* File 'serial' number */
unsigned long feature_flags; /* VFL Driver feature Flags */
+ haddr_t maxaddr; /* For this file, overrides class */
+ haddr_t base_addr; /* Base address for HDF5 data w/in file */
+
+ /* Space allocation management fields */
hsize_t threshold; /* Threshold for alignment */
hsize_t alignment; /* Allocation alignment */
-
- /* Metadata aggregation fields */
- hsize_t def_meta_block_size; /* Metadata allocation
- * block size (if
- * aggregating metadata) */
- hsize_t cur_meta_block_size; /* Current size of metadata
- * allocation region left */
- haddr_t eoma; /* End of metadata
- * allocated region */
- /* (ie. beginning of space available) */
-
- /* "Small data" aggregation fields */
- hsize_t def_sdata_block_size; /* "Small data"
- * allocation block size
- * (if aggregating "small
- * data") */
- hsize_t cur_sdata_block_size; /* Current size of "small
- * data" allocation
- * region left */
- haddr_t eosda; /* End of "small data"
- * allocated region */
- /* (ie. beginning of space available) */
-
- /* Metadata accumulator fields */
- unsigned char *meta_accum; /* Buffer to hold the accumulated metadata */
- haddr_t accum_loc; /* File location (offset) of the
- * accumulated metadata */
- size_t accum_size; /* Size of the accumulated
- * metadata buffer used (in
- * bytes) */
- size_t accum_buf_size; /* Size of the accumulated
- * metadata buffer allocated (in
- * bytes) */
- unsigned accum_dirty; /* Flag to indicate that the
- * accumulated metadata is dirty */
- haddr_t maxaddr; /* For this file, overrides class */
- H5FD_free_t *fl[H5FD_MEM_NTYPES]; /* Freelist per allocation type */
- hsize_t maxsize; /* Largest object on FL, or zero */
};
#ifdef __cplusplus
@@ -288,8 +277,6 @@ H5_DLL int H5FDquery(const H5FD_t *f, unsigned long *flags);
H5_DLL haddr_t H5FDalloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size);
H5_DLL herr_t H5FDfree(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id,
haddr_t addr, hsize_t size);
-H5_DLL haddr_t H5FDrealloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id,
- haddr_t addr, hsize_t old_size, hsize_t new_size);
H5_DLL haddr_t H5FDget_eoa(H5FD_t *file, H5FD_mem_t type);
H5_DLL herr_t H5FDset_eoa(H5FD_t *file, H5FD_mem_t type, haddr_t eoa);
H5_DLL haddr_t H5FDget_eof(H5FD_t *file);
@@ -299,8 +286,10 @@ H5_DLL herr_t H5FDread(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id,
H5_DLL herr_t H5FDwrite(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id,
haddr_t addr, size_t size, const void *buf);
H5_DLL herr_t H5FDflush(H5FD_t *file, hid_t dxpl_id, unsigned closing);
+H5_DLL herr_t H5FDtruncate(H5FD_t *file, hid_t dxpl_id, hbool_t closing);
#ifdef __cplusplus
}
#endif
#endif
+
diff --git a/src/H5FDsec2.c b/src/H5FDsec2.c
index b01ba3f..093624b 100644
--- a/src/H5FDsec2.c
+++ b/src/H5FDsec2.c
@@ -101,24 +101,16 @@ typedef struct H5FD_sec2_t {
* file_offset_t: The datatype for file offsets, the second argument of
* the lseek() or lseek64() call.
*
- * file_seek: The function which adjusts the current file position,
- * either lseek() or lseek64().
*/
/* adding for windows NT file system support. */
#ifdef H5_HAVE_LSEEK64
# define file_offset_t off64_t
-# define file_seek lseek64
-# define file_truncate ftruncate64
#elif defined (_WIN32) && !defined(__MWERKS__)
# /*MSVC*/
-# define file_offset_t __int64
-# define file_seek _lseeki64
-# define file_truncate _chsize
+# define file_offset_t __int64
#else
# define file_offset_t off_t
-# define file_seek lseek
-# define file_truncate HDftruncate
#endif
/*
@@ -158,7 +150,7 @@ static herr_t H5FD_sec2_read(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, hadd
size_t size, void *buf);
static herr_t H5FD_sec2_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr,
size_t size, const void *buf);
-static herr_t H5FD_sec2_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing);
+static herr_t H5FD_sec2_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
static const H5FD_class_t H5FD_sec2_g = {
"sec2", /*name */
@@ -178,6 +170,7 @@ static const H5FD_class_t H5FD_sec2_g = {
H5FD_sec2_close, /*close */
H5FD_sec2_cmp, /*cmp */
H5FD_sec2_query, /*query */
+ NULL, /*get_type_map */
NULL, /*alloc */
NULL, /*free */
H5FD_sec2_get_eoa, /*get_eoa */
@@ -186,7 +179,8 @@ static const H5FD_class_t H5FD_sec2_g = {
H5FD_sec2_get_handle, /*get_handle */
H5FD_sec2_read, /*read */
H5FD_sec2_write, /*write */
- H5FD_sec2_flush, /*flush */
+ NULL, /*flush */
+ H5FD_sec2_truncate, /*truncate */
NULL, /*lock */
NULL, /*unlock */
H5FD_FLMAP_SINGLE /*fl_map */
@@ -240,7 +234,7 @@ H5FD_sec2_init(void)
FUNC_ENTER_NOAPI(H5FD_sec2_init, FAIL)
if(H5I_VFL != H5I_get_type(H5FD_SEC2_g))
- H5FD_SEC2_g = H5FD_register(&H5FD_sec2_g, sizeof(H5FD_class_t));
+ H5FD_SEC2_g = H5FD_register(&H5FD_sec2_g, sizeof(H5FD_class_t), FALSE);
/* Set return value */
ret_value = H5FD_SEC2_g;
@@ -419,26 +413,32 @@ done:
* Programmer: Robb Matzke
* Thursday, July 29, 1999
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static herr_t
H5FD_sec2_close(H5FD_t *_file)
{
H5FD_sec2_t *file = (H5FD_sec2_t*)_file;
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5FD_sec2_close, FAIL)
+#ifdef QAK
+HDfprintf(stderr, "%s: file->eof = %a, file->eoa = %a\n", FUNC, file->eof, file->eoa);
+#endif /* QAK */
- if (HDclose(file->fd)<0)
+ /* Sanity check */
+ HDassert(file);
+
+ /* Close the underlying file */
+ if(HDclose(file->fd) < 0)
HSYS_GOTO_ERROR(H5E_IO, H5E_CANTCLOSEFILE, FAIL, "unable to close file")
- H5FL_FREE(H5FD_sec2_t,file);
+ /* Release the file info */
+ (void)H5FL_FREE(H5FD_sec2_t, file);
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_sec2_close() */
/*-------------------------------------------------------------------------
@@ -510,36 +510,33 @@ done:
* (listed in H5FDpublic.h)
*
* Return: Success: non-negative
- *
* Failure: negative
*
* Programmer: Quincey Koziol
* Friday, August 25, 2000
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
/* ARGSUSED */
static herr_t
H5FD_sec2_query(const H5FD_t UNUSED * _f, unsigned long *flags /* out */)
{
- herr_t ret_value=SUCCEED;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5FD_sec2_query, FAIL)
/* Set the VFL feature flags that this driver supports */
if(flags) {
*flags = 0;
- *flags|=H5FD_FEAT_AGGREGATE_METADATA; /* OK to aggregate metadata allocations */
- *flags|=H5FD_FEAT_ACCUMULATE_METADATA; /* OK to accumulate metadata for faster writes */
- *flags|=H5FD_FEAT_DATA_SIEVE; /* OK to perform data sieving for faster raw data reads & writes */
- *flags|=H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */
- }
+ *flags |= H5FD_FEAT_AGGREGATE_METADATA; /* OK to aggregate metadata allocations */
+ *flags |= H5FD_FEAT_ACCUMULATE_METADATA; /* OK to accumulate metadata for faster writes */
+ *flags |= H5FD_FEAT_DATA_SIEVE; /* OK to perform data sieving for faster raw data reads & writes */
+ *flags |= H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */
+ } /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_sec2_query() */
/*-------------------------------------------------------------------------
@@ -572,11 +569,11 @@ H5FD_sec2_get_eoa(const H5FD_t *_file, H5FD_mem_t UNUSED type)
FUNC_ENTER_NOAPI(H5FD_sec2_get_eoa, HADDR_UNDEF)
/* Set return value */
- ret_value=file->eoa;
+ ret_value = file->eoa;
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_sec2_get_eoa() */
/*-------------------------------------------------------------------------
@@ -612,7 +609,7 @@ H5FD_sec2_set_eoa(H5FD_t *_file, H5FD_mem_t UNUSED type, haddr_t addr)
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_sec2_set_eoa() */
/*-------------------------------------------------------------------------
@@ -692,80 +689,77 @@ done:
*
* Return: Success: Zero. Result is stored in caller-supplied
* buffer BUF.
- *
* Failure: -1, Contents of buffer BUF are undefined.
*
* Programmer: Robb Matzke
* Thursday, July 29, 1999
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
/* ARGSUSED */
static herr_t
-H5FD_sec2_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, haddr_t addr,
- size_t size, void *buf/*out*/)
+H5FD_sec2_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id,
+ haddr_t addr, size_t size, void *buf/*out*/)
{
H5FD_sec2_t *file = (H5FD_sec2_t*)_file;
ssize_t nbytes;
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5FD_sec2_read, FAIL)
- assert(file && file->pub.cls);
- assert(buf);
+ HDassert(file && file->pub.cls);
+ HDassert(buf);
/* Check for overflow conditions */
- if (HADDR_UNDEF==addr)
+ if(!H5F_addr_defined(addr))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "addr undefined")
- if (REGION_OVERFLOW(addr, size))
+ if(REGION_OVERFLOW(addr, size))
HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "addr overflow")
- if (addr+size>file->eoa)
+ if((addr + size) > file->eoa)
HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "addr overflow")
/* Seek to the correct location */
- if ((addr!=file->pos || OP_READ!=file->op) &&
- file_seek(file->fd, (file_offset_t)addr, SEEK_SET)<0)
+ if((addr != file->pos || OP_READ != file->op) &&
+ HDlseek(file->fd, (file_offset_t)addr, SEEK_SET) < 0)
HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position")
/*
* Read data, being careful of interrupted system calls, partial results,
* and the end of the file.
*/
- while (size>0) {
+ while(size > 0) {
do {
nbytes = HDread(file->fd, buf, size);
- } while (-1==nbytes && EINTR==errno);
- if (-1==nbytes) /* error */
+ } while(-1 == nbytes && EINTR == errno);
+ if(-1 == nbytes) /* error */
HSYS_GOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file read failed")
- if (0==nbytes) {
+ if(0 == nbytes) {
/* end of file but not end of format address space */
HDmemset(buf, 0, size);
break;
- }
- assert(nbytes>=0);
- assert((size_t)nbytes<=size);
- H5_CHECK_OVERFLOW(nbytes,ssize_t,size_t);
+ } /* end if */
+ HDassert(nbytes >= 0);
+ HDassert((size_t)nbytes <= size);
+ H5_CHECK_OVERFLOW(nbytes, ssize_t, size_t);
size -= (size_t)nbytes;
- H5_CHECK_OVERFLOW(nbytes,ssize_t,haddr_t);
+ H5_CHECK_OVERFLOW(nbytes, ssize_t, haddr_t);
addr += (haddr_t)nbytes;
- buf = (char*)buf + nbytes;
- }
+ buf = (char *)buf + nbytes;
+ } /* end while */
/* Update current position */
file->pos = addr;
file->op = OP_READ;
done:
- if(ret_value<0) {
+ if(ret_value < 0) {
/* Reset last file I/O information */
file->pos = HADDR_UNDEF;
file->op = OP_UNKNOWN;
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_sec2_read() */
/*-------------------------------------------------------------------------
@@ -776,14 +770,11 @@ done:
* DXPL_ID.
*
* Return: Success: Zero
- *
* Failure: -1
*
* Programmer: Robb Matzke
* Thursday, July 29, 1999
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
/* ARGSUSED */
@@ -793,64 +784,64 @@ H5FD_sec2_write(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, had
{
H5FD_sec2_t *file = (H5FD_sec2_t*)_file;
ssize_t nbytes;
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5FD_sec2_write, FAIL)
- assert(file && file->pub.cls);
- assert(buf);
+ HDassert(file && file->pub.cls);
+ HDassert(buf);
/* Check for overflow conditions */
- if (HADDR_UNDEF==addr)
+ if(!H5F_addr_defined(addr))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "addr undefined")
- if (REGION_OVERFLOW(addr, size))
+ if(REGION_OVERFLOW(addr, size))
HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "addr overflow")
- if (addr+size>file->eoa)
+ if((addr + size) > file->eoa)
HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "addr overflow")
/* Seek to the correct location */
- if ((addr!=file->pos || OP_WRITE!=file->op) &&
- file_seek(file->fd, (file_offset_t)addr, SEEK_SET)<0)
+ if((addr != file->pos || OP_WRITE != file->op) &&
+ HDlseek(file->fd, (file_offset_t)addr, SEEK_SET) < 0)
HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position")
/*
* Write the data, being careful of interrupted system calls and partial
* results
*/
- while (size>0) {
+ while(size > 0) {
do {
nbytes = HDwrite(file->fd, buf, size);
- } while (-1==nbytes && EINTR==errno);
- if (-1==nbytes) /* error */
+ } while(-1 == nbytes && EINTR == errno);
+ if(-1 == nbytes) /* error */
HSYS_GOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
- assert(nbytes>0);
- assert((size_t)nbytes<=size);
- H5_CHECK_OVERFLOW(nbytes,ssize_t,size_t);
+ HDassert(nbytes > 0);
+ HDassert((size_t)nbytes <= size);
+ H5_CHECK_OVERFLOW(nbytes, ssize_t, size_t);
size -= (size_t)nbytes;
- H5_CHECK_OVERFLOW(nbytes,ssize_t,haddr_t);
+ H5_CHECK_OVERFLOW(nbytes, ssize_t, haddr_t);
addr += (haddr_t)nbytes;
- buf = (const char*)buf + nbytes;
- }
+ buf = (const char *)buf + nbytes;
+ } /* end while */
/* Update current position and eof */
file->pos = addr;
file->op = OP_WRITE;
- if (file->pos>file->eof)
+ if(file->pos > file->eof)
file->eof = file->pos;
done:
- if(ret_value<0) {
+ if(ret_value < 0) {
/* Reset last file I/O information */
file->pos = HADDR_UNDEF;
file->op = OP_UNKNOWN;
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_sec2_write() */
/*-------------------------------------------------------------------------
- * Function: H5FD_sec2_flush
+ * Function: H5FD_sec2_truncate
*
* Purpose: Makes sure that the true file size is the same (or larger)
* than the end-of-address.
@@ -862,23 +853,24 @@ done:
* Programmer: Robb Matzke
* Wednesday, August 4, 1999
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
/* ARGSUSED */
static herr_t
-H5FD_sec2_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing)
+H5FD_sec2_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t UNUSED closing)
{
- H5FD_sec2_t *file = (H5FD_sec2_t*)_file;
- herr_t ret_value=SUCCEED; /* Return value */
+ H5FD_sec2_t *file = (H5FD_sec2_t*)_file;
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5FD_sec2_flush, FAIL)
+ FUNC_ENTER_NOAPI(H5FD_sec2_truncate, FAIL)
+#ifdef QAK
+HDfprintf(stderr, "%s: file->eof = %a, file->eoa = %a\n", FUNC, file->eof, file->eoa);
+#endif /* QAK */
- assert(file);
+ HDassert(file);
/* Extend the file to make sure it's large enough */
- if (file->eoa!=file->eof) {
+ if(!H5F_addr_eq(file->eoa, file->eof)) {
#ifdef _WIN32
HFILE filehandle; /* Windows file handle */
LARGE_INTEGER li; /* 64-bit integer for SetFilePointer() call */
@@ -889,11 +881,18 @@ H5FD_sec2_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing)
/* Translate 64-bit integers into form Windows wants */
/* [This algorithm is from the Windows documentation for SetFilePointer()] */
li.QuadPart = (LONGLONG)file->eoa;
- (void)SetFilePointer((HANDLE)filehandle,li.LowPart,&li.HighPart,FILE_BEGIN);
- if(SetEndOfFile((HANDLE)filehandle)==0)
+ (void)SetFilePointer((HANDLE)filehandle, li.LowPart, &li.HighPart, FILE_BEGIN);
+ if(SetEndOfFile((HANDLE)filehandle) == 0)
HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
#else /* _WIN32 */
- if (-1==file_truncate(file->fd, (file_offset_t)file->eoa))
+#ifdef H5_VMS
+ /* Reset seek offset to the beginning of the file, so that the file isn't
+ * re-extended later. This may happen on Open VMS. */
+ if(HDlseek(file->fd, (file_offset_t)0, SEEK_SET) < 0)
+ HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position")
+#endif
+
+ if(-1 == HDftruncate(file->fd, (file_offset_t)file->eoa))
HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
#endif /* _WIN32 */
@@ -903,8 +902,8 @@ H5FD_sec2_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing)
/* Reset last file I/O information */
file->pos = HADDR_UNDEF;
file->op = OP_UNKNOWN;
- }
+ } /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_sec2_truncate() */
diff --git a/src/H5FDspace.c b/src/H5FDspace.c
new file mode 100644
index 0000000..0fadc1e
--- /dev/null
+++ b/src/H5FDspace.c
@@ -0,0 +1,367 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5FDspace.c
+ * Jan 3 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: Space allocation routines for the file.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5FD_PACKAGE /*suppress error about including H5FDpkg */
+
+/* Interface initialization */
+#define H5_INTERFACE_INIT_FUNC H5FD_space_init_interface
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fprivate.h" /* File access */
+#include "H5FDpkg.h" /* File Drivers */
+#include "H5FDmulti.h" /* Usage-partitioned file family */
+#include "H5MMprivate.h" /* Memory management */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+/* Define this to display information about file allocations */
+/* #define H5FD_ALLOC_DEBUG */
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* Declare a free list to manage the H5FD_free_t struct */
+H5FL_DEFINE(H5FD_free_t);
+
+
+
+/*--------------------------------------------------------------------------
+NAME
+ H5FD_space_init_interface -- Initialize interface-specific information
+USAGE
+ herr_t H5FD_space_init_interface()
+
+RETURNS
+ Non-negative on success/Negative on failure
+DESCRIPTION
+ Initializes any interface-specific data or routines. (Just calls
+ H5FD_init_iterface currently).
+
+--------------------------------------------------------------------------*/
+static herr_t
+H5FD_space_init_interface(void)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_space_init_interface)
+
+ FUNC_LEAVE_NOAPI(H5FD_init())
+} /* H5FD_space_init_interface() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_extend
+ *
+ * Purpose: Extend the EOA space of a file.
+ *
+ * NOTE: Returns absolute file offset
+ *
+ * Return: Success: The address of the previous EOA.
+ * Failure: The undefined address HADDR_UNDEF
+ *
+ * Programmer: Bill Wendling
+ * Wednesday, 04. December, 2002
+ *
+ * Modifications:
+ * Vailin Choi, 29th July 2008
+ * Add 2 more parameters for handling alignment: address and size of the fragment
+ *
+ *-------------------------------------------------------------------------
+ */
+static haddr_t
+H5FD_extend(H5FD_t *file, H5FD_mem_t type, hbool_t new_block, hsize_t size, haddr_t *frag_addr, hsize_t *frag_size)
+{
+ haddr_t eoa; /* Address of end-of-allocated space */
+ hsize_t extra; /* Extra space to allocate, to align request */
+ haddr_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5FD_extend)
+
+ /* check args */
+ HDassert(file);
+ HDassert(file->cls);
+ HDassert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES);
+ HDassert(size > 0);
+
+ /* Get current end-of-allocated space address */
+ eoa = file->cls->get_eoa(file, type);
+
+ /* Compute extra space to allocate, if this is a new block and should be aligned */
+ extra = 0;
+ if(new_block && file->alignment > 1 && size >= file->threshold) {
+ hsize_t mis_align; /* Amount EOA is misaligned */
+
+ /* Check for EOA already aligned */
+ if((mis_align = (eoa % file->alignment)) > 0) {
+ extra = file->alignment - mis_align;
+ if (frag_addr) *frag_addr = eoa;
+ if (frag_size) *frag_size = extra;
+ }
+ } /* end if */
+
+ /* Add in extra allocation amount */
+ size += extra;
+
+ /* Check for overflow when extending */
+ if(H5F_addr_overflow(eoa, size) || (eoa + size) > file->maxaddr)
+ HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "file allocation request failed")
+
+ /* Set the [possibly aligned] address to return */
+ ret_value = eoa + extra;
+
+ /* Extend the end-of-allocated space address */
+ eoa += size;
+ if(file->cls->set_eoa(file, type, eoa) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "file allocation request failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_extend() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_alloc
+ *
+ * Purpose: Private version of H5FDalloc().
+ *
+ * Return: Success: The format address of the new file memory.
+ * Failure: The undefined address HADDR_UNDEF
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, August 4, 1999
+ *
+ * Modification:
+ * Vailin Choi, 29th July 2008
+ * Add two more parameters () for handling alignment: address & size of the fragment
+ *
+ *-------------------------------------------------------------------------
+ */
+haddr_t
+H5FD_alloc(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type, hsize_t size, haddr_t *frag_addr, hsize_t *frag_size)
+{
+ haddr_t ret_value = HADDR_UNDEF;
+
+ FUNC_ENTER_NOAPI(H5FD_alloc, HADDR_UNDEF)
+#ifdef H5FD_ALLOC_DEBUG
+HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size);
+#endif /* H5FD_ALLOC_DEBUG */
+
+ /* check args */
+ HDassert(file);
+ HDassert(file->cls);
+ HDassert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES);
+ HDassert(size > 0);
+
+ /* Dispatch to driver `alloc' callback or extend the end-of-address marker */
+ if(file->cls->alloc) {
+ if((ret_value = (file->cls->alloc)(file, type, dxpl_id, size)) == HADDR_UNDEF)
+ HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "driver allocation request failed")
+ } /* end if */
+ else {
+ if((ret_value = H5FD_extend(file, type, TRUE, size, frag_addr, frag_size)) == HADDR_UNDEF)
+ HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "driver eoa update request failed")
+ } /* end else */
+
+ /* Convert absolute file offset to relative address */
+ ret_value -= file->base_addr;
+
+done:
+#ifdef H5FD_ALLOC_DEBUG
+HDfprintf(stderr, "%s: ret_value = %a\n", FUNC, ret_value);
+#endif /* H5FD_ALLOC_DEBUG */
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_alloc() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_free
+ *
+ * Purpose: Private version of H5FDfree()
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, August 4, 1999
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FD_free(H5FD_t *file, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr, hsize_t size)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5FD_free, FAIL)
+
+ /* Check args */
+ HDassert(file);
+ HDassert(file->cls);
+ HDassert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES);
+ HDassert(size > 0);
+
+#ifdef H5FD_ALLOC_DEBUG
+HDfprintf(stderr, "%s: type = %u, addr = %a, size = %Hu\n", FUNC, (unsigned)type, addr, size);
+#endif /* H5FD_ALLOC_DEBUG */
+
+ /* Sanity checking */
+ if(!H5F_addr_defined(addr))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file offset")
+
+ /* Convert address to absolute file offset */
+ addr += file->base_addr;
+
+ /* More sanity checking */
+ if(addr > file->maxaddr || H5F_addr_overflow(addr, size) || (addr + size) > file->maxaddr)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file free space region to free")
+
+ /* Check for file driver 'free' callback and call it if available */
+ if(file->cls->free) {
+#ifdef H5FD_ALLOC_DEBUG
+HDfprintf(stderr, "%s: Letting VFD free space\n", FUNC);
+#endif /* H5FD_ALLOC_DEBUG */
+ if((file->cls->free)(file, type, dxpl_id, addr, size) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "driver free request failed")
+ } /* end if */
+ /* Check if this free block is at the end of file allocated space.
+ * Truncate it if this is true.
+ */
+ else if(file->cls->get_eoa) {
+ haddr_t eoa;
+
+ eoa = file->cls->get_eoa(file, type);
+#ifdef H5FD_ALLOC_DEBUG
+HDfprintf(stderr, "%s: eoa = %a\n", FUNC, eoa);
+#endif /* H5FD_ALLOC_DEBUG */
+ if(eoa == (addr + size)) {
+#ifdef H5FD_ALLOC_DEBUG
+HDfprintf(stderr, "%s: Reducing file size to = %a\n", FUNC, addr);
+#endif /* H5FD_ALLOC_DEBUG */
+ if(file->cls->set_eoa(file, type, addr) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "set end of space allocation request failed")
+ } /* end if */
+ } /* end else-if */
+ else {
+ /* leak memory */
+#ifdef H5FD_ALLOC_DEBUG
+HDfprintf(stderr, "%s: LEAKED MEMORY!!! type = %u, addr = %a, size = %Hu\n", FUNC, (unsigned)type, addr, size);
+#endif /* H5FD_ALLOC_DEBUG */
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_free() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_try_extend
+ *
+ * Purpose: Extend a block at the end of the file, if possible.
+ *
+ * Return: Success: TRUE(1) - Block was extended
+ * FALSE(0) - Block could not be extended
+ * Failure: FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, 17. January, 2008
+ *
+ * Modification:
+ * Vailin Choi, 29th July 2008
+ * Two more parameters were added to FD_extend() for handling alignment
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5FD_try_extend(H5FD_t *file, H5FD_mem_t type, haddr_t blk_end, hsize_t extra_requested)
+{
+ haddr_t eoa; /* End of allocated space in file */
+ htri_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5FD_try_extend, FAIL)
+
+ /* check args */
+ HDassert(file);
+ HDassert(file->cls);
+ HDassert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES);
+ HDassert(extra_requested > 0);
+
+ /* Retrieve the end of the address space */
+ if(HADDR_UNDEF == (eoa = file->cls->get_eoa(file, type)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "driver get_eoa request failed")
+
+ /* Adjust block end by base address of the file, to create absolute address */
+ blk_end += file->base_addr;
+
+ /* Check if the block is exactly at the end of the file */
+ if(H5F_addr_eq(blk_end, eoa)) {
+ /* Extend the object by extending the underlying file */
+ if(HADDR_UNDEF == H5FD_extend(file, type, FALSE, extra_requested, NULL, NULL))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTEXTEND, FAIL, "driver extend request failed")
+
+ /* Indicate success */
+ HGOTO_DONE(TRUE)
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_try_extend() */
+
diff --git a/src/H5FDstdio.c b/src/H5FDstdio.c
index c66b1ab..59e5b1e 100644
--- a/src/H5FDstdio.c
+++ b/src/H5FDstdio.c
@@ -166,6 +166,7 @@ static herr_t H5FD_stdio_read(H5FD_t *lf, H5FD_mem_t type, hid_t fapl_id, haddr_
static herr_t H5FD_stdio_write(H5FD_t *lf, H5FD_mem_t type, hid_t fapl_id, haddr_t addr,
size_t size, const void *buf);
static herr_t H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing);
+static herr_t H5FD_stdio_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
static const H5FD_class_t H5FD_stdio_g = {
"stdio", /*name */
@@ -185,6 +186,7 @@ static const H5FD_class_t H5FD_stdio_g = {
H5FD_stdio_close, /*close */
H5FD_stdio_cmp, /*cmp */
H5FD_stdio_query, /*query */
+ NULL, /*get_type_map */
H5FD_stdio_alloc, /*alloc */
NULL, /*free */
H5FD_stdio_get_eoa, /*get_eoa */
@@ -194,6 +196,7 @@ static const H5FD_class_t H5FD_stdio_g = {
H5FD_stdio_read, /*read */
H5FD_stdio_write, /*write */
H5FD_stdio_flush, /*flush */
+ H5FD_stdio_truncate, /*truncate */
NULL, /*lock */
NULL, /*unlock */
H5FD_FLMAP_SINGLE /*fl_map */
@@ -370,7 +373,7 @@ H5FD_stdio_open( const char *name, unsigned flags, hid_t fapl_id,
H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_CANTOPENFILE, "fopen failed", NULL)
/* Build the return value */
- if(NULL==(file = calloc((size_t)1, sizeof(H5FD_stdio_t))))
+ if(NULL == (file = (H5FD_stdio_t *)calloc((size_t)1, sizeof(H5FD_stdio_t))))
H5Epush_ret(func, H5E_ERR_CLS, H5E_RESOURCE, H5E_NOSPACE, "memory allocation failed", NULL)
file->fp = f;
file->op = H5FD_STDIO_OP_SEEK;
@@ -539,8 +542,8 @@ H5FD_stdio_query(const H5FD_t *_f, unsigned long *flags /* out */)
/*-------------------------------------------------------------------------
* Function: H5FD_stdio_alloc
*
- * Purpose: Allocates file memory. If fseeko isn't available, makes
- * sure the file size isn't bigger than 2GB because the
+ * Purpose: Allocates file memory. If fseeko isn't available, makes
+ * sure the file size isn't bigger than 2GB because the
* parameter OFFSET of fseek is of the type LONG INT, limiting
* the file size to 2GB.
*
@@ -584,7 +587,7 @@ H5FD_stdio_alloc(H5FD_t *_file, H5FD_mem_t /*UNUSED*/ type, hid_t /*UNUSED*/ dxp
/* If fseeko isn't available, big files (>2GB) won't be supported. */
if((addr + size) > BIG_FILE)
H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_SEEKERROR, "can't write file bigger than 2GB because fseeko isn't available", HADDR_UNDEF)
-#endif
+#endif
file->eoa = addr + size;
@@ -943,19 +946,63 @@ H5FD_stdio_write(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr,
* Programmer: Robb Matzke
* Wednesday, October 22, 1997
*
- * Modifications:
- * Ported to VFL/H5FD layer - QAK, 10/18/99
- *
*-------------------------------------------------------------------------
*/
static herr_t
H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing)
{
H5FD_stdio_t *file = (H5FD_stdio_t*)_file;
- static const char *func="H5FD_stdio_flush"; /* Function Name for error reporting */
+ static const char *func = "H5FD_stdio_flush"; /* Function Name for error reporting */
/* Shut compiler up */
- dxpl_id=dxpl_id;
+ dxpl_id = dxpl_id;
+
+ /* Clear the error stack */
+ H5Eclear2(H5E_DEFAULT);
+
+ /* Only try to flush the file if we have write access */
+ if(file->write_access) {
+ /* Flush */
+ if(!closing) {
+ if(fflush(file->fp) < 0)
+ H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_WRITEERROR, "fflush failed", -1)
+
+ /* Reset last file I/O information */
+ file->pos = HADDR_UNDEF;
+ file->op = H5FD_STDIO_OP_UNKNOWN;
+ } /* end if */
+ } /* end if */
+
+ return(0);
+} /* end H5FD_stdio_flush() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_stdio_truncate
+ *
+ * Purpose: Makes sure that the true file size is the same (or larger)
+ * than the end-of-address.
+ *
+ * Errors:
+ * IO SEEKERROR fseek failed.
+ * IO WRITEERROR fflush or fwrite failed.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, January 31, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_stdio_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing)
+{
+ H5FD_stdio_t *file = (H5FD_stdio_t*)_file;
+ static const char *func = "H5FD_stdio_truncate"; /* Function Name for error reporting */
+
+ /* Shut compiler up */
+ dxpl_id = dxpl_id;
+ closing = closing;
/* Clear the error stack */
H5Eclear2(H5E_DEFAULT);
@@ -963,9 +1010,10 @@ H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing)
/* Only try to flush the file if we have write access */
if(file->write_access) {
/* Makes sure that the true file size is the same as the end-of-address. */
- if (file->eoa!=file->eof) {
+ if(file->eoa != file->eof) {
+ int fd = fileno(file->fp); /* File descriptor for HDF5 file */
+
#ifdef _WIN32
- int fd=_fileno(file->fp); /* File descriptor for HDF5 file */
HFILE filehandle; /* Windows file handle */
LARGE_INTEGER li; /* 64-bit integer for SetFilePointer() call */
@@ -975,14 +1023,16 @@ H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing)
/* Translate 64-bit integers into form Windows wants */
/* [This algorithm is from the Windows documentation for SetFilePointer()] */
li.QuadPart = (LONGLONG)file->eoa;
- (void)SetFilePointer((HANDLE)filehandle,li.LowPart,&li.HighPart,FILE_BEGIN);
- if(SetEndOfFile((HANDLE)filehandle)==0)
- H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_SEEKERROR, "unable to extend file properly", -1)
+ (void)SetFilePointer((HANDLE)filehandle, li.LowPart, &li.HighPart, FILE_BEGIN);
+ if(SetEndOfFile((HANDLE)filehandle) == 0)
+ H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_SEEKERROR, "unable to truncate/extend file properly", -1)
#else /* _WIN32 */
- int fd=fileno(file->fp); /* File descriptor for HDF5 file */
+ /* Reset seek offset to beginning of file, so that file isn't re-extended later */
+ rewind(file->fp);
- if (-1==file_truncate(fd, (file_offset_t)file->eoa))
- H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_SEEKERROR, "unable to extend file properly", -1)
+ /* Truncate file to proper length */
+ if(-1 == file_truncate(fd, (file_offset_t)file->eoa))
+ H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_SEEKERROR, "unable to truncate/extend file properly", -1)
#endif /* _WIN32 */
/* Update the eof value */
@@ -992,23 +1042,15 @@ H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing)
file->pos = HADDR_UNDEF;
file->op = H5FD_STDIO_OP_UNKNOWN;
} /* end if */
-
- /*
- * Flush
- */
- if(!closing) {
- if (fflush(file->fp) < 0)
- H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_WRITEERROR, "fflush failed", -1)
- } /* end if */
} /* end if */
else {
/* Double-check for problems */
- if (file->eoa>file->eof)
+ if(file->eoa > file->eof)
H5Epush_ret(func, H5E_ERR_CLS, H5E_IO, H5E_TRUNCATED, "eoa>eof!", -1)
} /* end else */
return(0);
-}
+} /* end H5FD_stdio_truncate() */
#ifdef _H5private_H
@@ -1019,3 +1061,4 @@ H5FD_stdio_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing)
*/
#error "Do not use HDF5 private definitions"
#endif
+
diff --git a/src/H5FDstream.c b/src/H5FDstream.c
deleted file mode 100644
index 82828ac..0000000
--- a/src/H5FDstream.c
+++ /dev/null
@@ -1,1170 +0,0 @@
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Copyright by The HDF Group. *
- * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
- * access to either file, you may request a copy from help@hdfgroup.org. *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-/*
- * Copyright © 2000 The author.
- * The author prefers this code not be used for military purposes.
- *
- *
- * Author: Thomas Radke <tradke@aei-potsdam.mpg.de>
- * Tuesday, September 12, 2000
- *
- * Purpose: This code provides the Stream Virtual File Driver.
- * It is very much based on the core VFD which keeps an
- * entire HDF5 data file to be processed in main memory.
- * In addition to that, the memory image of the file is
- * read from/written to a socket during an open/flush operation.
- *
- * Modifications:
- * Thomas Radke, Thursday, October 26, 2000
- * Added support for Windows.
- * Catch SIGPIPE on an open socket.
- *
- */
-
-/* Interface initialization */
-#define H5_INTERFACE_INIT_FUNC H5FD_stream_init_interface
-
-
-#include "H5private.h" /* Generic Functions */
-#include "H5Eprivate.h" /* Error handling */
-#include "H5FDprivate.h" /* File drivers */
-#include "H5FDstream.h" /* Stream file driver */
-#include "H5Iprivate.h" /* IDs */
-#include "H5MMprivate.h" /* Memory management */
-#include "H5Pprivate.h" /* Property lists */
-
-/* Only build this driver if it was configured with --with-Stream-VFD */
-#ifdef H5_HAVE_STREAM
-
-#ifdef H5FD_STREAM_HAVE_UNIX_SOCKETS
-#ifdef H5_HAVE_SYS_TYPES_H
-#include <sys/types.h> /* socket stuff */
-#endif
-#ifdef H5_HAVE_SYS_SOCKET_H
-#include <sys/socket.h> /* socket stuff */
-#endif
-#include <netdb.h> /* gethostbyname */
-#include <netinet/in.h> /* socket stuff */
-#ifdef H5_HAVE_NETINET_TCP_H
-#include <netinet/tcp.h> /* socket stuff */
-#endif
-#ifdef H5_HAVE_SYS_FILIO_H
-#include <sys/filio.h> /* socket stuff */
-#endif
-#endif
-
-/*
- * WinXP x64 does not define EWOULDBLOCK, but instead uses
- * their own Windows-specific macro, so define it here.
- */
- #ifdef _WIN32
- #ifndef EWOULDBLOCK
- #define EWOULDBLOCK WSAEWOULDBLOCK
- #endif /* EWOULDBLOCK */
- #endif /* _WIN32 */
-
-#ifndef H5_HAVE_SOCKLEN_T
-typedef int socklen_t;
-#endif
-
-/* Some useful macros */
-#ifdef MIN
-#undef MIN
-#endif
-#ifdef MAX
-#undef MAX
-#endif
-#define MIN(x,y) ((x) < (y) ? (x) : (y))
-#define MAX(x,y) ((x) > (y) ? (x) : (y))
-
-/* Uncomment this to switch on debugging output */
-/* #define DEBUG 1 */
-
-/* Define some socket stuff which is different for UNIX and Windows */
-#ifdef H5FD_STREAM_HAVE_UNIX_SOCKETS
-#define H5FD_STREAM_CLOSE_SOCKET(a) close(a)
-#define H5FD_STREAM_IOCTL_SOCKET(a, b, c) ioctl(a, b, c)
-#define H5FD_STREAM_ERROR_CHECK(rc) ((rc) < 0)
-#else
-#define H5FD_STREAM_CLOSE_SOCKET(a) closesocket (a)
-#define H5FD_STREAM_IOCTL_SOCKET(a, b, c) ioctlsocket (a, b, (u_long *) (c))
-#define H5FD_STREAM_ERROR_CHECK(rc) ((rc) == (SOCKET) (SOCKET_ERROR))
-#endif
-
-
-/* The driver identification number, initialized at runtime */
-static hid_t H5FD_STREAM_g = 0;
-
-/*
- * The description of a file belonging to this driver. The `eoa' and `eof'
- * determine the amount of hdf5 address space in use and the high-water mark
- * of the file (the current size of the underlying memory).
- */
-typedef struct H5FD_stream_t
-{
- H5FD_t pub; /* public stuff, must be first */
- H5FD_stream_fapl_t fapl; /* file access property list */
- unsigned char *mem; /* the underlying memory */
- haddr_t eoa; /* end of allocated region */
- haddr_t eof; /* current allocated size */
- H5FD_STREAM_SOCKET_TYPE socket; /* socket to write / read from */
- hbool_t dirty; /* flag indicating unflushed data */
- hbool_t internal_socket; /* flag indicating an internal socket */
-} H5FD_stream_t;
-
-/* Allocate memory in multiples of this size (in bytes) by default */
-#define H5FD_STREAM_INCREMENT 8192
-
-/* default backlog argument for listen call */
-#define H5FD_STREAM_BACKLOG 1
-
-/* number of successive ports to hunt for until bind(2) succeeds
- (default 0 means no port hunting - only try the one given in the filename) */
-#define H5FD_STREAM_MAXHUNT 0
-
-/* default file access property list */
-static const H5FD_stream_fapl_t default_fapl =
-{
- H5FD_STREAM_INCREMENT, /* address space allocation blocksize */
- H5FD_STREAM_INVALID_SOCKET, /* no external socket descriptor */
- TRUE, /* enable I/O on socket */
- H5FD_STREAM_BACKLOG, /* default backlog for listen(2) */
- NULL, /* do not broadcast received files */
- NULL, /* argument to READ broadcast routine */
- H5FD_STREAM_MAXHUNT, /* default number of ports to hunt */
- 0 /* unknown port for unbound socket */
-};
-
-/*
- * These macros check for overflow of various quantities. These macros
- * assume that file_offset_t is signed and haddr_t and size_t are unsigned.
- *
- * ADDR_OVERFLOW: Checks whether a file address of type `haddr_t'
- * is too large to be represented by the second argument
- * of the file seek function.
- *
- * SIZE_OVERFLOW: Checks whether a buffer size of type `hsize_t' is too
- * large to be represented by the `size_t' type.
- *
- * REGION_OVERFLOW: Checks whether an address and size pair describe data
- * which can be addressed entirely in memory.
- */
-#ifdef H5_HAVE_LSEEK64
-# define file_offset_t off64_t
-#else
-# define file_offset_t off_t
-#endif
-#define MAXADDR (((haddr_t)1<<(8*sizeof(file_offset_t)-1))-1)
-#define ADDR_OVERFLOW(A) (HADDR_UNDEF==(A) || \
- ((A) & ~(haddr_t)MAXADDR))
-#define SIZE_OVERFLOW(Z) ((Z) & ~(hsize_t)MAXADDR)
-#define REGION_OVERFLOW(A,Z) (ADDR_OVERFLOW(A) || SIZE_OVERFLOW(Z) || \
- HADDR_UNDEF==(A)+(Z) || \
- (size_t)((A)+(Z))<(size_t)(A))
-
-/* Function prototypes */
-static void *H5FD_stream_fapl_get (H5FD_t *_stream);
-static H5FD_t *H5FD_stream_open (const char *name, unsigned flags,
- hid_t fapl_id, haddr_t maxaddr);
-static herr_t H5FD_stream_flush (H5FD_t *_stream, hid_t dxpl_id, unsigned closing);
-static herr_t H5FD_stream_close (H5FD_t *_stream);
-static herr_t H5FD_stream_query(const H5FD_t *_f1, unsigned long *flags);
-static haddr_t H5FD_stream_get_eoa (const H5FD_t *_stream, H5FD_mem_t type);
-static herr_t H5FD_stream_set_eoa (H5FD_t *_stream, H5FD_mem_t type, haddr_t addr);
-static haddr_t H5FD_stream_get_eof (const H5FD_t *_stream);
-static herr_t H5FD_stream_get_handle(H5FD_t *_file, hid_t fapl, void** file_handle);
-static herr_t H5FD_stream_read (H5FD_t *_stream, H5FD_mem_t type,
- hid_t fapl_id, haddr_t addr,
- size_t size, void *buf);
-static herr_t H5FD_stream_write (H5FD_t *_stream, H5FD_mem_t type,
- hid_t fapl_id, haddr_t addr,
- size_t size, const void *buf);
-
-/* The Stream VFD's class information structure */
-static const H5FD_class_t H5FD_stream_g = {
- "stream", /*name */
- MAXADDR, /*maxaddr */
- H5F_CLOSE_WEAK, /*fc_degree */
- NULL, /*sb_size */
- NULL, /*sb_encode */
- NULL, /*sb_decode */
- sizeof (H5FD_stream_fapl_t), /*fapl_size */
- H5FD_stream_fapl_get, /*fapl_get */
- NULL, /*fapl_copy */
- NULL, /*fapl_free */
- 0, /*dxpl_size */
- NULL, /*dxpl_copy */
- NULL, /*dxpl_free */
- H5FD_stream_open, /*open */
- H5FD_stream_close, /*close */
- NULL, /*cmp */
- H5FD_stream_query, /*query */
- NULL, /*alloc */
- NULL, /*free */
- H5FD_stream_get_eoa, /*get_eoa */
- H5FD_stream_set_eoa, /*set_eoa */
- H5FD_stream_get_eof, /*get_eof */
- H5FD_stream_get_handle, /*get_handle */
- H5FD_stream_read, /*read */
- H5FD_stream_write, /*write */
- H5FD_stream_flush, /*flush */
- NULL, /*lock */
- NULL, /*unlock */
- H5FD_FLMAP_SINGLE /*fl_map */
-};
-
-
-/*--------------------------------------------------------------------------
-NAME
- H5FD_stream_init_interface -- Initialize interface-specific information
-USAGE
- herr_t H5FD_stream_init_interface()
-
-RETURNS
- Non-negative on success/Negative on failure
-DESCRIPTION
- Initializes any interface-specific data or routines. (Just calls
- H5FD_stream_init currently).
-
---------------------------------------------------------------------------*/
-static herr_t
-H5FD_stream_init_interface(void)
-{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_stream_init_interface)
-
- FUNC_LEAVE_NOAPI(H5FD_stream_init())
-} /* H5FD_stream_init_interface() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_stream_init
- *
- * Purpose: Initialize this driver by registering it with the library.
- *
- * Return: Success: The driver ID for the Stream driver.
- * Failure: Negative.
- *
- * Programmer: Thomas Radke
- * Tuesday, September 12, 2000
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-hid_t H5FD_stream_init (void)
-{
- hid_t ret_value=H5FD_STREAM_g; /* Return value */
-
- FUNC_ENTER_NOAPI(H5FD_stream_init, FAIL)
-
- if (H5I_VFL != H5Iget_type (H5FD_STREAM_g)) {
- H5FD_STREAM_g = H5FD_register (&H5FD_stream_g,sizeof(H5FD_class_t));
-
- /* set the process signal mask to ignore SIGPIPE signals */
- /* NOTE: Windows doesn't know SIGPIPE signals that's why the #ifdef */
-#ifdef SIGPIPE
- if (signal (SIGPIPE, SIG_IGN) == SIG_ERR)
- fprintf (stderr, "Stream VFD warning: failed to set the process signal "
- "mask to ignore SIGPIPE signals\n");
-#endif
- }
-
- /* Set return value */
- ret_value=H5FD_STREAM_g;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-}
-
-
-/*---------------------------------------------------------------------------
- * Function: H5FD_stream_term
- *
- * Purpose: Shut down the VFD
- *
- * Return: <none>
- *
- * Programmer: Quincey Koziol
- * Friday, Jan 30, 2004
- *
- * Modification:
- *
- *---------------------------------------------------------------------------
- */
-void
-H5FD_stream_term(void)
-{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FD_stream_term)
-
- /* Reset VFL ID */
- H5FD_STREAM_g=0;
-
- FUNC_LEAVE_NOAPI_VOID
-} /* end H5FD_stream_term() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5Pset_fapl_stream
- *
- * Purpose: Modify the file access property list to use the Stream
- * driver defined in this source file. The INCREMENT specifies
- * how much to grow the memory each time we need more.
- * If a valid socket argument is given this will be used
- * by the driver instead of parsing the 'hostname:port' filename
- * and opening a socket internally.
- *
- * Return: Success: Non-negative
- * Failure: Negative
- *
- * Programmer: Thomas Radke
- * Tuesday, September 12, 2000
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-herr_t H5Pset_fapl_stream (hid_t fapl_id, H5FD_stream_fapl_t *fapl)
-{
- H5FD_stream_fapl_t user_fapl;
- H5P_genplist_t *plist; /* Property list pointer */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_API(H5Pset_fapl_stream, FAIL)
- H5TRACE2 ("e", "ix", fapl_id, fapl);
-
- if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS)))
- HGOTO_ERROR (H5E_PLIST, H5E_BADTYPE, FAIL, "not a fapl")
-
- if (fapl) {
- if (! fapl->do_socket_io && fapl->broadcast_fn == NULL)
- HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "read broadcast function pointer is NULL")
-
- user_fapl = *fapl;
- if (fapl->increment == 0)
- user_fapl.increment = H5FD_STREAM_INCREMENT;
- user_fapl.port = 0;
- ret_value = H5P_set_driver (plist, H5FD_STREAM, &user_fapl);
- }
- else
- ret_value = H5P_set_driver (plist, H5FD_STREAM, &default_fapl);
-
-done:
- FUNC_LEAVE_API(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5Pget_fapl_stream
- *
- * Purpose: Queries properties set by the H5Pset_fapl_stream() function.
- *
- * Return: Success: Non-negative
- * Failure: Negative
- *
- * Programmer: Thomas Radke
- * Tuesday, September 12, 2000
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-herr_t H5Pget_fapl_stream(hid_t fapl_id, H5FD_stream_fapl_t *fapl /* out */)
-{
- H5FD_stream_fapl_t *this_fapl;
- H5P_genplist_t *plist; /* Property list pointer */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_API(H5Pget_fapl_stream, FAIL)
- H5TRACE2("e","ix",fapl_id,fapl);
-
- if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS)))
- HGOTO_ERROR (H5E_PLIST, H5E_BADTYPE, FAIL, "not a fapl")
- if (H5FD_STREAM != H5P_get_driver (plist))
- HGOTO_ERROR (H5E_PLIST, H5E_BADVALUE, FAIL, "incorrect VFL driver")
- if (NULL == (this_fapl = H5P_get_driver_info (plist)))
- HGOTO_ERROR (H5E_PLIST, H5E_BADVALUE, FAIL, "bad VFL driver info")
-
- if (fapl)
- *fapl = *this_fapl;
-
-done:
- FUNC_LEAVE_API(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_stream_fapl_get
- *
- * Purpose: Returns a copy of the file access properties
- *
- * Return: Success: Ptr to new file access properties
- * Failure: NULL
- *
- * Programmer: Thomas Radke
- * Tuesday, September 12, 2000
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static void *
-H5FD_stream_fapl_get (H5FD_t *_stream)
-{
- H5FD_stream_t *stream = (H5FD_stream_t *) _stream;
- H5FD_stream_fapl_t *fapl;
- void *ret_value;
-
- FUNC_ENTER_NOAPI(H5FD_stream_fapl_get, NULL)
-
- if ((fapl = H5MM_calloc (sizeof (H5FD_stream_fapl_t))) == NULL)
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
-
- *fapl = stream->fapl;
-
- /* Set return value */
- ret_value=fapl;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-}
-
-
-static H5FD_STREAM_SOCKET_TYPE
-H5FD_stream_open_socket (const char *filename, int o_flags,
- H5FD_stream_fapl_t *fapl)
-{
- struct sockaddr_in server;
- struct hostent *he;
- H5FD_STREAM_SOCKET_TYPE sock=H5FD_STREAM_INVALID_SOCKET;
- char *hostname=NULL;
- unsigned short int first_port;
- const char *separator, *tmp;
- int on = 1;
- H5FD_STREAM_SOCKET_TYPE ret_value=H5FD_STREAM_INVALID_SOCKET;
-
- FUNC_ENTER_NOAPI_NOINIT(H5FD_stream_open_socket)
-
- /* Parse "hostname:port" from filename argument */
- for (separator = filename; *separator != ':' && *separator; separator++)
- ;
- if (separator == filename || !*separator) {
- HGOTO_ERROR(H5E_ARGS,H5E_BADVALUE,H5FD_STREAM_INVALID_SOCKET,"invalid host address")
- } else {
- tmp = separator;
- if (! tmp[1])
- HGOTO_ERROR(H5E_ARGS,H5E_BADVALUE,H5FD_STREAM_INVALID_SOCKET,"no port number")
- while (*++tmp) {
- if (! isdigit (*tmp))
- HGOTO_ERROR(H5E_ARGS,H5E_BADVALUE,H5FD_STREAM_INVALID_SOCKET,"invalid port number")
- }
- }
-
- hostname = (char *) H5MM_malloc ((size_t)(separator - filename + 1));
-
- /* Return if out of memory */
- if (hostname == NULL)
- HGOTO_ERROR(H5E_RESOURCE,H5E_NOSPACE,H5FD_STREAM_INVALID_SOCKET,"memory allocation failed")
-
- HDstrncpy (hostname, filename, (size_t)(separator - filename));
- hostname[separator - filename] = 0;
- fapl->port = atoi (separator + 1);
-
- HDmemset (&server, 0, sizeof (server));
- server.sin_family = AF_INET;
- server.sin_port = htons (fapl->port);
-
- if (! (he = gethostbyname (hostname))) {
- HGOTO_ERROR(H5E_RESOURCE,H5E_NOSPACE,H5FD_STREAM_INVALID_SOCKET,"unable to get host address")
- } else if (H5FD_STREAM_ERROR_CHECK (sock = socket (AF_INET, SOCK_STREAM, 0)))
- HGOTO_ERROR(H5E_RESOURCE,H5E_NOSPACE,H5FD_STREAM_INVALID_SOCKET,"unable to open socket")
-
- if (O_RDONLY == o_flags) {
- HDmemcpy (&server.sin_addr, he->h_addr, (size_t)he->h_length);
-#ifdef DEBUG
- fprintf (stderr, "Stream VFD: connecting to host '%s' port %d\n",
- hostname, fapl->port);
-#endif
- if (connect (sock, (struct sockaddr *) &server, (socklen_t)sizeof (server)) < 0)
- HGOTO_ERROR(H5E_RESOURCE,H5E_NOSPACE,H5FD_STREAM_INVALID_SOCKET,"unable to connect")
- }
- else {
- server.sin_addr.s_addr = INADDR_ANY;
- if (H5FD_STREAM_IOCTL_SOCKET (sock, (int)FIONBIO, &on) < 0) {
- HGOTO_ERROR(H5E_RESOURCE,H5E_NOSPACE,H5FD_STREAM_INVALID_SOCKET,"unable to set non-blocking mode for socket")
- } else if (setsockopt (sock, IPPROTO_TCP, TCP_NODELAY, (const char *) &on,
- (socklen_t)sizeof(on)) < 0) {
- HGOTO_ERROR(H5E_RESOURCE,H5E_NOSPACE,H5FD_STREAM_INVALID_SOCKET,"unable to set socket option TCP_NODELAY")
- } else if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (const char *) &on,
- (socklen_t)sizeof(on)) < 0) {
- HGOTO_ERROR(H5E_RESOURCE,H5E_NOSPACE,H5FD_STREAM_INVALID_SOCKET,"unable to set socket option SO_REUSEADDR")
- } else {
- /* Try to bind the socket to the given port.
- If maxhunt is given try some successive ports also. */
- first_port = fapl->port;
- while (fapl->port <= first_port + fapl->maxhunt) {
-#ifdef DEBUG
- fprintf (stderr, "Stream VFD: binding to port %d\n", fapl->port);
-#endif
- server.sin_port = htons (fapl->port);
- if (bind (sock, (struct sockaddr *) &server, sizeof (server)) < 0)
- fapl->port++;
- else
- break;
- }
- if (fapl->port > first_port + fapl->maxhunt) {
- fapl->port = 0;
- HGOTO_ERROR(H5E_RESOURCE,H5E_NOSPACE,H5FD_STREAM_INVALID_SOCKET,"unable to bind socket")
- }
- else if (listen (sock, fapl->backlog) < 0)
- HGOTO_ERROR(H5E_RESOURCE,H5E_NOSPACE,H5FD_STREAM_INVALID_SOCKET,"unable to listen on socket")
- }
- }
-
- /* Set return value for success */
- ret_value=sock;
-
-done:
- /* Cleanup variables */
- if(hostname!=NULL)
- hostname=H5MM_xfree(hostname);
-
- /* Clean up on error */
- if(ret_value==H5FD_STREAM_INVALID_SOCKET) {
- if (!H5FD_STREAM_ERROR_CHECK(sock))
- H5FD_STREAM_CLOSE_SOCKET(sock);
- } /* end if */
-
- FUNC_LEAVE_NOAPI(ret_value)
-}
-
-
-static herr_t
-H5FD_stream_read_from_socket (H5FD_stream_t *stream)
-{
- int size;
- size_t max_size = 0;
- unsigned char *ptr=NULL;
- herr_t ret_value=SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT(H5FD_stream_read_from_socket)
-
- stream->eof = 0;
- stream->mem = NULL;
-
- while (1) {
- if (max_size <= 0) {
- /*
- * Allocate initial buffer as increment + 1
- * to prevent unnecessary reallocation
- * if increment is exactly a multiple of the filesize
- */
- max_size = stream->fapl.increment;
- if (! stream->mem)
- max_size++;
- ptr = H5MM_realloc (stream->mem, (size_t) (stream->eof + max_size));
- if (! ptr)
- HGOTO_ERROR(H5E_RESOURCE,H5E_NOSPACE,FAIL,"unable to allocate file space buffer")
- stream->mem = ptr;
- ptr += stream->eof;
- }
-
- /* now receive the next chunk of data */
- size = recv (stream->socket, ptr, max_size, 0);
-
- if (size < 0 && (EINTR == errno || EAGAIN == errno || EWOULDBLOCK))
- continue;
- if (size < 0)
- HGOTO_ERROR(H5E_IO,H5E_READERROR,FAIL,"error reading from file from socket")
- if (! size)
- break;
- max_size -= (size_t) size;
- stream->eof += (haddr_t) size;
- ptr += size;
-#ifdef DEBUG
- fprintf (stderr, "Stream VFD: read %d bytes (%d total) from socket\n",
- size, (int) stream->eof);
-#endif
- }
-
-#ifdef DEBUG
- fprintf (stderr, "Stream VFD: read total of %d bytes from socket\n",
- (int) stream->eof);
-#endif
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_stream_open
- *
- * Purpose: Opens an HDF5 file in memory.
- *
- * Return: Success: A pointer to a new file data structure. The
- * public fields will be initialized by the
- * caller, which is always H5FD_open().
- * Failure: NULL
- *
- * Programmer: Thomas Radke
- * Tuesday, September 12, 2000
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static H5FD_t *
-H5FD_stream_open (const char *filename,
- unsigned flags,
- hid_t fapl_id,
- haddr_t maxaddr)
-{
- H5FD_stream_t *stream=NULL;
- const H5FD_stream_fapl_t *fapl;
- int o_flags;
-#ifdef _WIN32
- WSADATA wsadata;
-#endif
- H5P_genplist_t *plist=NULL; /* Property list pointer */
- H5FD_t *ret_value; /* Function return value */
-
- FUNC_ENTER_NOAPI(H5FD_stream_open, NULL)
-
- /* Check arguments */
- if (filename == NULL|| *filename == '\0')
- HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, NULL,"invalid file name")
- if (maxaddr == 0 || HADDR_UNDEF == maxaddr)
- HGOTO_ERROR (H5E_ARGS, H5E_BADRANGE, NULL, "bogus maxaddr")
- if (ADDR_OVERFLOW (maxaddr))
- HGOTO_ERROR (H5E_ARGS, H5E_OVERFLOW, NULL, "maxaddr overflow")
-
- /* Build the open flags */
- o_flags = (H5F_ACC_RDWR & flags) ? O_RDWR : O_RDONLY;
- if (H5F_ACC_TRUNC & flags) o_flags |= O_TRUNC;
- if (H5F_ACC_CREAT & flags) o_flags |= O_CREAT;
- if (H5F_ACC_EXCL & flags) o_flags |= O_EXCL;
-
- if ((O_RDWR & o_flags) && ! (O_CREAT & o_flags))
- HGOTO_ERROR (H5E_ARGS, H5E_UNSUPPORTED, NULL, "open stream for read/write not supported")
-
-#ifdef _WIN32
- if (WSAStartup (MAKEWORD (2, 0), &wsadata))
- HGOTO_ERROR (H5E_IO, H5E_CANTINIT, NULL, "Couldn't start Win32 socket layer")
-#endif
-
- fapl = NULL;
- if (H5P_FILE_ACCESS_DEFAULT != fapl_id) {
- if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list")
- fapl = H5P_get_driver_info (plist);
- }
- if (fapl == NULL)
- fapl = &default_fapl;
-
- /* Create the new file struct */
- stream = (H5FD_stream_t *) H5MM_calloc (sizeof (H5FD_stream_t));
- if (stream == NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate file struct")
- stream->fapl = *fapl;
- stream->socket = H5FD_STREAM_INVALID_SOCKET;
-
- /* if an external socket is provided with the file access property list
- we use that, otherwise the filename argument is parsed and a socket
- is opened internally */
- if (fapl->do_socket_io) {
- if (! H5FD_STREAM_ERROR_CHECK (fapl->socket)) {
- stream->internal_socket = FALSE;
- stream->socket = fapl->socket;
- }
- else {
- stream->internal_socket = TRUE;
- stream->socket = H5FD_stream_open_socket (filename, o_flags, &stream->fapl);
- if (stream->socket != H5FD_STREAM_INVALID_SOCKET) {
- /* update the port ID in the file access property
- so that it can be queried via H5P_get_fapl_stream() later on */
- H5P_set_driver (plist, H5FD_STREAM, &stream->fapl);
- }
- else
- HGOTO_ERROR(H5E_IO, H5E_CANTOPENFILE, NULL, "can't open internal socket")
- }
- }
-
- /* read the data from socket into memory */
- if (O_RDONLY == o_flags) {
- if (fapl->do_socket_io) {
-#ifdef DEBUG
- fprintf (stderr, "Stream VFD: reading file from socket\n");
-#endif
- if(H5FD_stream_read_from_socket (stream)<0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, NULL, "can't read file from socket")
- }
-
- /* Now call the user's broadcast routine if given */
- if (fapl->broadcast_fn) {
- if ((fapl->broadcast_fn) (&stream->mem, &stream->eof,
- fapl->broadcast_arg) < 0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, NULL, "broadcast error")
-
- /* check for filesize of zero bytes */
- if (stream->eof == 0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, NULL, "zero filesize")
- }
-
- /* For files which are read from a socket:
- the opened socket is not needed anymore */
- if (stream->internal_socket && ! H5FD_STREAM_ERROR_CHECK (stream->socket))
- H5FD_STREAM_CLOSE_SOCKET (stream->socket);
- stream->socket = H5FD_STREAM_INVALID_SOCKET;
- }
-
- /* Set return value on success */
- ret_value=(H5FD_t*)stream;
-
-done:
- if(ret_value==NULL) {
- if(stream!=NULL) {
- if (stream->mem)
- H5MM_xfree (stream->mem);
- if (stream->internal_socket && ! H5FD_STREAM_ERROR_CHECK (stream->socket))
- H5FD_STREAM_CLOSE_SOCKET (stream->socket);
- H5MM_xfree(stream);
- } /* end if */
- }
-
- FUNC_LEAVE_NOAPI(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_stream_flush
- *
- * Purpose: Flushes the file via sockets to any connected clients
- * if its dirty flag is set.
- *
- * Return: Success: 0
- * Failure: -1
- *
- * Programmer: Thomas Radke
- * Tuesday, September 12, 2000
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5FD_stream_flush (H5FD_t *_stream, hid_t UNUSED dxpl_id, unsigned UNUSED closing)
-{
- H5FD_stream_t *stream = (H5FD_stream_t *) _stream;
- size_t size;
- ssize_t bytes_send;
- int on = 1;
- unsigned char *ptr;
- struct sockaddr from;
- socklen_t fromlen;
- H5FD_STREAM_SOCKET_TYPE sock;
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5FD_stream_flush, FAIL)
-
- /* Write to backing store */
- if (stream->dirty && ! H5FD_STREAM_ERROR_CHECK (stream->socket)) {
-#ifdef DEBUG
- fprintf (stderr, "Stream VFD: accepting client connections\n");
-#endif
- fromlen = sizeof (from);
- while (! H5FD_STREAM_ERROR_CHECK (sock = accept (stream->socket,
- &from, &fromlen))) {
- if (H5FD_STREAM_IOCTL_SOCKET (sock, (int)FIONBIO, &on) < 0) {
- H5FD_STREAM_CLOSE_SOCKET (sock);
- continue; /* continue the loop for other clients to connect */
- }
-
- size = stream->eof;
- ptr = stream->mem;
-
- while (size) {
- bytes_send = send (sock, ptr, size, 0);
- if (bytes_send < 0) {
- if (EINTR == errno || EAGAIN == errno || EWOULDBLOCK == errno)
- continue;
-
- /* continue the outermost loop for other clients to connect */
- break;
- }
- ptr += bytes_send;
- size -= bytes_send;
-#ifdef DEBUG
- fprintf (stderr, "Stream VFD: wrote %d bytes to socket, %d in total, "
- "%d left\n", bytes_send, (int) (ptr - stream->mem), size);
-#endif
- }
- H5FD_STREAM_CLOSE_SOCKET (sock);
- }
- stream->dirty = FALSE;
- }
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_stream_close
- *
- * Purpose: Closes the file.
- *
- * Return: Success: 0
- * Failure: -1
- *
- * Programmer: Thomas Radke
- * Tuesday, September 12, 2000
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5FD_stream_close (H5FD_t *_stream)
-{
- H5FD_stream_t *stream = (H5FD_stream_t *) _stream;
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5FD_stream_close, FAIL)
-
- /* Release resources */
- if (! H5FD_STREAM_ERROR_CHECK (stream->socket) && stream->internal_socket)
- H5FD_STREAM_CLOSE_SOCKET (stream->socket);
- if (stream->mem)
- H5MM_xfree (stream->mem);
- HDmemset (stream, 0, sizeof (H5FD_stream_t));
- H5MM_xfree (stream);
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_stream_query
- *
- * Purpose: Set the flags that this VFL driver is capable of supporting.
- * (listed in H5FDpublic.h)
- *
- * Return: Success: non-negative
- *
- * Failure: negative
- *
- * Programmer: Quincey Koziol
- * Tuesday, September 26, 2000
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5FD_stream_query(const H5FD_t UNUSED * _f,
- unsigned long *flags/*out*/)
-{
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5FD_stream_query, SUCCEED)
-
- /* Set the VFL feature flags that this driver supports */
- if (flags) {
- *flags = 0;
- /* OK to perform data sieving for faster raw data reads & writes */
- *flags |= H5FD_FEAT_DATA_SIEVE;
- *flags|=H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */
- }
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_stream_get_eoa
- *
- * Purpose: Gets the end-of-address marker for the file. The EOA marker
- * is the first address past the last byte allocated in the
- * format address space.
- *
- * Return: Success: The end-of-address marker.
- * Failure: HADDR_UNDEF
- *
- * Programmer: Thomas Radke
- * Tuesday, September 12, 2000
- *
- * Modifications:
- * Raymond Lu
- * 21 Dec. 2006
- * Added the parameter TYPE. It's only used for MULTI driver.
- *
- *-------------------------------------------------------------------------
- */
-static haddr_t
-H5FD_stream_get_eoa (const H5FD_t *_stream, H5FD_mem_t UNUSED type)
-{
- const H5FD_stream_t *stream = (const H5FD_stream_t *) _stream;
- haddr_t ret_value; /* Return value */
-
- FUNC_ENTER_NOAPI(H5FD_stream_get_eoa, HADDR_UNDEF)
-
- /* Set return value */
- ret_value=stream->eoa;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_stream_set_eoa
- *
- * Purpose: Set the end-of-address marker for the file. This function is
- * called shortly after an existing HDF5 file is opened in order
- * to tell the driver where the end of the HDF5 data is located.
- *
- * Return: Success: 0
- * Failure: -1
- *
- * Programmer: Thomas Radke
- * Tuesday, September 12, 2000
- *
- * Modifications:
- * Raymond Lu
- * 21 Dec. 2006
- * Added the parameter TYPE. It's only used for MULTI driver.
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5FD_stream_set_eoa (H5FD_t *_stream, H5FD_mem_t UNUSED type, haddr_t addr)
-{
- H5FD_stream_t *stream = (H5FD_stream_t *) _stream;
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5FD_stream_set_eoa, FAIL)
-
- if (ADDR_OVERFLOW (addr))
- HGOTO_ERROR (H5E_ARGS, H5E_OVERFLOW, FAIL, "address overflow")
-
- stream->eoa = addr;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_stream_get_eof
- *
- * Purpose: Returns the end-of-file marker, which is the greater of
- * either the size of the underlying memory or the HDF5
- * end-of-address markers.
- *
- * Return: Success: End of file address, the first address past
- * the end of the "file", either the memory
- * or the HDF5 file.
- * Failure: HADDR_UNDEF
- *
- * Programmer: Thomas Radke
- * Tuesday, September 12, 2000
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static haddr_t
-H5FD_stream_get_eof (const H5FD_t *_stream)
-{
- const H5FD_stream_t *stream = (const H5FD_stream_t *) _stream;
- haddr_t ret_value; /* Return value */
-
- FUNC_ENTER_NOAPI(H5FD_stream_get_eof, HADDR_UNDEF)
-
- /* Set return value */
- ret_value= MAX (stream->eof, stream->eoa);
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_stream_get_handle
- *
- * Purpose: Returns the file handle of stream file driver.
- *
- * Returns: Non-negative if succeed or negative if fails.
- *
- * Programmer: Raymond Lu
- * Sept. 16, 2002
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5FD_stream_get_handle(H5FD_t *_file, hid_t UNUSED fapl, void** file_handle)
-{
- H5FD_stream_t *file = (H5FD_stream_t *)_file;
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI(H5FD_stream_get_handle, FAIL)
-
- if(!file_handle)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file handle not valid")
-
- *file_handle = &(file->socket);
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_stream_read
- *
- * Purpose: Reads SIZE bytes of data from FILE beginning at address ADDR
- * into buffer BUF according to data transfer properties in
- * DXPL_ID.
- *
- * Return: Success: 0
- * Result is stored in caller-supplied buffer BUF
- * Failure: -1
- * Contents of buffer BUF are undefined
- *
- * Programmer: Thomas Radke
- * Tuesday, September 12, 2000
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5FD_stream_read (H5FD_t *_stream,
- H5FD_mem_t UNUSED type,
- hid_t UNUSED dxpl_id,
- haddr_t addr,
- size_t size,
- void *buf /*out*/)
-{
- H5FD_stream_t *stream = (H5FD_stream_t *) _stream;
- size_t nbytes;
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5FD_stream_read, FAIL)
-
- assert (stream && stream->pub.cls);
- assert (buf);
-
- /* Check for overflow conditions */
- if (HADDR_UNDEF == addr)
- HGOTO_ERROR (H5E_IO, H5E_OVERFLOW, FAIL, "file address overflowed")
- if (REGION_OVERFLOW (addr, size))
- HGOTO_ERROR (H5E_IO, H5E_OVERFLOW, FAIL, "file address overflowed")
- if (addr + size > stream->eoa)
- HGOTO_ERROR (H5E_IO, H5E_OVERFLOW, FAIL, "file address overflowed")
-
- /* Read the part which is before the EOF marker */
- if (addr < stream->eof) {
- nbytes = MIN (size, stream->eof - addr);
- HDmemcpy (buf, stream->mem + addr, nbytes);
- size -= nbytes;
- addr += nbytes;
- buf = (char *) buf + nbytes;
- }
-
- /* Read zeros for the part which is after the EOF markers */
- if (size > 0)
- HDmemset (buf, 0, size);
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_stream_write
- *
- * Purpose: Writes SIZE bytes of data to FILE beginning at address ADDR
- * from buffer BUF according to data transfer properties in
- * DXPL_ID.
- *
- * Return: Success: Zero
- * Failure: -1
- *
- * Programmer: Thomas Radke
- * Tuesday, September 12, 2000
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5FD_stream_write (H5FD_t *_stream,
- H5FD_mem_t UNUSED type,
- hid_t UNUSED dxpl_id,
- haddr_t addr,
- size_t size,
- const void *buf)
-{
- H5FD_stream_t *stream = (H5FD_stream_t *) _stream;
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5FD_stream_write, FAIL)
-
- assert (stream && stream->pub.cls);
- assert (buf);
-
- /* Check for overflow conditions */
- if (REGION_OVERFLOW (addr, size))
- HGOTO_ERROR (H5E_IO, H5E_OVERFLOW, FAIL, "file address overflowed")
- if (addr + size > stream->eoa)
- HGOTO_ERROR (H5E_IO, H5E_OVERFLOW, FAIL, "file address overflowed")
-
- /*
- * Allocate more memory if necessary, careful of overflow. Also, if the
- * allocation fails then the file should remain in a usable state. Be
- * careful of non-Posix realloc() that doesn't understand what to do when
- * the first argument is null.
- */
- if (addr + size > stream->eof) {
- unsigned char *x;
- haddr_t new_eof = stream->fapl.increment *
- ((addr+size) / stream->fapl.increment);
-
- if ((addr+size) % stream->fapl.increment)
- new_eof += stream->fapl.increment;
- if (stream->mem == NULL)
- x = H5MM_malloc ((size_t) new_eof);
- else
- x = H5MM_realloc (stream->mem, (size_t) new_eof);
- if (x == NULL)
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory block")
- stream->mem = x;
- stream->eof = new_eof;
- }
-
- /* Write from BUF to memory */
- HDmemcpy (stream->mem + addr, buf, size);
- stream->dirty = TRUE;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-}
-
-#endif /* H5_HAVE_STREAM */
diff --git a/src/H5FDstream.h b/src/H5FDstream.h
deleted file mode 100644
index 3f3ba6a..0000000
--- a/src/H5FDstream.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Copyright by The HDF Group. *
- * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
- * access to either file, you may request a copy from help@hdfgroup.org. *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-/*
- * Copyright © 2000 The author.
- * The author prefers this code not be used for military purposes.
- *
- *
- * Author: Thomas Radke <tradke@aei-potsdam.mpg.de>
- * Tuesday, September 12, 2000
- *
- * Purpose: The public header file for the Stream Virtual File Driver.
- *
- * Modifications:
- * Thomas Radke, Thursday, October 26, 2000
- * Added support for Windows.
- *
- */
-#ifndef H5FDstream_H
-#define H5FDstream_H
-
-#ifdef H5_HAVE_STREAM
-# define H5FD_STREAM (H5FD_stream_init())
-#else
-# define H5FD_STREAM (-1)
-#endif /*H5_HAVE_STREAM */
-
-#ifdef H5_HAVE_STREAM
-/* check what sockets type we have (Unix or Windows sockets)
- Note that only MS compilers require to use Windows sockets
- but gcc under Windows does not. */
-#if ! defined(H5_HAVE_WINSOCK_H) || defined(__GNUC__)
-#define H5FD_STREAM_HAVE_UNIX_SOCKETS 1
-#endif
-
-/* define the data type for socket descriptors
- and the constant indicating an invalid descriptor */
-#ifdef H5FD_STREAM_HAVE_UNIX_SOCKETS
-
-#define H5FD_STREAM_SOCKET_TYPE int
-#define H5FD_STREAM_INVALID_SOCKET -1
-
-#else
-#include <winsock.h>
-
-#define H5FD_STREAM_SOCKET_TYPE SOCKET
-#define H5FD_STREAM_INVALID_SOCKET INVALID_SOCKET
-
-#endif
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* prototype for read broadcast callback routine */
-typedef int (*H5FD_stream_broadcast_t) (unsigned char **file,
- haddr_t *len,
- void *arg);
-
-/* driver-specific file access properties */
-typedef struct H5FD_stream_fapl_t
-{
- size_t increment; /* how much to grow memory in reallocs */
- H5FD_STREAM_SOCKET_TYPE socket; /* externally provided socket descriptor*/
- hbool_t do_socket_io; /* do I/O on socket */
- int backlog; /* backlog argument for listen call */
- H5FD_stream_broadcast_t broadcast_fn; /* READ broadcast callback */
- void *broadcast_arg; /* READ broadcast callback user argument*/
- unsigned int maxhunt; /* how many more ports to try to bind to*/
- unsigned short int port; /* port a socket was bound/connected to */
-} H5FD_stream_fapl_t;
-
-
-/* prototypes of exported functions */
-H5_DLL hid_t H5FD_stream_init (void);
-H5_DLL void H5FD_stream_term(void);
-H5_DLL herr_t H5Pset_fapl_stream (hid_t fapl_id,
- H5FD_stream_fapl_t *fapl);
-H5_DLL herr_t H5Pget_fapl_stream (hid_t fapl_id,
- H5FD_stream_fapl_t *fapl /*out*/ );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* H5_HAVE_STREAM */
-
-#endif /* H5FDstream_H */
diff --git a/src/H5FDwindows.c b/src/H5FDwindows.c
index 08a8e69..ef26fec 100644
--- a/src/H5FDwindows.c
+++ b/src/H5FDwindows.c
@@ -20,11 +20,11 @@
*
* Purpose: We would like to create a driver specifically for Windows
* to utilize the Win32 API, and reduce the maintenence demands
- * for the other file drivers. Our other motivation is that
+ * for the other file drivers. Our other motivation is that
* the Windows system calls of the existing sec2 driver differ
* from those on other platforms, and are not 64-bit compatible.
- * From the start, this will have the structure very similar
- * to our sec2 driver, but make system calls more similar to
+ * From the start, this will have the structure very similar
+ * to our sec2 driver, but make system calls more similar to
* our stdio driver.
*/
@@ -66,7 +66,7 @@ static hid_t H5FD_WINDOWS_g = 0;
*/
typedef struct H5FD_windows_t {
H5FD_t pub; /*public stuff, must be first */
- /*
+ /*
* .NET doesn't support our 64-bit safe stdio functions,
* so we will use io.h functions instead.
*/
@@ -96,7 +96,7 @@ typedef struct H5FD_windows_t {
/* These are used by the macros below */
-#define file_offset_t __int64
+#define file_offset_t __int64
#define fseek_offset_t __int64
/*
@@ -128,7 +128,7 @@ static H5FD_t *H5FD_windows_open(const char *name, unsigned flags, hid_t fapl_id
static herr_t H5FD_windows_close(H5FD_t *_file);
static int H5FD_windows_cmp(const H5FD_t *_f1, const H5FD_t *_f2);
static herr_t H5FD_windows_query(const H5FD_t *_f1, unsigned long *flags);
-static haddr_t H5FD_windows_alloc(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id,
+static haddr_t H5FD_windows_alloc(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id,
hsize_t size);
static haddr_t H5FD_windows_get_eoa(const H5FD_t *_file, H5FD_mem_t type);
static herr_t H5FD_windows_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t addr);
@@ -139,11 +139,12 @@ static herr_t H5FD_windows_read(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, h
static herr_t H5FD_windows_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr,
size_t size, const void *buf);
static herr_t H5FD_windows_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing);
+static herr_t H5FD_windows_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
static const H5FD_class_t H5FD_windows_g = {
- "windows", /*name */
- MAXADDR, /*maxaddr */
- H5F_CLOSE_WEAK, /* fc_degree */
+ "windows", /*name */
+ MAXADDR, /*maxaddr */
+ H5F_CLOSE_WEAK, /* fc_degree */
NULL, /*sb_size */
NULL, /*sb_encode */
NULL, /*sb_decode */
@@ -154,22 +155,24 @@ static const H5FD_class_t H5FD_windows_g = {
0, /*dxpl_size */
NULL, /*dxpl_copy */
NULL, /*dxpl_free */
- H5FD_windows_open, /*open */
- H5FD_windows_close, /*close */
- H5FD_windows_cmp, /*cmp */
- H5FD_windows_query, /*query */
+ H5FD_windows_open, /*open */
+ H5FD_windows_close, /*close */
+ H5FD_windows_cmp, /*cmp */
+ H5FD_windows_query, /*query */
+ NULL, /*get_type_map */
NULL, /*alloc */
NULL, /*free */
- H5FD_windows_get_eoa, /*get_eoa */
- H5FD_windows_set_eoa, /*set_eoa */
- H5FD_windows_get_eof, /*get_eof */
- H5FD_windows_get_handle,/*get_handle */
- H5FD_windows_read, /*read */
- H5FD_windows_write, /*write */
- H5FD_windows_flush, /*flush */
- NULL, /*lock */
- NULL, /*unlock */
- H5FD_FLMAP_SINGLE /*fl_map */
+ H5FD_windows_get_eoa, /*get_eoa */
+ H5FD_windows_set_eoa, /*set_eoa */
+ H5FD_windows_get_eof, /*get_eof */
+ H5FD_windows_get_handle, /*get_handle */
+ H5FD_windows_read, /*read */
+ H5FD_windows_write, /*write */
+ H5FD_windows_flush, /*flush */
+ H5FD_windows_truncate, /*truncate */
+ NULL, /*lock */
+ NULL, /*unlock */
+ H5FD_FLMAP_SINGLE /*fl_map */
};
/* Declare a free list to manage the H5FD_windows_t struct */
@@ -219,7 +222,7 @@ H5FD_windows_init(void)
FUNC_ENTER_NOAPI(H5FD_windows_init, FAIL)
if(H5I_VFL != H5I_get_type(H5FD_WINDOWS_g))
- H5FD_WINDOWS_g = H5FD_register(&H5FD_windows_g, sizeof(H5FD_class_t));
+ H5FD_WINDOWS_g = H5FD_register(&H5FD_windows_g, sizeof(H5FD_class_t), FALSE);
/* Set return value */
ret_value = H5FD_WINDOWS_g;
@@ -346,7 +349,7 @@ H5FD_windows_open(const char *name, unsigned flags, hid_t UNUSED fapl_id,
if (H5F_ACC_CREAT & flags) o_flags |= O_CREAT;
if (H5F_ACC_EXCL & flags) o_flags |= O_EXCL;
/* Windows needs O_BINARY to correctly handle eol characters */
- o_flags |= O_BINARY;
+ o_flags |= O_BINARY;
/* Open the file */
if ((fd=_open(name, o_flags, 0666))<0)
@@ -388,7 +391,7 @@ H5FD_windows_open(const char *name, unsigned flags, hid_t UNUSED fapl_id,
H5_ASSIGN_OVERFLOW(file->eof,sb.st_size,h5_stat_size_t,haddr_t);
file->pos = HADDR_UNDEF;
file->op = OP_UNKNOWN;
-
+
#ifndef WINDOWS_USE_STDIO
file->fd = fd;
#else
@@ -815,7 +818,7 @@ H5FD_windows_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, h
/* end of file but not end of format address space */
HDmemset(buf, 0, size);
break;
- }
+ }
}
#endif /* WINDOWS_USE_STDIO */
assert(nbytes>=0);
@@ -941,22 +944,20 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
}
+
/*-------------------------------------------------------------------------
* Function: H5FD_windows_flush
*
* Purpose: Makes sure that the true file size is the same (or larger)
- * than the end-of-address.
+ * than the end-of-address.
*
* Return: Success: Non-negative
- *
- * Failure: Negative
+ * Failure: Negative
*
* Programmer: Scott Wegner
- * Based on code by Robb Matzke
+ * Based on code by Robb Matzke
* Thursday, May 24 2007
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
/* ARGSUSED */
@@ -964,58 +965,96 @@ static herr_t
H5FD_windows_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned closing)
{
H5FD_windows_t *file = (H5FD_windows_t*)_file;
- herr_t ret_value=SUCCEED; /* Return value */
-#ifndef WINDOWS_USE_STDIO
- LARGE_INTEGER li;
- HANDLE filehandle;
-#else
- int fd;
-#endif /* WINDOWS_USE_STDIO */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5FD_windows_flush, FAIL)
- assert(file);
+ HDassert(file);
+
+ /* Only try to flush if we have write access */
+ if(file->write_access) {
+ /* Flush */
+ if(!closing) {
+#ifdef WINDOWS_USE_STDIO
+ if(fflush(file->fp) == EOF)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "fflush failed")
+#endif /* WINDOWS_USE_STDIO */
- if (file->eoa != file->eof) {
+ /* Reset last file I/O information */
+ file->pos = HADDR_UNDEF;
+ file->op = OP_UNKNOWN;
+ } /* end if */
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_windows_flush() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_windows_truncate
+ *
+ * Purpose: Makes sure that the true file size is the same (or larger)
+ * than the end-of-address.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Scott Wegner
+ * Based on code by Robb Matzke
+ * Thursday, May 24 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static herr_t
+H5FD_windows_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t closing)
+{
+ H5FD_windows_t *file = (H5FD_windows_t*)_file;
#ifndef WINDOWS_USE_STDIO
+ LARGE_INTEGER li;
+ HANDLE filehandle;
+#else
+ int fd;
+#endif /* WINDOWS_USE_STDIO */
+ herr_t ret_value = SUCCEED; /* Return value */
- /* Extend the file to make sure it's large enough */
- if( (filehandle = (HANDLE)_get_osfhandle(file->fd)) == INVALID_HANDLE_VALUE)
- HGOTO_ERROR(H5E_FILE, H5E_FILEOPEN, FAIL, "unable to get file handle for file")
-
- li.QuadPart = (__int64)file->eoa;
- (void)SetFilePointer((HANDLE)filehandle,li.LowPart,&li.HighPart,FILE_BEGIN);
- if(SetEndOfFile(filehandle) == 0)
- HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
+ FUNC_ENTER_NOAPI(H5FD_windows_truncate, FAIL)
+ HDassert(file);
+
+ if(file->eoa != file->eof) {
+#ifndef WINDOWS_USE_STDIO
+ /* Extend the file to make sure it's large enough */
+ if((filehandle = (HANDLE)_get_osfhandle(file->fd)) == INVALID_HANDLE_VALUE)
+ HGOTO_ERROR(H5E_FILE, H5E_FILEOPEN, FAIL, "unable to get file handle for file")
+
+ li.QuadPart = (__int64)file->eoa;
+ (void)SetFilePointer((HANDLE)filehandle, li.LowPart, &li.HighPart, FILE_BEGIN);
+ if(SetEndOfFile(filehandle) == 0)
+ HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
#else /* WINDOWS_USE_STDIO */
- /* Only try to flush if we have write access */
- if(!file->write_access)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "cannot flush without write access")
-
- if((fd = _fileno(file->fp)) == -1)
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to get file descriptor for file")
- if(_chsize_s(fd, file->eoa))
- HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
-
- /* Flush */
- if(!closing)
- if (fflush(file->fp) == EOF)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "fflush failed")
+ /* Only try to flush if we have write access */
+ if(!file->write_access)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "cannot flush without write access")
+
+ if((fd = _fileno(file->fp)) == -1)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to get file descriptor for file")
+ if(_chsize_s(fd, file->eoa))
+ HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
#endif /* WINDOWS_USE_STDIO */
- /* Update the eof value */
- file->eof = file->eoa;
+ /* Update the eof value */
+ file->eof = file->eoa;
- /* Reset last file I/O information */
- file->pos = HADDR_UNDEF;
- file->op = OP_UNKNOWN;
-
- }
+ /* Reset last file I/O information */
+ file->pos = HADDR_UNDEF;
+ file->op = OP_UNKNOWN;
+ } /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5FD_windows_truncate() */
#endif /* H5_HAVE_WINDOWS */
diff --git a/src/H5FL.c b/src/H5FL.c
index ee62f94..1045658 100644
--- a/src/H5FL.c
+++ b/src/H5FL.c
@@ -212,11 +212,11 @@ H5FL_reg_init(H5FL_reg_head_t *head)
FUNC_ENTER_NOAPI_NOINIT(H5FL_reg_init)
/* Allocate a new garbage collection node */
- if (NULL==(new_node = H5MM_malloc(sizeof(H5FL_reg_gc_node_t))))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ if(NULL == (new_node = (H5FL_reg_gc_node_t *)H5MM_malloc(sizeof(H5FL_reg_gc_node_t))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Initialize the new garbage collection node */
- new_node->list=head;
+ new_node->list = head;
/* Link in to the garbage collection list */
new_node->next=H5FL_reg_gc_head.first;
@@ -481,11 +481,11 @@ H5FL_reg_gc_list(H5FL_reg_head_t *head)
H5MM_xfree(free_list);
- free_list=tmp;
+ free_list = (H5FL_reg_node_t *)tmp;
} /* end while */
/* Double check that all the memory on this list is recycled */
- assert(head->list_mem==0);
+ HDassert(0 == head->list_mem);
/* Indicate no free nodes on the free list */
head->list=NULL;
@@ -754,11 +754,11 @@ H5FL_blk_init(H5FL_blk_head_t *head)
FUNC_ENTER_NOAPI_NOINIT(H5FL_blk_init)
/* Allocate a new garbage collection node */
- if (NULL==(new_node = H5MM_malloc(sizeof(H5FL_blk_gc_node_t))))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ if(NULL == (new_node = (H5FL_blk_gc_node_t *)H5MM_malloc(sizeof(H5FL_blk_gc_node_t))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Initialize the new garbage collection node */
- new_node->pq=head;
+ new_node->pq = head;
/* Link in to the garbage collection list */
new_node->next=H5FL_blk_gc_head.first;
@@ -864,7 +864,7 @@ H5FL_blk_malloc(H5FL_blk_head_t *head, size_t size H5FL_TRACK_PARAMS)
/* No free list available, or there are no nodes on the list, allocate a new node to give to the user */
else {
/* Allocate new node, with room for the page info header and the actual page data */
- if(NULL==(temp=H5FL_malloc(sizeof(H5FL_blk_list_t) + H5FL_TRACK_SIZE + size)))
+ if(NULL == (temp = (H5FL_blk_list_t *)H5FL_malloc(sizeof(H5FL_blk_list_t) + H5FL_TRACK_SIZE + size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for chunk")
/* Increment the number of blocks allocated */
@@ -1223,22 +1223,22 @@ H5FL_blk_gc_list(H5FL_blk_head_t *head)
/* Free the block */
H5MM_xfree(list);
- list=next;
+ list = (H5FL_blk_list_t *)next;
} /* end while */
/* Free the free list node */
- H5FL_FREE(H5FL_blk_node_t,head->head);
+ (void)H5FL_FREE(H5FL_blk_node_t, head->head);
/* Advance to the next free list */
- head->head=temp;
+ head->head = (H5FL_blk_node_t *)temp;
} /* end while */
/* Indicate no free nodes on the free list */
- head->head=NULL;
- head->onlist=0;
+ head->head = NULL;
+ head->onlist = 0;
/* Double check that all the memory on this list is recycled */
- assert(head->list_mem==0);
+ HDassert(0 == head->list_mem);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5FL_blk_gc_list() */
@@ -1373,26 +1373,26 @@ H5FL_arr_init(H5FL_arr_head_t *head)
FUNC_ENTER_NOAPI_NOINIT(H5FL_arr_init)
/* Allocate a new garbage collection node */
- if (NULL==(new_node = H5MM_malloc(sizeof(H5FL_gc_arr_node_t))))
+ if(NULL == (new_node = (H5FL_gc_arr_node_t *)H5MM_malloc(sizeof(H5FL_gc_arr_node_t))))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Initialize the new garbage collection node */
- new_node->list=head;
+ new_node->list = head;
/* Link in to the garbage collection list */
new_node->next=H5FL_arr_gc_head.first;
H5FL_arr_gc_head.first=new_node;
/* Allocate room for the free lists */
- if (NULL==(head->list_arr = H5MM_calloc((size_t)head->maxelem*sizeof(H5FL_arr_node_t))))
+ if(NULL == (head->list_arr = (H5FL_arr_node_t *)H5MM_calloc((size_t)head->maxelem*sizeof(H5FL_arr_node_t))))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Initialize the size of each array */
- for(u = 0; u<(size_t)head->maxelem; u++)
+ for(u = 0; u < (size_t)head->maxelem; u++)
head->list_arr[u].size = head->base_size + (head->elem_size * u);
/* Indicate that the free list is initialized */
- head->init=1;
+ head->init = 1;
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1532,7 +1532,7 @@ H5FL_arr_malloc(H5FL_arr_head_t *head, size_t elem)
} /* end if */
/* Otherwise allocate a node */
else {
- if (NULL==(new_obj = H5FL_malloc(sizeof(H5FL_arr_list_t)+mem_size)))
+ if(NULL == (new_obj = (H5FL_arr_list_t *)H5FL_malloc(sizeof(H5FL_arr_list_t)+mem_size)))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Increment the number of blocks allocated in list */
@@ -1683,18 +1683,18 @@ H5FL_arr_gc_list(H5FL_arr_head_t *head)
/* For each free list being garbage collected, walk through the nodes and free them */
arr_free_list=head->list_arr[u].list;
while(arr_free_list!=NULL) {
- tmp=arr_free_list->next;
+ tmp = arr_free_list->next;
/* Decrement the count of nodes allocated and free the node */
head->allocated--;
H5MM_xfree(arr_free_list);
- arr_free_list=tmp;
+ arr_free_list = (H5FL_arr_list_t *)tmp;
} /* end while */
/* Indicate no free nodes on the free list */
- head->list_arr[u].list=NULL;
- head->list_arr[u].onlist=0;
+ head->list_arr[u].list = NULL;
+ head->list_arr[u].onlist = 0;
/* Decrement count of free memory on this "array" list */
head->list_mem-=total_mem;
@@ -2133,7 +2133,7 @@ H5FL_fac_term(H5FL_fac_head_t *factory)
H5FL_blk_unlink(&(factory->queue));
/* Free factory info */
- H5FL_FREE(H5FL_fac_head_t,factory);
+ (void)H5FL_FREE(H5FL_fac_head_t, factory);
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5FLprivate.h b/src/H5FLprivate.h
index 1dcced6..446c852 100644
--- a/src/H5FLprivate.h
+++ b/src/H5FLprivate.h
@@ -130,7 +130,7 @@ typedef struct H5FL_reg_head_t {
#define H5FL_CALLOC(t) (t *)H5FL_reg_calloc(&(H5FL_REG_NAME(t)) H5FL_TRACK_INFO)
/* Free an object of type 't' */
-#define H5FL_FREE(t,obj) H5FL_reg_free(&(H5FL_REG_NAME(t)),obj)
+#define H5FL_FREE(t,obj) (t *)H5FL_reg_free(&(H5FL_REG_NAME(t)),obj)
/* Re-allocating an object of type 't' is not defined, because these free-lists
* only support fixed sized types, like structs, etc..
@@ -331,7 +331,7 @@ typedef struct H5FL_seq_head_t {
#define H5FL_SEQ_CALLOC(t,elem) (t *)H5FL_seq_calloc(&(H5FL_SEQ_NAME(t)),elem H5FL_TRACK_INFO)
/* Free a sequence of type 't' */
-#define H5FL_SEQ_FREE(t,obj) H5FL_seq_free(&(H5FL_SEQ_NAME(t)),obj)
+#define H5FL_SEQ_FREE(t,obj) (t *)H5FL_seq_free(&(H5FL_SEQ_NAME(t)),obj)
/* Re-allocate a sequence of type 't' */
#define H5FL_SEQ_REALLOC(t,obj,new_elem) (t *)H5FL_seq_realloc(&(H5FL_SEQ_NAME(t)),obj,new_elem H5FL_TRACK_INFO)
diff --git a/src/H5FO.c b/src/H5FO.c
index bae7fe2..fe3eaa9 100644
--- a/src/H5FO.c
+++ b/src/H5FO.c
@@ -119,18 +119,18 @@ H5FO_opened(const H5F_t *f, haddr_t addr)
FUNC_ENTER_NOAPI_NOFUNC(H5FO_opened)
/* Sanity check */
- assert(f);
- assert(f->shared);
- assert(f->shared->open_objs);
- assert(H5F_addr_defined(addr));
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(f->shared->open_objs);
+ HDassert(H5F_addr_defined(addr));
/* Get the object node from the container */
- if((open_obj=H5SL_search(f->shared->open_objs,&addr))!=NULL) {
- ret_value=open_obj->obj;
- assert(ret_value!=NULL);
+ if(NULL != (open_obj = (H5FO_open_obj_t *)H5SL_search(f->shared->open_objs,&addr))) {
+ ret_value = open_obj->obj;
+ HDassert(ret_value != NULL);
} /* end if */
else
- ret_value=NULL;
+ ret_value = NULL;
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FO_opened() */
@@ -218,23 +218,23 @@ H5FO_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr)
FUNC_ENTER_NOAPI(H5FO_delete,FAIL)
/* Sanity check */
- assert(f);
- assert(f->shared);
- assert(f->shared->open_objs);
- assert(H5F_addr_defined(addr));
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(f->shared->open_objs);
+ HDassert(H5F_addr_defined(addr));
/* Remove from container */
- if((open_obj=H5SL_remove(f->shared->open_objs,&addr))==NULL)
+ if(NULL == (open_obj = (H5FO_open_obj_t *)H5SL_remove(f->shared->open_objs, &addr)))
HGOTO_ERROR(H5E_CACHE,H5E_CANTRELEASE,FAIL,"can't remove object from container")
/* Check if the object was deleted from the file */
if(open_obj->deleted) {
- if(H5O_delete(f, dxpl_id, addr)<0)
+ if(H5O_delete(f, dxpl_id, addr) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't delete object from file")
} /* end if */
/* Release the object information */
- H5FL_FREE(H5FO_open_obj_t,open_obj);
+ (void)H5FL_FREE(H5FO_open_obj_t, open_obj);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -275,10 +275,10 @@ H5FO_mark(const H5F_t *f, haddr_t addr, hbool_t deleted)
assert(H5F_addr_defined(addr));
/* Get the object node from the container */
- if((open_obj=H5SL_search(f->shared->open_objs,&addr))!=NULL)
- open_obj->deleted=deleted;
+ if(NULL != (open_obj = (H5FO_open_obj_t *)H5SL_search(f->shared->open_objs, &addr)))
+ open_obj->deleted = deleted;
else
- ret_value=FAIL;
+ ret_value = FAIL;
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FO_mark() */
@@ -308,19 +308,19 @@ htri_t
H5FO_marked(const H5F_t *f, haddr_t addr)
{
H5FO_open_obj_t *open_obj; /* Information about open object */
- htri_t ret_value=FAIL; /* Return value */
+ htri_t ret_value = FAIL; /* Return value */
FUNC_ENTER_NOAPI_NOFUNC(H5FO_marked)
/* Sanity check */
- assert(f);
- assert(f->shared);
- assert(f->shared->open_objs);
- assert(H5F_addr_defined(addr));
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(f->shared->open_objs);
+ HDassert(H5F_addr_defined(addr));
/* Get the object node from the container */
- if((open_obj=H5SL_search(f->shared->open_objs,&addr))!=NULL)
- ret_value=open_obj->deleted;
+ if(NULL != (open_obj = (H5FO_open_obj_t *)H5SL_search(f->shared->open_objs, &addr)))
+ ret_value = open_obj->deleted;
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FO_marked() */
@@ -441,12 +441,12 @@ H5FO_top_incr(const H5F_t *f, haddr_t addr)
HDassert(H5F_addr_defined(addr));
/* Get the object node from the container */
- if((obj_count = H5SL_search(f->obj_count, &addr)) != NULL) {
+ if(NULL != (obj_count = (H5FO_obj_count_t *)H5SL_search(f->obj_count, &addr))) {
(obj_count->count)++;
} /* end if */
else {
/* Allocate new opened object information structure */
- if((obj_count = H5FL_MALLOC(H5FO_obj_count_t)) == NULL)
+ if(NULL == (obj_count = H5FL_MALLOC(H5FO_obj_count_t)))
HGOTO_ERROR(H5E_CACHE,H5E_NOSPACE,FAIL,"memory allocation failed")
/* Assign information */
@@ -496,17 +496,17 @@ H5FO_top_decr(const H5F_t *f, haddr_t addr)
HDassert(H5F_addr_defined(addr));
/* Get the object node from the container */
- if((obj_count = H5SL_search(f->obj_count, &addr)) != NULL) {
+ if(NULL != (obj_count = (H5FO_obj_count_t *)H5SL_search(f->obj_count, &addr))) {
/* Decrement the reference count for the object */
(obj_count->count)--;
if(obj_count->count == 0) {
/* Remove from container */
- if((obj_count = H5SL_remove(f->obj_count, &addr)) == NULL)
+ if(NULL == (obj_count = (H5FO_obj_count_t *)H5SL_remove(f->obj_count, &addr)))
HGOTO_ERROR(H5E_CACHE, H5E_CANTRELEASE, FAIL, "can't remove object from container")
/* Release the object information */
- H5FL_FREE(H5FO_obj_count_t, obj_count);
+ (void)H5FL_FREE(H5FO_obj_count_t, obj_count);
} /* end if */
} /* end if */
else
@@ -550,7 +550,7 @@ H5FO_top_count(const H5F_t *f, haddr_t addr)
HDassert(H5F_addr_defined(addr));
/* Get the object node from the container */
- if((obj_count = H5SL_search(f->obj_count, &addr)) != NULL)
+ if(NULL != (obj_count = (H5FO_obj_count_t *)H5SL_search(f->obj_count, &addr)))
ret_value = obj_count->count;
else
ret_value = 0;
diff --git a/src/H5FS.c b/src/H5FS.c
index f1907b2..4282200 100644
--- a/src/H5FS.c
+++ b/src/H5FS.c
@@ -91,19 +91,25 @@ H5FL_DEFINE(H5FS_t);
* Programmer: Quincey Koziol
* Tuesday, March 7, 2006
*
+ * Modifications:
+ * Vailin Choi, July 29th, 2008
+ * Add two more parameters for handling alignment: alignment & threshhold
+ *
*-------------------------------------------------------------------------
*/
H5FS_t *
H5FS_create(H5F_t *f, hid_t dxpl_id, haddr_t *fs_addr, const H5FS_create_t *fs_create,
- size_t nclasses, const H5FS_section_class_t *classes[], void *cls_init_udata)
+ size_t nclasses, const H5FS_section_class_t *classes[], void *cls_init_udata, hsize_t alignment, hsize_t threshold)
{
H5FS_t *fspace = NULL; /* New free space structure */
H5FS_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5FS_create, NULL)
+#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: Creating free space manager, nclasses = %Zu\n", FUNC, nclasses);
+#endif /* H5FS_DEBUG */
/* Check arguments. */
- HDassert(fs_addr);
HDassert(fs_create->shrink_percent);
HDassert(fs_create->shrink_percent < fs_create->expand_percent);
HDassert(fs_create->max_sect_size);
@@ -115,11 +121,6 @@ H5FS_create(H5F_t *f, hid_t dxpl_id, haddr_t *fs_addr, const H5FS_create_t *fs_c
if(NULL == (fspace = H5FS_new(nclasses, classes, cls_init_udata)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for free space free list")
- /* Allocate space for the free space header */
- if(HADDR_UNDEF == (fspace->addr = H5MF_alloc(f, H5FD_MEM_FSPACE_HDR, dxpl_id, (hsize_t)H5FS_HEADER_SIZE(f))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "file allocation failed for free space header")
- *fs_addr = fspace->addr;
-
/* Initialize creation information for free space manager */
fspace->client = fs_create->client;
fspace->shrink_percent = fs_create->shrink_percent;
@@ -127,17 +128,39 @@ H5FS_create(H5F_t *f, hid_t dxpl_id, haddr_t *fs_addr, const H5FS_create_t *fs_c
fspace->max_sect_addr = fs_create->max_sect_addr;
fspace->max_sect_size = fs_create->max_sect_size;
- /* Cache the new free space header (pinned) */
- if(H5AC_set(f, dxpl_id, H5AC_FSPACE_HDR, fspace->addr, fspace, H5AC__PIN_ENTRY_FLAG) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, NULL, "can't add free space header to cache")
+ fspace->alignment = alignment;
+ fspace->threshold = threshold;
+
+ /* Check if the free space tracker is supposed to be persistant */
+ if(fs_addr) {
+ /* Allocate space for the free space header */
+ if(HADDR_UNDEF == (fspace->addr = H5MF_alloc(f, H5FD_MEM_FSPACE_HDR, dxpl_id, (hsize_t)H5FS_HEADER_SIZE(f))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "file allocation failed for free space header")
+
+ /* Cache the new free space header (pinned) */
+ if(H5AC_set(f, dxpl_id, H5AC_FSPACE_HDR, fspace->addr, fspace, H5AC__PIN_ENTRY_FLAG) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, NULL, "can't add free space header to cache")
+
+ /* Return free space header address to caller, if desired */
+ *fs_addr = fspace->addr;
+ } /* end if */
+
+ /* Set the reference count to 1, since we inserted the entry in the cache pinned */
+ fspace->rc = 1;
/* Set the return value */
ret_value = fspace;
+#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: fspace = %p, fspace->addr = %a\n", FUNC, fspace, fspace->addr);
+#endif /* H5FS_DEBUG */
done:
if(!ret_value && fspace)
(void)H5FS_cache_hdr_dest(f, fspace);
+#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: Leaving, ret_value = %d\n", FUNC, ret_value);
+#endif /* H5FS_DEBUG */
FUNC_LEAVE_NOAPI(ret_value)
} /* H5FS_create() */
@@ -154,21 +177,25 @@ done:
* Programmer: Quincey Koziol
* Tuesday, May 2, 2006
*
+ * Modfications:
+ *
+ * Vailin Choi, July 29th, 2008
+ * Add two more parameters for handling alignment: alignment & threshhold
+ *
*-------------------------------------------------------------------------
*/
H5FS_t *
H5FS_open(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr, size_t nclasses,
- const H5FS_section_class_t *classes[], void *cls_init_udata)
+ const H5FS_section_class_t *classes[], void *cls_init_udata, hsize_t alignment, hsize_t threshold)
{
H5FS_t *fspace = NULL; /* New free space structure */
H5FS_prot_t fs_prot; /* Information for protecting free space manager */
- unsigned fspace_status = 0; /* Free space header's status in the metadata cache */
H5FS_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5FS_open, NULL)
-#ifdef QAK
-HDfprintf(stderr, "%s: Opening free space manager, nclasses = %Zu\n", FUNC, nclasses);
-#endif /* QAK */
+#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: Opening free space manager, fs_addr = %a, nclasses = %Zu\n", FUNC, fs_addr, nclasses);
+#endif /* H5FS_DEBUG */
/* Check arguments. */
HDassert(H5F_addr_defined(fs_addr));
@@ -181,28 +208,25 @@ HDfprintf(stderr, "%s: Opening free space manager, nclasses = %Zu\n", FUNC, ncla
fs_prot.cls_init_udata = cls_init_udata;
/* Protect the free space header */
- if(NULL == (fspace = H5AC_protect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, &fs_prot, NULL, H5AC_READ)))
+ if(NULL == (fspace = (H5FS_t *)H5AC_protect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, &fs_prot, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_FSPACE, H5E_CANTPROTECT, NULL, "unable to load free space header")
-#ifdef QAK
+#ifdef H5FS_DEBUG
HDfprintf(stderr, "%s: fspace->sect_addr = %a\n", FUNC, fspace->sect_addr);
HDfprintf(stderr, "%s: fspace->sect_size = %Hu\n", FUNC, fspace->sect_size);
HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu\n", FUNC, fspace->alloc_sect_size);
HDfprintf(stderr, "%s: fspace->sinfo = %p\n", FUNC, fspace->sinfo);
-#endif /* QAK */
+HDfprintf(stderr, "%s: fspace->rc = %u\n", FUNC, fspace->rc);
+#endif /* H5FS_DEBUG */
- /* Check the free space header's status in the metadata cache */
- if(H5AC_get_entry_status(f, fs_addr, &fspace_status) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, NULL, "unable to check metadata cache status for free space header")
+ /* Increment the reference count on the free space manager header */
+ HDassert(fspace->rc <= 1);
+ if(H5FS_incr(f, fspace) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTINC, NULL, "unable to increment ref. count on free space header")
- /* If the free space header isn't already pinned, pin it now */
- /* (could still be pinned from it's section info still hanging around in the cache) */
- if(!(fspace_status & H5AC_ES__IS_PINNED)) {
- /* Pin free space header in the cache */
- if(H5AC_pin_protected_entry(f, fspace) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTPIN, NULL, "unable to pin free space header")
- } /* end if */
+ fspace->alignment = alignment;
+ fspace->threshold = threshold;
- /* Unlock free space header, now pinned */
+ /* Unlock free space header */
if(H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, fspace, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPROTECT, NULL, "unable to release free space header")
@@ -236,9 +260,9 @@ H5FS_delete(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr)
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5FS_delete, FAIL)
-#ifdef QAK
-HDfprintf(stderr, "%s: Deleting free space manager\n", FUNC);
-#endif /* QAK */
+#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: Deleting free space manager, fs_addr = %a\n", FUNC, fs_addr);
+#endif /* H5FS_DEBUG */
/* Check arguments. */
HDassert(f);
@@ -251,19 +275,22 @@ HDfprintf(stderr, "%s: Deleting free space manager\n", FUNC);
fs_prot.cls_init_udata = NULL;
/* Protect the free space header */
- if(NULL == (fspace = H5AC_protect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, &fs_prot, NULL, H5AC_WRITE)))
+ if(NULL == (fspace = (H5FS_t *)H5AC_protect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, &fs_prot, NULL, H5AC_WRITE)))
HGOTO_ERROR(H5E_FSPACE, H5E_CANTPROTECT, FAIL, "unable to protect free space header")
+ /* Sanity check */
+ HDassert(fspace->sinfo == NULL);
+
/* Delete serialized section storage, if there are any */
-#ifdef QAK
+#ifdef H5FS_DEBUG
HDfprintf(stderr, "%s: fspace->sect_addr = %a\n", FUNC, fspace->sect_addr);
-#endif /* QAK */
+#endif /* H5FS_DEBUG */
if(fspace->serial_sect_count > 0) {
unsigned sinfo_status = 0; /* Free space section info's status in the metadata cache */
/* Sanity check */
HDassert(H5F_addr_defined(fspace->sect_addr));
- HDassert(fspace->sect_size > 0);
+ HDassert(fspace->alloc_sect_size > 0);
/* Check the free space section info's status in the metadata cache */
if(H5AC_get_entry_status(f, fspace->sect_addr, &sinfo_status) < 0)
@@ -275,32 +302,28 @@ HDfprintf(stderr, "%s: fspace->sect_addr = %a\n", FUNC, fspace->sect_addr);
HDassert(!(sinfo_status & H5AC_ES__IS_PINNED));
HDassert(!(sinfo_status & H5AC_ES__IS_PROTECTED));
-#ifdef QAK
+#ifdef H5FS_DEBUG
HDfprintf(stderr, "%s: Expunging free space section info from cache\n", FUNC);
-#endif /* QAK */
+#endif /* H5FS_DEBUG */
/* Evict the free space section info from the metadata cache */
- if(H5AC_expunge_entry(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr) < 0)
+ /* (Free file space) */
+ if(H5AC_expunge_entry(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, H5AC__FREE_FILE_SPACE_FLAG) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "unable to remove free space section info from cache")
-#ifdef QAK
+#ifdef H5FS_DEBUG
HDfprintf(stderr, "%s: Done expunging free space section info from cache\n", FUNC);
-#endif /* QAK */
+#endif /* H5FS_DEBUG */
} /* end if */
-
- /* Release the space in the file */
- if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_addr, fspace->alloc_sect_size) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to release free space sections")
+ else {
+ /* Release the space in the file */
+ if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_addr, fspace->alloc_sect_size) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to release free space sections")
+ } /* end else */
} /* end if */
- /* Release header's disk space */
- if(H5MF_xfree(f, H5FD_MEM_FSPACE_HDR, dxpl_id, fs_addr, (hsize_t)H5FS_HEADER_SIZE(f))<0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to release free space header")
-
- /* Release the free space header */
- if(H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, fspace, H5AC__DELETED_FLAG) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPROTECT, FAIL, "unable to release free space header")
- fspace = NULL;
-
done:
+ if(fspace && H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, fspace, H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0)
+ HDONE_ERROR(H5E_FSPACE, H5E_CANTUNPROTECT, FAIL, "unable to release free space header")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* H5FS_delete() */
@@ -330,72 +353,143 @@ H5FS_close(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace)
/* Check arguments. */
HDassert(f);
HDassert(fspace);
-#ifdef QAK
-HDfprintf(stderr, "%s: Entering, fspace = %p, fspace->sinfo = %p\n", FUNC, fspace, fspace->sinfo);
-#endif /* QAK */
+#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: Entering, fspace = %p, fspace->addr = %a, fspace->sinfo = %p\n", FUNC, fspace, fspace->addr, fspace->sinfo);
+#endif /* H5FS_DEBUG */
/* Check if section info is valid */
+ /* (i.e. the header "owns" the section info and it's not in the cache) */
if(fspace->sinfo) {
- HDassert(H5F_addr_defined(fspace->sect_addr));
-
- /* Unpin the free space section info in the cache */
- if(H5AC_unpin_entry(f, fspace->sinfo) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPIN, FAIL, "unable to unpin free space section info")
-
- /* If there aren't any sections being managed, free the space for the sections */
-#ifdef QAK
-HDfprintf(stderr, "%s: fspace->tot_sect_count = %Hu\n", FUNC, fspace->tot_sect_count);
-#endif /* QAK */
- if(fspace->tot_sect_count == 0) {
- haddr_t old_addr; /* Old section info address */
-
- HDassert(fspace->serial_sect_count == 0);
- HDassert(fspace->ghost_sect_count == 0);
-
- /* Free previous serialized sections disk space */
- old_addr = fspace->sect_addr;
- if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, old_addr, fspace->alloc_sect_size) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to release free space sections")
+#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: fspace->tot_sect_count = %Hu, fspace->serial_sect_count = %Hu, fspace->sect_addr = %a, fspace->rc = %u\n", FUNC, fspace->tot_sect_count, fspace->serial_sect_count, fspace->sect_addr, fspace->rc);
+HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n", FUNC, fspace->alloc_sect_size, fspace->sect_size);
+#endif /* H5FS_DEBUG */
+ /* If there are sections to serialize, update them */
+ /* (if the free space manager is persistant) */
+ if(fspace->serial_sect_count > 0 && H5F_addr_defined(fspace->addr)) {
+#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: Real sections to store in file\n", FUNC);
+#endif /* H5FS_DEBUG */
+ if(fspace->sinfo->dirty) {
+ /* Check if the section info is "floating" */
+ if(!H5F_addr_defined(fspace->sect_addr)) {
+ /* Sanity check */
+ HDassert(fspace->sect_size > 0);
+
+ /* Allocate space for the section info in file */
+ if(HADDR_UNDEF == (fspace->sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_size)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections")
+ fspace->alloc_sect_size = (size_t)fspace->sect_size;
+
+ /* Mark free space header as dirty */
+ if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty")
+ } /* end if */
+ } /* end if */
+ else
+ /* Sanity check that section info has address */
+ HDassert(H5F_addr_defined(fspace->sect_addr));
+
+ /* Cache the free space section info */
+ if(H5AC_set(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, fspace->sinfo, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, FAIL, "can't add free space sections to cache")
+ } /* end if */
+ else {
+#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: NOT storing section info in file\n", FUNC);
+#endif /* H5FS_DEBUG */
+ /* Check if space for the section info is allocated */
+ if(H5F_addr_defined(fspace->sect_addr)) {
+ /* Sanity check */
+ /* (section info should only be in the file if the header is */
+ HDassert(H5F_addr_defined(fspace->addr));
- /* Reset section info */
- fspace->sect_addr = HADDR_UNDEF;
- fspace->alloc_sect_size = fspace->sect_size = 0;
+#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: Section info allocated though\n", FUNC);
+#endif /* H5FS_DEBUG */
+ /* Check if the section info is for the free space in the file */
+ /* (NOTE: This is the "bootstrapping" special case for the
+ * free space manager, to avoid freeing the space for the
+ * section info and re-creating it as a section in the
+ * manager. -QAK)
+ */
+ if(fspace->client == H5FS_CLIENT_FILE_ID) {
+ htri_t status; /* "can absorb" status for section into */
- /* Mark free space header as dirty */
- if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty")
+#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: Section info is for file free space\n", FUNC);
+#endif /* H5FS_DEBUG */
+ /* Try to shrink the file or absorb the section info into a block aggregator */
+ if((status = H5MF_try_shrink(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_addr, fspace->alloc_sect_size)) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTMERGE, FAIL, "can't check for absorbing section info")
+ else if(status == FALSE) {
+ /* Section info can't "go away", but it's free. Allow
+ * header to record it
+ */
+#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: Section info can't 'go away', header will own it\n", FUNC);
+#endif /* H5FS_DEBUG */
+ } /* end if */
+ else {
+#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: Section info went 'go away'\n", FUNC);
+#endif /* H5FS_DEBUG */
+ /* Reset section info in header */
+ fspace->sect_addr = HADDR_UNDEF;
+ fspace->alloc_sect_size = 0;
+
+ /* Mark free space header as dirty */
+ if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty")
+ } /* end else */
+ } /* end if */
+ else {
+ haddr_t old_sect_addr = fspace->sect_addr; /* Previous location of section info in file */
+ hsize_t old_alloc_sect_size = fspace->alloc_sect_size; /* Previous size of section info in file */
- /* Evict the section info from the metadata cache */
- if(H5AC_expunge_entry(f, dxpl_id, H5AC_FSPACE_SINFO, old_addr) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "unable to remove free space section info from cache")
- } /* end if */
+#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: Section info is NOT for file free space\n", FUNC);
+#endif /* H5FS_DEBUG */
+ /* Reset section info in header */
+ fspace->sect_addr = HADDR_UNDEF;
+ fspace->alloc_sect_size = 0;
+
+ /* Mark free space header as dirty */
+ if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty")
+
+ /* Free previous serialized sections disk space */
+ if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, old_sect_addr, old_alloc_sect_size) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space sections")
+ } /* end if */
+ } /* end else */
+
+ /* Destroy section info */
+ if(H5FS_cache_sinfo_dest(f, fspace->sinfo) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTCLOSEOBJ, FAIL, "unable to destroy free space section info")
+ } /* end else */
+
+ /* Reset the header's pointer to the section info */
+ fspace->sinfo = NULL;
} /* end if */
else {
- unsigned sect_status = 0; /* Free space section's status in the metadata cache */
-
- /* Check the free space section's status in the metadata cache */
- if(H5AC_get_entry_status(f, fspace->sect_addr, &sect_status) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "unable to check metadata cache status for free space header")
-
- /* If this free list header's section info is still in the cache, don't
- * unpin the header - let the section info do it, when the section
- * into is evicted from the cache. -QAK
- */
- if(!(sect_status & H5AC_ES__IN_CACHE)) {
- /* Unpin the free space header in the cache */
- /* (the section info destructor would unpin it if the section info existed) */
- if(H5AC_unpin_entry(f, fspace) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPIN, FAIL, "unable to unpin free space header")
- } /* end if */
+ /* Just sanity checks... */
+ if(fspace->serial_sect_count > 0)
+ /* Sanity check that section info has address */
+ HDassert(H5F_addr_defined(fspace->sect_addr));
+ else
+ /* Sanity check that section info doesn't have address */
+ HDassert(!H5F_addr_defined(fspace->sect_addr));
} /* end else */
- /* Reset the header's pointer to the section info, so it will get pinned again
- * if the free space header is still in the metadata cache when the free
- * space manager is re-opened.
- */
- fspace->sinfo = NULL;
+ /* Decrement the reference count on the free space manager header */
+ if(H5FS_decr(f, fspace) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTDEC, FAIL, "unable to decrement ref. count on free space header")
done:
+#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: Leaving, ret_value = %d, fspace->rc = %u\n", FUNC, ret_value, fspace->rc);
+#endif /* H5FS_DEBUG */
FUNC_LEAVE_NOAPI(ret_value)
} /* H5FS_close() */
@@ -450,6 +544,10 @@ H5FS_new(size_t nclasses, const H5FS_section_class_t *classes[],
if(fspace->sect_cls[u].init_cls)
if((fspace->sect_cls[u].init_cls)(&fspace->sect_cls[u], cls_init_udata) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, NULL, "unable to initialize section class")
+
+ /* Determine maximum class-specific serialization size for each section */
+ if(fspace->sect_cls[u].serial_size > fspace->max_cls_serial_size)
+ fspace->max_cls_serial_size = fspace->sect_cls[u].serial_size;
} /* end for */
} /* end if */
@@ -470,7 +568,7 @@ done:
*
* Purpose: Collect meta storage info used by the free space manager
*
- * Return: Success: non-negative
+ * Return: Success: non-negative
* Failure: negative
*
* Programmer: Vailin Choi
@@ -491,12 +589,141 @@ H5FS_size(const H5F_t *f, const H5FS_t *fspace, hsize_t *meta_size)
HDassert(meta_size);
/* Get the free space size info */
- *meta_size += H5FS_HEADER_SIZE(f) + fspace->alloc_sect_size;
-
- FUNC_LEAVE_NOAPI(SUCCEED)
+ *meta_size += H5FS_HEADER_SIZE(f) + (fspace->sinfo ? fspace->sect_size : fspace->alloc_sect_size);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5FS_size() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5FS_incr
+ *
+ * Purpose: Increment reference count on free space header
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * February 7, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FS_incr(H5F_t *f, H5FS_t *fspace)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5FS_incr, FAIL)
#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: Entering, fpace->addr = %a, fspace->rc = %u\n", FUNC, fspace->addr, fspace->rc);
+#endif /* H5FS_DEBUG */
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(fspace);
+
+ /* Check if we should pin the header in the cache */
+ if(fspace->rc == 0 && H5F_addr_defined(fspace->addr))
+ if(H5AC_pin_protected_entry(f, fspace) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTPIN, FAIL, "unable to pin free space header")
+
+ /* Increment reference count on header */
+ fspace->rc++;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FS_incr() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FS_decr
+ *
+ * Purpose: Decrement reference count on free space header
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * February 7, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FS_decr(H5F_t *f, H5FS_t *fspace)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5FS_decr, FAIL)
+#ifdef H5FS_DEBUG
+HDfprintf(stderr, "%s: Entering, fpace->addr = %a, fspace->rc = %u\n", FUNC, fspace->addr, fspace->rc);
+#endif /* H5FS_DEBUG */
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(fspace);
+
+ /* Decrement reference count on header */
+ fspace->rc--;
+
+ /* Check if we should unpin the header in the cache */
+ if(fspace->rc == 0) {
+ if(H5F_addr_defined(fspace->addr)) {
+ if(H5AC_unpin_entry(f, fspace) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPIN, FAIL, "unable to unpin free space header")
+ } /* end if */
+ else {
+ if(H5FS_cache_hdr_dest(f, fspace) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTCLOSEOBJ, FAIL, "unable to destroy free space header")
+ } /* end else */
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FS_decr() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FS_dirty
+ *
+ * Purpose: Mark free space header as dirty
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Feb 14 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FS_dirty(H5F_t *f, H5FS_t *fspace)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5FS_dirty)
+#ifdef QAK
+HDfprintf(stderr, "%s: Marking free space header as dirty\n", FUNC);
+#endif /* QAK */
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(fspace);
+
+ /* Check if the free space manager is persistant */
+ if(H5F_addr_defined(fspace->addr))
+ /* Mark header as dirty in cache */
+ if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FS_dirty() */
+
+#ifdef H5FS_DEBUG_ASSERT
/*-------------------------------------------------------------------------
* Function: H5FS_assert
@@ -515,16 +742,19 @@ herr_t
H5FS_assert(const H5FS_t *fspace)
{
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_assert)
-#ifdef QAK
-HDfprintf(stderr, "%s: fspace->hdr->tot_sect_count = %Hu\n", "H5FS_assert", fspace->hdr->tot_sect_count);
+#ifndef QAK
+HDfprintf(stderr, "%s: fspace->tot_sect_count = %Hu\n", "H5FS_assert", fspace->tot_sect_count);
#endif /* QAK */
- /* Sanity check sections */
- H5FS_sect_assert(fspace);
+ /* Checks for section info, if it's available */
+ if(fspace->sinfo) {
+ /* Sanity check sections */
+ H5FS_sect_assert(fspace);
- /* General assumptions about the section size counts */
- HDassert(fspace->sinfo->tot_size_count >= fspace->sinfo->serial_size_count);
- HDassert(fspace->sinfo->tot_size_count >= fspace->sinfo->ghost_size_count);
+ /* General assumptions about the section size counts */
+ HDassert(fspace->sinfo->tot_size_count >= fspace->sinfo->serial_size_count);
+ HDassert(fspace->sinfo->tot_size_count >= fspace->sinfo->ghost_size_count);
+ } /* end if */
/* General assumptions about the section counts */
HDassert(fspace->tot_sect_count >= fspace->serial_sect_count);
@@ -536,5 +766,4 @@ HDfprintf(stderr, "%s: fspace->hdr->tot_sect_count = %Hu\n", "H5FS_assert", fspa
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5FS_assert() */
-#endif /* H5FS_DEBUG */
-
+#endif /* H5FS_DEBUG_ASSERT */
diff --git a/src/H5FScache.c b/src/H5FScache.c
index 74a9aab..a7af72b 100644
--- a/src/H5FScache.c
+++ b/src/H5FScache.c
@@ -36,6 +36,7 @@
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
#include "H5FSpkg.h" /* File free space */
+#include "H5MFprivate.h" /* File memory management */
#include "H5Vprivate.h" /* Vectors and arrays */
#include "H5WBprivate.h" /* Wrapped Buffers */
@@ -181,7 +182,7 @@ HDfprintf(stderr, "%s: Load free space header, addr = %a\n", FUNC, addr);
size = H5FS_HEADER_SIZE(f);
/* Get a pointer to a buffer that's large enough for header */
- if(NULL == (hdr = H5WB_actual(wb, size)))
+ if(NULL == (hdr = (uint8_t *)H5WB_actual(wb, size)))
HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, NULL, "can't get actual buffer")
/* Read header from disk */
@@ -191,9 +192,9 @@ HDfprintf(stderr, "%s: Load free space header, addr = %a\n", FUNC, addr);
p = hdr;
/* Magic number */
- if(HDmemcmp(p, H5FS_HDR_MAGIC, (size_t)H5FS_SIZEOF_MAGIC))
+ if(HDmemcmp(p, H5FS_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC))
HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, NULL, "wrong free space header signature")
- p += H5FS_SIZEOF_MAGIC;
+ p += H5_SIZEOF_MAGIC;
/* Version */
if(*p++ != H5FS_HDR_VERSION)
@@ -299,12 +300,68 @@ H5FS_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5F
FUNC_ENTER_NOAPI_NOINIT(H5FS_cache_hdr_flush)
#ifdef QAK
HDfprintf(stderr, "%s: Flushing free space header, addr = %a, destroy = %u\n", FUNC, addr, (unsigned)destroy);
+HDfprintf(stderr, "%s: fspace->sect_addr = %a, fspace->sinfo = %p\n", FUNC, fspace->sect_addr, fspace->sinfo);
+HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n", FUNC, fspace->alloc_sect_size, fspace->sect_size);
#endif /* QAK */
/* check arguments */
HDassert(f);
HDassert(H5F_addr_defined(addr));
HDassert(fspace);
+ HDassert(H5F_addr_defined(fspace->addr));
+
+ /* Check if the header "owns" the section info */
+ if(fspace->sinfo) {
+ /* Sanity check - should not be trying to destroy header if it still
+ * "owns" section info
+ */
+ HDassert(!destroy);
+
+ /* Check if the section info is dirty */
+ if(fspace->sinfo->dirty) {
+ if(fspace->serial_sect_count > 0) {
+ /* Check if we need to allocate space for section info */
+ if(!H5F_addr_defined(fspace->sect_addr)) {
+ /* Sanity check */
+ HDassert(fspace->sect_size > 0);
+
+ /* Allocate space for the section info in file */
+ if(HADDR_UNDEF == (fspace->sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->sect_size)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections")
+ fspace->alloc_sect_size = (size_t)fspace->sect_size;
+
+ /* Mark header dirty */
+ /* (don't use cache API, since we're in a callback) */
+ fspace->cache_info.is_dirty = TRUE;
+ } /* end if */
+
+ /* Write section info to file */
+ if(H5FS_cache_sinfo_flush(f, dxpl_id, FALSE, fspace->sect_addr, fspace->sinfo, NULL) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTFLUSH, FAIL, "unable to save free space section info to disk")
+ } /* end if */
+ else {
+ /* Sanity check that section info doesn't have address */
+ HDassert(!H5F_addr_defined(fspace->sect_addr));
+ } /* end else */
+#ifdef QAK
+HDfprintf(stderr, "%s: Check 2.0\n", FUNC);
+HDfprintf(stderr, "%s: fspace->sect_addr = %a, fspace->sinfo = %p\n", FUNC, fspace->sect_addr, fspace->sinfo);
+HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n", FUNC, fspace->alloc_sect_size, fspace->sect_size);
+#endif /* QAK */
+
+ /* Mark section info clean */
+ fspace->sinfo->dirty = FALSE;
+ } /* end if */
+ } /* end if */
+ else {
+ /* Just sanity checks... */
+ if(fspace->serial_sect_count > 0)
+ /* Sanity check that section info has address */
+ HDassert(H5F_addr_defined(fspace->sect_addr));
+ else
+ /* Sanity check that section info doesn't have address */
+ HDassert(!H5F_addr_defined(fspace->sect_addr));
+ } /* end else */
if(fspace->cache_info.is_dirty) {
uint8_t *hdr; /* Pointer to header buffer */
@@ -320,15 +377,15 @@ HDfprintf(stderr, "%s: Flushing free space header, addr = %a, destroy = %u\n", F
size = H5FS_HEADER_SIZE(f);
/* Get a pointer to a buffer that's large enough for header */
- if(NULL == (hdr = H5WB_actual(wb, size)))
+ if(NULL == (hdr = (uint8_t *)H5WB_actual(wb, size)))
HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "can't get actual buffer")
/* Get temporary pointer to header */
p = hdr;
/* Magic number */
- HDmemcpy(p, H5FS_HDR_MAGIC, (size_t)H5FS_SIZEOF_MAGIC);
- p += H5FS_SIZEOF_MAGIC;
+ HDmemcpy(p, H5FS_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ p += H5_SIZEOF_MAGIC;
/* Version # */
*p++ = H5FS_HDR_VERSION;
@@ -412,9 +469,8 @@ done:
*
*-------------------------------------------------------------------------
*/
-/* ARGSUSED */
herr_t
-H5FS_cache_hdr_dest(H5F_t UNUSED *f, H5FS_t *fspace)
+H5FS_cache_hdr_dest(H5F_t *f, H5FS_t *fspace)
{
unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
@@ -426,6 +482,12 @@ H5FS_cache_hdr_dest(H5F_t UNUSED *f, H5FS_t *fspace)
*/
HDassert(fspace);
+ /* We should not still be holding on to the free space section info */
+ HDassert(!fspace->sinfo);
+
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!fspace->cache_info.free_file_space_on_destroy || H5F_addr_defined(fspace->cache_info.addr));
+
/* Terminate the section classes for this free space list */
for(u = 0; u < fspace->nclasses ; u++) {
/* Call the class termination routine, if there is one */
@@ -434,12 +496,23 @@ H5FS_cache_hdr_dest(H5F_t UNUSED *f, H5FS_t *fspace)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "unable to finalize section class")
} /* end for */
+ /* Check for freeing file space for free space header */
+ if(fspace->cache_info.free_file_space_on_destroy) {
+ /* Sanity check */
+ HDassert(H5F_addr_defined(fspace->addr));
+
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_FSPACE_HDR, H5AC_dxpl_id, fspace->cache_info.addr, (hsize_t)H5FS_HEADER_SIZE(f)) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space header")
+ } /* end if */
+
/* Release the memory for the free space section classes */
if(fspace->sect_cls)
- fspace->sect_cls = H5FL_SEQ_FREE(H5FS_section_class_t, fspace->sect_cls);
+ fspace->sect_cls = (H5FS_section_class_t *)H5FL_SEQ_FREE(H5FS_section_class_t, fspace->sect_cls);
/* Free free space info */
- H5FL_FREE(H5FS_t, fspace);
+ (void)H5FL_FREE(H5FS_t, fspace);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -555,11 +628,6 @@ HDfprintf(stderr, "%s: Load free space sections, addr = %a\n", FUNC, addr);
/* Allocate a new free space section info */
if(NULL == (sinfo = H5FS_sinfo_new(f, fspace)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
-
- /* Link free space manager to section info */
- /* (for deserializing sections) */
- HDassert(fspace->sinfo == NULL);
- fspace->sinfo = sinfo;
/* Sanity check address */
if(H5F_addr_ne(addr, fspace->sect_addr))
@@ -581,9 +649,9 @@ HDfprintf(stderr, "%s: fspace->sect_size = %Hu\n", FUNC, fspace->sect_size);
p = buf;
/* Magic number */
- if(HDmemcmp(p, H5FS_SINFO_MAGIC, (size_t)H5FS_SIZEOF_MAGIC))
+ if(HDmemcmp(p, H5FS_SINFO_MAGIC, (size_t)H5_SIZEOF_MAGIC))
HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, NULL, "wrong free space sections signature")
- p += H5FS_SIZEOF_MAGIC;
+ p += H5_SIZEOF_MAGIC;
/* Version */
if(*p++ != H5FS_SINFO_VERSION)
@@ -606,7 +674,7 @@ HDfprintf(stderr, "%s: fspace->addr = %a, fs_addr = %a\n", FUNC, fspace->addr, f
unsigned sect_cnt_size; /* The size of the section size counts */
/* Compute the size of the section counts */
- sect_cnt_size = MAX(1, (H5V_log2_gen(fspace->serial_sect_count) + 7) / 8);
+ sect_cnt_size = H5V_limit_enc_size((uint64_t)fspace->serial_sect_count);
#ifdef QAK
HDfprintf(stderr, "%s: sect_cnt_size = %u\n", FUNC, sect_cnt_size);
HDfprintf(stderr, "%s: fspace->sect_len_size = %u\n", FUNC, fspace->sect_len_size);
@@ -713,7 +781,7 @@ HDfprintf(stderr, "%s: fspace->sect_cls[%u].serial_size = %Zu\n", FUNC, sect_typ
done:
if(buf)
- H5FL_BLK_FREE(sect_block, buf);
+ (void)H5FL_BLK_FREE(sect_block, buf);
if(!ret_value && sinfo)
(void)H5FS_cache_sinfo_dest(f, sinfo);
@@ -872,7 +940,7 @@ HDfprintf(stderr, "%s: Flushing free space header, addr = %a, destroy = %u\n", F
HDassert(sinfo->fspace);
HDassert(sinfo->fspace->sect_cls);
- if(sinfo->cache_info.is_dirty) {
+ if(sinfo->cache_info.is_dirty || sinfo->dirty) {
H5FS_iter_ud_t udata; /* User data for callbacks */
uint8_t *buf = NULL; /* Temporary raw data buffer */
uint8_t *p; /* Pointer into raw data buffer */
@@ -890,8 +958,8 @@ HDfprintf(stderr, "%s: Flushing free space header, addr = %a, destroy = %u\n", F
p = buf;
/* Magic number */
- HDmemcpy(p, H5FS_SINFO_MAGIC, (size_t)H5FS_SIZEOF_MAGIC);
- p += H5FS_SIZEOF_MAGIC;
+ HDmemcpy(p, H5FS_SINFO_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ p += H5_SIZEOF_MAGIC;
/* Version # */
*p++ = H5FS_SINFO_VERSION;
@@ -905,7 +973,7 @@ HDfprintf(stderr, "%s: sinfo->fspace->addr = %a\n", FUNC, sinfo->fspace->addr);
/* Set up user data for iterator */
udata.sinfo = sinfo;
udata.p = &p;
- udata.sect_cnt_size = MAX(1, (H5V_log2_gen(sinfo->fspace->serial_sect_count) + 7) / 8);
+ udata.sect_cnt_size = H5V_limit_enc_size((uint64_t)sinfo->fspace->serial_sect_count);
#ifdef QAK
HDfprintf(stderr, "%s: udata.sect_cnt_size = %u\n", FUNC, udata.sect_cnt_size);
#endif /* QAK */
@@ -941,9 +1009,10 @@ HDfprintf(stderr, "%s: sinfo->fspace->alloc_sect_size = %Hu\n", FUNC, sinfo->fsp
if(H5F_block_write(f, H5FD_MEM_FSPACE_SINFO, sinfo->fspace->sect_addr, (size_t)sinfo->fspace->sect_size, dxpl_id, buf) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTFLUSH, FAIL, "unable to save free space sections to disk")
- H5FL_BLK_FREE(sect_block, buf);
+ (void)H5FL_BLK_FREE(sect_block, buf);
sinfo->cache_info.is_dirty = FALSE;
+ sinfo->dirty = FALSE;
} /* end if */
if(destroy)
@@ -966,6 +1035,10 @@ done:
* Programmer: Quincey Koziol
* Saturday, March 11, 2006
*
+ * Modifications:
+ * Vailin Choi, July 29th, 2008
+ * Add HDassert() to make sure "free" method exists before calling
+ *
*-------------------------------------------------------------------------
*/
static herr_t
@@ -978,6 +1051,7 @@ H5FS_sinfo_free_sect_cb(void *_sect, void UNUSED *key, void *op_data)
HDassert(sect);
HDassert(sinfo);
+ HDassert(sinfo->fspace->sect_cls[sect->type].free);
/* Call the section's class 'free' method on the section */
(*sinfo->fspace->sect_cls[sect->type].free)(sect);
@@ -1014,7 +1088,7 @@ H5FS_sinfo_free_node_cb(void *item, void UNUSED *key, void *op_data)
H5SL_destroy(fspace_node->sect_list, H5FS_sinfo_free_sect_cb, op_data);
/* Release free space list node */
- H5FL_FREE(H5FS_node_t, fspace_node);
+ (void)H5FL_FREE(H5FS_node_t, fspace_node);
FUNC_LEAVE_NOAPI(0)
} /* H5FS_sinfo_free_node_cb() */
@@ -1033,7 +1107,6 @@ H5FS_sinfo_free_node_cb(void *item, void UNUSED *key, void *op_data)
*
*-------------------------------------------------------------------------
*/
-/* ARGSUSED */
herr_t
H5FS_cache_sinfo_dest(H5F_t *f, H5FS_sinfo_t *sinfo)
{
@@ -1041,6 +1114,9 @@ H5FS_cache_sinfo_dest(H5F_t *f, H5FS_sinfo_t *sinfo)
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5FS_cache_sinfo_dest)
+#ifdef QAK
+HDfprintf(stderr, "%s: Destroying section info, sinfo->fspace->addr = %a\n", FUNC, sinfo->fspace->addr);
+#endif /* QAK */
/*
* Check arguments.
@@ -1049,6 +1125,20 @@ H5FS_cache_sinfo_dest(H5F_t *f, H5FS_sinfo_t *sinfo)
HDassert(sinfo->fspace);
HDassert(sinfo->bins);
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!sinfo->cache_info.free_file_space_on_destroy || H5F_addr_defined(sinfo->cache_info.addr));
+
+ /* Check for freeing file space for free space section info */
+ if(sinfo->cache_info.free_file_space_on_destroy) {
+ /* Sanity check */
+ HDassert(sinfo->fspace->alloc_sect_size > 0);
+
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, H5AC_dxpl_id, sinfo->cache_info.addr, (hsize_t)sinfo->fspace->alloc_sect_size) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space section info")
+ } /* end if */
+
/* Clear out lists of nodes */
for(u = 0; u < sinfo->nbins; u++)
if(sinfo->bins[u].bin_list) {
@@ -1057,22 +1147,24 @@ H5FS_cache_sinfo_dest(H5F_t *f, H5FS_sinfo_t *sinfo)
} /* end if */
/* Release bins for skip lists */
- sinfo->bins = H5FL_SEQ_FREE(H5FS_bin_t, sinfo->bins);
+ sinfo->bins = (H5FS_bin_t *)H5FL_SEQ_FREE(H5FS_bin_t, sinfo->bins);
/* Release skip list for merging sections */
if(sinfo->merge_list)
if(H5SL_close(sinfo->merge_list) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTCLOSEOBJ, FAIL, "can't destroy section merging skip list")
- /* Unpin the free space header in the cache */
+ /* Decrement the reference count on free space header */
/* (make certain this is last action with section info, to allow for header
* disappearing immediately)
*/
- if(H5AC_unpin_entry(f, sinfo->fspace) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPIN, FAIL, "unable to unpin free space header")
+ sinfo->fspace->sinfo = NULL;
+ if(H5FS_decr(f, sinfo->fspace) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTDEC, FAIL, "unable to decrement ref. count on free space header")
+ sinfo->fspace = NULL;
/* Release free space section info */
- H5FL_FREE(H5FS_sinfo_t, sinfo);
+ (void)H5FL_FREE(H5FS_sinfo_t, sinfo);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1141,7 +1233,7 @@ H5FS_cache_sinfo_size(const H5F_t UNUSED *f, const H5FS_sinfo_t *sinfo, size_t *
HDassert(size_ptr);
/* Set size value */
- H5_ASSIGN_OVERFLOW(/* To: */ *size_ptr, /* From: */ sinfo->fspace->sect_size, /* From: */ hsize_t, /* To: */ size_t);
+ H5_ASSIGN_OVERFLOW(/* To: */ *size_ptr, /* From: */ sinfo->fspace->alloc_sect_size, /* From: */ hsize_t, /* To: */ size_t);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* H5FS_cache_sinfo_size() */
diff --git a/src/H5FSdbg.c b/src/H5FSdbg.c
index 0ac7b3b..cf165ca 100644
--- a/src/H5FSdbg.c
+++ b/src/H5FSdbg.c
@@ -30,6 +30,7 @@
#define H5FS_PACKAGE /*suppress error about including H5FSpkg */
#define H5HF_DEBUGGING /* Need access to fractal heap debugging routines */
+#define H5MF_DEBUGGING /* Need access to file space debugging routines */
/***********/
/* Headers */
@@ -38,6 +39,7 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5FSpkg.h" /* File free space */
#include "H5HFprivate.h" /* Fractal heaps */
+#include "H5MFprivate.h" /* File memory management */
/****************/
/* Local Macros */
@@ -85,6 +87,10 @@
* koziol@ncsa.uiuc.edu
* May 9 2006
*
+ * Modifications:
+ * Vailin Choi, July 29th, 2008
+ * Add H5FS_CLIENT_FILE_ID for File Memory Management
+ *
*-------------------------------------------------------------------------
*/
herr_t
@@ -113,7 +119,7 @@ H5FS_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int
/*
* Load the free space header.
*/
- if(NULL == (fspace = H5AC_protect(f, dxpl_id, H5AC_FSPACE_HDR, addr, &fs_prot, NULL, H5AC_READ)))
+ if(NULL == (fspace = (H5FS_t *)H5AC_protect(f, dxpl_id, H5AC_FSPACE_HDR, addr, &fs_prot, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, FAIL, "unable to load free space header")
/* Print opening message */
@@ -124,7 +130,8 @@ H5FS_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int
*/
HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
"Free space client:",
- (fspace->client == H5FS_CLIENT_FHEAP_ID ? "Fractal heap" : "Unknown"));
+ (fspace->client == H5FS_CLIENT_FHEAP_ID ? "Fractal heap" :
+ (fspace->client == H5FS_CLIENT_FILE_ID ? "File Memory Management" : "Unknown")));
HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
"Total free space tracked:",
fspace->tot_space);
@@ -252,14 +259,17 @@ H5FS_sects_debug(H5F_t *f, hid_t dxpl_id, haddr_t UNUSED addr, FILE *stream, int
/*
* Load the free space header.
*/
- if(NULL == (fspace = H5AC_protect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, &fs_prot, NULL, H5AC_READ)))
+ if(NULL == (fspace = (H5FS_t *)H5AC_protect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, &fs_prot, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, FAIL, "unable to load free space header")
/* Retrieve the client id */
client = fspace->client;
/* Release the free space header */
- if(H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, fspace, H5AC__NO_FLAGS_SET) < 0)
+ /* (set the "deleted" flag for the unprotect, so the cache entry is removed
+ * and reloaded later, with the correct client information -QAK)
+ */
+ if(H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, fspace, H5AC__DELETED_FLAG) < 0)
HDONE_ERROR(H5E_FSPACE, H5E_PROTECT, FAIL, "unable to release free space header")
fspace = NULL;
@@ -275,6 +285,13 @@ H5FS_sects_debug(H5F_t *f, hid_t dxpl_id, haddr_t UNUSED addr, FILE *stream, int
HGOTO_ERROR(H5E_FSPACE, H5E_SYSTEM, FAIL, "unable to dump fractal heap free space sections")
break;
+ case H5FS_CLIENT_FILE_ID:
+#ifdef NOT_YET
+ if(H5MF_sects_debug(f, dxpl_id, client_addr, stream, indent + 3, MAX(0, fwidth - 3)) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_SYSTEM, FAIL, "unable to dump file free space sections")
+#endif /* NOT_YET */
+ break;
+
default:
HDfprintf(stream, "Unknown client!\n");
break;
diff --git a/src/H5FSpkg.h b/src/H5FSpkg.h
index 9119902..1786b44 100644
--- a/src/H5FSpkg.h
+++ b/src/H5FSpkg.h
@@ -28,9 +28,15 @@
#ifndef _H5FSpkg_H
#define _H5FSpkg_H
-/* Uncomment this macro to enable extra sanity checking */
+/* Uncomment this macro to enable debugging output for free space manager */
/* #define H5FS_DEBUG */
+/* Uncomment this macro to enable debugging output for free space sections */
+/* #define H5FS_SINFO_DEBUG */
+
+/* Uncomment this macro to enable extra sanity checking */
+/* #define H5FS_DEBUG_ASSERT */
+
/* Get package's private header */
#include "H5FSprivate.h" /* File free space */
@@ -42,19 +48,12 @@
/* Package Private Macros */
/**************************/
-/* Size of signature information (on disk) */
-#define H5FS_SIZEOF_MAGIC 4
-
-/* Free space signatures */
-#define H5FS_HDR_MAGIC "FSHD" /* Header */
-#define H5FS_SINFO_MAGIC "FSSE" /* Serialized sections */
-
/* Size of checksum information (on disk) */
#define H5FS_SIZEOF_CHKSUM 4
/* "Standard" size of prefix information for free space metadata */
#define H5FS_METADATA_PREFIX_SIZE ( \
- H5FS_SIZEOF_MAGIC /* Signature */ \
+ H5_SIZEOF_MAGIC /* Signature */ \
+ 1 /* Version */ \
+ H5FS_SIZEOF_CHKSUM /* Metadata checksum */ \
)
@@ -117,7 +116,7 @@ typedef struct H5FS_node_t {
H5SL_t *sect_list; /* Skip list to hold pointers to actual free list section node */
} H5FS_node_t;
-/* Information about sections managed */
+/* Free space section info */
typedef struct H5FS_sinfo_t {
/* Information for H5AC cache functions, _must_ be first field in structure */
H5AC_info_t cache_info;
@@ -126,6 +125,7 @@ typedef struct H5FS_sinfo_t {
H5FS_bin_t *bins; /* Array of lists of lists of free sections */
/* Computed/cached values */
+ hbool_t dirty; /* Whether this info in memory is out of sync w/info in file */
unsigned nbins; /* Number of bins */
size_t serial_size; /* Total size of all serializable sections */
size_t tot_size_count; /* Total number of differently sized sections */
@@ -140,7 +140,7 @@ typedef struct H5FS_sinfo_t {
H5SL_t *merge_list; /* Skip list to hold sections for detecting merges */
} H5FS_sinfo_t;
-/* Main free space info */
+/* Free space header info */
struct H5FS_t {
/* Information for H5AC cache functions, _must_ be first field in structure */
H5AC_info_t cache_info;
@@ -166,8 +166,17 @@ struct H5FS_t {
hsize_t alloc_sect_size; /* Allocated size of the section info in the file */
/* Computed/cached values */
+ unsigned rc; /* Count of outstanding references to struct */
haddr_t addr; /* Address of free space header on disk */
H5FS_sinfo_t *sinfo; /* Section information */
+ unsigned sinfo_lock_count; /* # of times the section info has been locked */
+ hbool_t sinfo_protected; /* Whether the section info was protected when locked */
+ hbool_t sinfo_modified; /* Whether the section info has been modified while locked */
+ H5AC_protect_t sinfo_accmode; /* Access mode for protecting the section info */
+ size_t max_cls_serial_size; /* Max. additional size of serialized form of section */
+ hsize_t threshold; /* Threshold for alignment */
+ hsize_t alignment; /* Alignment */
+
/* Memory data structures (not stored directly) */
H5FS_section_class_t *sect_cls; /* Array of section classes for this free list */
@@ -204,16 +213,13 @@ H5FL_EXTERN(H5FS_t);
/* Free space manager header routines */
H5_DLL H5FS_t *H5FS_new(size_t nclasses, const H5FS_section_class_t *classes[],
void *cls_init_udata);
+H5_DLL herr_t H5FS_incr(H5F_t *f, H5FS_t *fspace);
+H5_DLL herr_t H5FS_decr(H5F_t *f, H5FS_t *fspace);
+H5_DLL herr_t H5FS_dirty(H5F_t *f, H5FS_t *fspace);
/* Free space section routines */
H5_DLL H5FS_sinfo_t *H5FS_sinfo_new(H5F_t *f, H5FS_t *fspace);
-/* Debugging routines for dumping file structures */
-H5_DLL herr_t H5FS_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr,
- FILE *stream, int indent, int fwidth);
-H5_DLL herr_t H5FS_sects_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr,
- FILE *stream, int indent, int fwidth, haddr_t fs_addr, haddr_t client_addr);
-
/* Metadata cache callbacks */
H5_DLL herr_t H5FS_cache_hdr_dest(H5F_t *f, H5FS_t *hdr);
H5_DLL herr_t H5FS_cache_sinfo_dest(H5F_t *f, H5FS_sinfo_t *sinfo);
@@ -224,5 +230,11 @@ H5_DLL herr_t H5FS_assert(const H5FS_t *fspace);
H5_DLL herr_t H5FS_sect_assert(const H5FS_t *fspace);
#endif /* H5FS_DEBUG */
+/* Testing routines */
+#ifdef H5FS_TESTING
+H5_DLL herr_t H5FS_get_cparam_test(const H5FS_t *fh, H5FS_create_t *cparam);
+H5_DLL int H5FS_cmp_cparam_test(const H5FS_create_t *cparam1, const H5FS_create_t *cparam2);
+#endif /* H5FS_TESTING */
+
#endif /* _H5FSpkg_H */
diff --git a/src/H5FSprivate.h b/src/H5FSprivate.h
index bf24b8a..6f73b93 100644
--- a/src/H5FSprivate.h
+++ b/src/H5FSprivate.h
@@ -43,10 +43,14 @@
* serialized to the file.
*/
#define H5FS_CLS_SEPAR_OBJ 0x02 /* Objects in this class shouldn't
- * participate in merge operations
+ * participate in merge operations.
*/
#define H5FS_CLS_MERGE_SYM 0x04 /* Objects in this class only merge
- * with other objects in this class
+ * with other objects in this class.
+ */
+#define H5FS_CLS_ADJUST_OK 0x08 /* Objects in this class can be merged
+ * without requiring a can_adjust/adjust
+ * callback pair.
*/
/* Flags for H5FS_add() */
@@ -103,6 +107,7 @@ typedef struct H5FS_section_class_t {
herr_t (*shrink)(H5FS_section_info_t **, void *); /* Routine to shrink container */
herr_t (*free)(H5FS_section_info_t *); /* Routine to free node */
herr_t (*valid)(const struct H5FS_section_class_t *, const H5FS_section_info_t *); /* Routine to check if a section is valid */
+ H5FS_section_info_t *(*split)(H5FS_section_info_t *, hsize_t); /* Routine to create the split section */
herr_t (*debug)(const H5FS_section_info_t *, FILE *, int , int ); /* Routine to dump debugging information about a section */
} H5FS_section_class_t;
@@ -123,6 +128,7 @@ struct H5FS_section_info_t {
/* Free space client IDs for identifying user of free space */
typedef enum H5FS_client_t {
H5FS_CLIENT_FHEAP_ID = 0, /* Free space is used by fractal heap */
+ H5FS_CLIENT_FILE_ID, /* Free space is used by file */
H5FS_NUM_CLIENT_ID /* Number of free space client IDs (must be last) */
} H5FS_client_t;
@@ -135,6 +141,15 @@ typedef struct H5FS_create_t {
hsize_t max_sect_size; /* Maximum size of section to track */
} H5FS_create_t;
+/* Free space statistics info */
+typedef struct H5FS_stat_t {
+ hsize_t tot_space; /* Total amount of space tracked */
+ hsize_t tot_sect_count; /* Total # of sections tracked */
+ hsize_t serial_sect_count; /* # of serializable sections tracked */
+ hsize_t ghost_sect_count; /* # of un-serializable sections tracked */
+} H5FS_stat_t;
+
+
/* Typedef for iteration operations */
typedef herr_t (*H5FS_operator_t)(const H5FS_section_info_t *sect,
void *operator_data/*in,out*/);
@@ -155,9 +170,9 @@ H5FL_SEQ_EXTERN(H5FS_section_class_t);
/* Free space manager routines */
H5_DLL H5FS_t *H5FS_create(H5F_t *f, hid_t dxpl_id, haddr_t *fs_addr,
const H5FS_create_t *fs_create, size_t nclasses,
- const H5FS_section_class_t *classes[], void *cls_init_udata);
+ const H5FS_section_class_t *classes[], void *cls_init_udata, hsize_t alignment, hsize_t threshold);
H5_DLL H5FS_t *H5FS_open(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr,
- size_t nclasses, const H5FS_section_class_t *classes[], void *cls_init_udata);
+ size_t nclasses, const H5FS_section_class_t *classes[], void *cls_init_udata, hsize_t alignment, hsize_t threshold);
H5_DLL herr_t H5FS_size(const H5F_t *f, const H5FS_t *fspace, hsize_t *meta_size);
H5_DLL herr_t H5FS_delete(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr);
H5_DLL herr_t H5FS_close(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace);
@@ -165,16 +180,27 @@ H5_DLL herr_t H5FS_close(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace);
/* Free space section routines */
H5_DLL herr_t H5FS_sect_add(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
H5FS_section_info_t *node, unsigned flags, void *op_data);
+H5_DLL herr_t H5FS_sect_try_extend(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
+ haddr_t addr, hsize_t size, hsize_t extra_requested);
H5_DLL herr_t H5FS_sect_remove(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
H5FS_section_info_t *node);
H5_DLL htri_t H5FS_sect_find(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
hsize_t request, H5FS_section_info_t **node);
H5_DLL herr_t H5FS_sect_iterate(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_operator_t op, void *op_data);
-H5_DLL herr_t H5FS_get_sect_count(const H5FS_t *fspace, hsize_t *nsects);
+H5_DLL herr_t H5FS_sect_stats(const H5FS_t *fspace, hsize_t *tot_space,
+ hsize_t *nsects);
H5_DLL herr_t H5FS_sect_change_class(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
H5FS_section_info_t *sect, unsigned new_class);
+/* Statistics routine */
+H5_DLL herr_t H5FS_stat_info(const H5FS_t *fh, H5FS_stat_t *stats);
+
+
/* Debugging routines for dumping file structures */
+H5_DLL herr_t H5FS_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr,
+ FILE *stream, int indent, int fwidth);
+H5_DLL herr_t H5FS_sects_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr,
+ FILE *stream, int indent, int fwidth, haddr_t fs_addr, haddr_t client_addr);
H5_DLL herr_t H5FS_sect_debug(const H5FS_t *fspace, const H5FS_section_info_t *sect,
FILE *stream, int indent, int fwidth);
diff --git a/src/H5FSsection.c b/src/H5FSsection.c
index 505223a..42c0f86 100644
--- a/src/H5FSsection.c
+++ b/src/H5FSsection.c
@@ -40,6 +40,8 @@
/* Local Macros */
/****************/
+/* #define QAK */
+
/* Default starting size of section buffer */
#define H5FS_SINFO_SIZE_DEFAULT 64
@@ -67,27 +69,26 @@ typedef struct {
/********************/
/* Local Prototypes */
/********************/
-static herr_t H5FS_sect_increase(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
- const H5FS_section_class_t *cls, unsigned flags);
-static herr_t H5FS_sect_decrease(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
- const H5FS_section_class_t *cls);
+static herr_t H5FS_sect_increase(H5FS_t *fspace, const H5FS_section_class_t *cls,
+ unsigned flags);
+static herr_t H5FS_sect_decrease(H5FS_t *fspace, const H5FS_section_class_t *cls);
static herr_t H5FS_size_node_decr(H5FS_sinfo_t *sinfo, unsigned bin, H5FS_node_t *fspace_node,
const H5FS_section_class_t *cls);
static herr_t H5FS_sect_unlink_size(H5FS_sinfo_t *sinfo, const H5FS_section_class_t *cls,
H5FS_section_info_t *sect);
-static herr_t H5FS_sect_unlink_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
+static herr_t H5FS_sect_unlink_rest(H5FS_t *fspace,
const H5FS_section_class_t *cls, H5FS_section_info_t *sect);
+static herr_t H5FS_sect_remove_real(H5FS_t *fspace, H5FS_section_info_t *sect);
static herr_t H5FS_sect_link_size(H5FS_sinfo_t *sinfo, const H5FS_section_class_t *cls,
H5FS_section_info_t *sect);
-static herr_t H5FS_sect_link_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
- const H5FS_section_class_t *cls, H5FS_section_info_t *sect, unsigned flags);
-static herr_t H5FS_sect_link(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
+static herr_t H5FS_sect_link_rest(H5FS_t *fspace, const H5FS_section_class_t *cls,
H5FS_section_info_t *sect, unsigned flags);
-static herr_t H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
- H5FS_section_info_t **sect, void *op_data);
+static herr_t H5FS_sect_link(H5FS_t *fspace, H5FS_section_info_t *sect,
+ unsigned flags);
+static herr_t H5FS_sect_merge(H5FS_t *fspace, H5FS_section_info_t **sect,
+ void *op_data);
static htri_t H5FS_sect_find_node(H5FS_t *fspace, hsize_t request, H5FS_section_info_t **node);
-static herr_t H5FS_sect_serialize_size(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace);
-
+static herr_t H5FS_sect_serialize_size(H5FS_t *fspace);
/*********************/
/* Package Variables */
@@ -138,6 +139,9 @@ H5FS_sinfo_new(H5F_t *f, H5FS_t *fspace)
/* Check arguments. */
HDassert(f);
HDassert(fspace);
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: fspace->addr = %a\n", FUNC, fspace->addr);
+#endif /* H5FS_SINFO_DEBUG */
/* Allocate the free space header */
if(NULL == (sinfo = H5FL_CALLOC(H5FS_sinfo_t)))
@@ -147,105 +151,371 @@ H5FS_sinfo_new(H5F_t *f, H5FS_t *fspace)
sinfo->nbins = H5V_log2_gen(fspace->max_sect_size);
sinfo->sect_prefix_size = H5FS_SINFO_PREFIX_SIZE(f);
sinfo->sect_off_size = (fspace->max_sect_addr + 7) / 8;
- sinfo->sect_len_size = (H5V_log2_gen(fspace->max_sect_size) + 7) / 8;
- sinfo->fspace = fspace;
-#ifdef QAK
+ sinfo->sect_len_size = H5V_limit_enc_size((uint64_t)fspace->max_sect_size);
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: fspace->max_sect_size = %Hu\n", FUNC, fspace->max_sect_size);
+HDfprintf(stderr, "%s: fspace->max_sect_addr = %u\n", FUNC, fspace->max_sect_addr);
HDfprintf(stderr, "%s: sinfo->nbins = %u\n", FUNC, sinfo->nbins);
HDfprintf(stderr, "%s: sinfo->sect_off_size = %u, sinfo->sect_len_size = %u\n", FUNC, sinfo->sect_off_size, sinfo->sect_len_size);
-#endif /* QAK */
+#endif /* H5FS_SINFO_DEBUG */
/* Allocate space for the section size bins */
if(NULL == (sinfo->bins = H5FL_SEQ_CALLOC(H5FS_bin_t, (size_t)sinfo->nbins)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for free space section bin array")
+ /* Increment the reference count on the free space manager header */
+ if(H5FS_incr(f, fspace) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTINC, NULL, "unable to increment ref. count on free space header")
+ sinfo->fspace = fspace;
+
+ /* Link free space manager to section info */
+ /* (for deserializing sections) */
+ HDassert(fspace->sinfo == NULL);
+ fspace->sinfo = sinfo;
+
/* Set return value */
ret_value = sinfo;
done:
+ if(ret_value == NULL && sinfo) {
+ /* Release bins for skip lists */
+ if(sinfo->bins)
+ sinfo->bins = H5FL_SEQ_FREE(H5FS_bin_t, sinfo->bins);
+ /* Release free space section info */
+ H5FL_FREE(H5FS_sinfo_t, sinfo);
+ } /* end if */
+
FUNC_LEAVE_NOAPI(ret_value)
} /* H5FS_sinfo_new() */
/*-------------------------------------------------------------------------
- * Function: H5FS_sinfo_pin
+ * Function: H5FS_sinfo_lock
*
- * Purpose: Pin the section info for the free space manager in memory
- * Either loads section info from disk, or creates new section info
+ * Purpose: Make certain the section info for the free space manager is
+ * in memory.
*
- * Return: Success: non-NULL, pointer to section info struct
- * Failure: NULL
+ * Either uses existing section info owned by the free space
+ * header, loads section info from disk, or creates new section
+ * info
+ *
+ * Return: Success: non-negative
+ * Failure: negative
*
* Programmer: Quincey Koziol
- * Monday, July 31, 2006
+ * Thursday, February 7, 2008
*
*-------------------------------------------------------------------------
*/
-static H5FS_sinfo_t *
-H5FS_sinfo_pin(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace)
+static herr_t
+H5FS_sinfo_lock(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5AC_protect_t accmode)
{
- H5FS_sinfo_t *sinfo; /* Section information struct created */
- H5FS_sinfo_t *ret_value; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5FS_sinfo_pin)
+ FUNC_ENTER_NOAPI_NOINIT(H5FS_sinfo_lock)
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: Called, fspace->addr = %a, fspace->sinfo = %p, fspace->sect_addr = %a\n", FUNC, fspace->addr, fspace->sinfo, fspace->sect_addr);
+HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n", FUNC, fspace->alloc_sect_size, fspace->sect_size);
+#endif /* H5FS_SINFO_DEBUG */
/* Check arguments. */
HDassert(f);
HDassert(fspace);
- /* Create new section info, if it doesn't exist yet */
- if(!H5F_addr_defined(fspace->sect_addr)) {
- /* Sanity check */
- HDassert(fspace->tot_sect_count == 0);
- HDassert(fspace->serial_sect_count == 0);
- HDassert(fspace->ghost_sect_count == 0);
+ /* If the free space header doesn't already "own" the section info, load
+ * section info or create it
+ */
+ if(fspace->sinfo) {
+ /* Check if the section info was protected & we want a different access mode */
+ if(fspace->sinfo_protected && accmode != fspace->sinfo_accmode) {
+ /* Check if we need to switch from read-only access to read-write */
+ if(H5AC_WRITE == accmode) {
+ /* Unprotect the read-only section info */
+ if(H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, fspace->sinfo, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPROTECT, FAIL, "unable to release free space section info")
+
+ /* Re-protect the section info with read-write access */
+ if(NULL == (fspace->sinfo = H5AC_protect(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, NULL, fspace, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTPROTECT, FAIL, "unable to load free space sections")
+
+ /* Switch the access mode we have */
+ fspace->sinfo_accmode = H5AC_WRITE;
+ } /* end if */
+ } /* end if */
+ } /* end if */
+ else {
+ /* If the section address is defined, load it from the file */
+ if(H5F_addr_defined(fspace->sect_addr)) {
+ /* Sanity check */
+ HDassert(fspace->sinfo_protected == FALSE);
+ HDassert(H5F_addr_defined(fspace->addr));
+
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: Reading in existing sections, fspace->sect_addr = %a\n", FUNC, fspace->sect_addr);
+#endif /* H5FS_SINFO_DEBUG */
+ /* Protect the free space sections */
+ if(NULL == (fspace->sinfo = H5AC_protect(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, NULL, fspace, accmode)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTPROTECT, FAIL, "unable to load free space sections")
+
+ /* Remember that we protected the section info & the access mode */
+ fspace->sinfo_protected = TRUE;
+ fspace->sinfo_accmode = accmode;
+ } /* end if */
+ else {
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: Creating new section info\n", FUNC);
+#endif /* H5FS_SINFO_DEBUG */
+ /* Sanity check */
+ HDassert(fspace->tot_sect_count == 0);
+ HDassert(fspace->serial_sect_count == 0);
+ HDassert(fspace->ghost_sect_count == 0);
+
+ /* Allocate and initialize free space section info */
+ if(NULL == (fspace->sinfo = H5FS_sinfo_new(f, fspace)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTCREATE, FAIL, "can't create section info")
+
+ /* Set initial size of section info to 0 */
+ fspace->sect_size = fspace->alloc_sect_size = 0;
+ } /* end if */
+ } /* end if */
+ HDassert(fspace->rc == 2);
+
+ /* Increment the section info lock count */
+ fspace->sinfo_lock_count++;
+
+done:
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: Leaving, fspace->addr = %a, fspace->sinfo = %p, fspace->sect_addr = %a\n", FUNC, fspace->addr, fspace->sinfo, fspace->sect_addr);
+HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n", FUNC, fspace->alloc_sect_size, fspace->sect_size);
+#endif /* H5FS_SINFO_DEBUG */
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5FS_sinfo_lock() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FS_sinfo_unlock
+ *
+ * Purpose: Release the section info, either giving ownership back to
+ * the cache or letting the free space header keep it.
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, February 7, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FS_sinfo_unlock(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, hbool_t modified)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
- /* Allocate and initialize free space section info */
- if(NULL == (sinfo = H5FS_sinfo_new(f, fspace)))
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTCREATE, NULL, "can't create section info")
+ FUNC_ENTER_NOAPI_NOINIT(H5FS_sinfo_unlock)
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: Called, modified = %t, fspace->addr = %a, fspace->sect_addr = %a\n", FUNC, modified, fspace->addr, fspace->sect_addr);
+HDfprintf(stderr, "%s: fspace->sinfo_lock_count = %u, fspace->sinfo_modified = %t, fspace->sinfo_protected = %t\n", FUNC, fspace->sinfo_lock_count, fspace->sinfo_modified, fspace->sinfo_protected);
+HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu, fspace->sect_size = %Hu\n", FUNC, fspace->alloc_sect_size, fspace->sect_size);
+#endif /* H5FS_SINFO_DEBUG */
- /* Allocate space for the section info */
- fspace->sect_size = H5FS_SINFO_SIZE_DEFAULT;
- fspace->alloc_sect_size = (size_t)fspace->sect_size;
- if(HADDR_UNDEF == (fspace->sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, fspace->alloc_sect_size)))
- HGOTO_ERROR(H5E_STORAGE, H5E_NOSPACE, NULL, "file allocation failed for free space sections")
+ /* Check arguments. */
+ HDassert(f);
+ HDassert(fspace);
+ HDassert(fspace->rc == 2);
+ HDassert(fspace->sinfo);
- /* Cache the new free space section info (pinned) */
- if(H5AC_set(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, sinfo, H5AC__PIN_ENTRY_FLAG) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, NULL, "can't add free space sections to cache")
+ /* Check if we modified any section */
+ if(modified) {
+ /* Check if the section info was protected with a different access mode */
+ if(fspace->sinfo_protected && fspace->sinfo_accmode != H5AC_WRITE)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTDIRTY, FAIL, "attempt to modify read-only section info")
- /* Mark free space header as dirty */
- if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, NULL, "unable to mark free space header as dirty")
+ /* If we modified the section info, mark it dirty */
+ fspace->sinfo->dirty = TRUE;
+
+ /* Remember that the section info was modified while locked */
+ fspace->sinfo_modified = TRUE;
+
+ /* Assume that the modification will affect the statistics in the header
+ * and mark that dirty also
+ */
+ if(H5FS_dirty(f, fspace) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty")
} /* end if */
- else {
+
+ /* Decrement the lock count on the section info */
+ fspace->sinfo_lock_count--;
+
+ /* Check if section info lock count dropped to zero */
+ if(fspace->sinfo_lock_count == 0) {
+ hbool_t release_sinfo_space = FALSE; /* Flag to indicate section info space in file should be released */
+
+ /* Check if we actually protected the section info */
+ if(fspace->sinfo_protected) {
+ unsigned cache_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting heap */
+
+ /* Sanity check */
+ HDassert(H5F_addr_defined(fspace->addr));
+
+ /* Check if we've made new changes to the section info while locked */
+ if(fspace->sinfo_modified) {
+ /* Note that we've modified the section info */
+ cache_flags |= H5AC__DIRTIED_FLAG;
+
+ /* Check if the section info size in the file has changed */
+ if(fspace->sect_size != fspace->alloc_sect_size)
+ cache_flags |= H5AC__SIZE_CHANGED_FLAG | H5AC__DELETED_FLAG | H5AC__TAKE_OWNERSHIP_FLAG;
+ } /* end if */
+
+ /* Sanity check */
+ HDassert(H5F_addr_defined(fspace->sect_addr));
+
+ /* Unprotect section info in cache */
+ /* (Possibly dirty) */
+ /* (Possibly taking ownership from the cache) */
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: Unprotecting section info, cache_flags = %u\n", FUNC, cache_flags);
+#endif /* H5FS_SINFO_DEBUG */
+ if(H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, fspace->sinfo, cache_flags) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPROTECT, FAIL, "unable to release free space section info")
+
+ /* Reset the protected flag on the section info */
+ fspace->sinfo_protected = FALSE;
+
+ /* Check if header is taking ownership of section info */
+ if((cache_flags & H5AC__TAKE_OWNERSHIP_FLAG)) {
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: Taking ownership of section info\n", FUNC);
+#endif /* H5FS_SINFO_DEBUG */
+ /* Set flag to release section info space in file */
+ release_sinfo_space = TRUE;
+ } /* end if */
+ else {
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: Relinquishing section info ownership\n", FUNC);
+#endif /* H5FS_SINFO_DEBUG */
+ /* Free space header relinquished ownership of section info */
+ fspace->sinfo = NULL;
+ } /* end else */
+ } /* end if */
+ else {
+ /* Check if the section info was modified */
+ if(fspace->sinfo_modified) {
+ /* Check if we need to release section info in the file */
+ if(H5F_addr_defined(fspace->sect_addr))
+ /* Set flag to release section info space in file */
+ release_sinfo_space = TRUE;
+ else
+ HDassert(fspace->alloc_sect_size == 0);
+ } /* end if */
+ else {
+ /* Sanity checks... */
+ if(H5F_addr_defined(fspace->sect_addr))
+ HDassert(fspace->alloc_sect_size == fspace->sect_size);
+ else
+ HDassert(fspace->alloc_sect_size == 0);
+ } /* end else */
+ } /* end else */
+
+ /* Reset the "section info modified" flag */
+ fspace->sinfo_modified = FALSE;
+
+ /* Check if header needs to release section info in the file */
+ if(release_sinfo_space) {
+ haddr_t old_sect_addr = fspace->sect_addr; /* Previous location of section info in file */
+ hsize_t old_alloc_sect_size = fspace->alloc_sect_size; /* Previous size of section info in file */
+
+ /* Sanity check */
+ HDassert(H5F_addr_defined(fspace->addr));
+
+ /* Reset section info in header */
+ fspace->sect_addr = HADDR_UNDEF;
+ fspace->alloc_sect_size = 0;
+
+ /* If we haven't already marked the header dirty, do so now */
+ if(!modified)
+ if(H5FS_dirty(f, fspace) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty")
+
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: Freeing section info on disk, old_sect_addr = %a, old_alloc_sect_size = %Hu\n", FUNC, old_sect_addr, old_alloc_sect_size);
+#endif /* H5FS_SINFO_DEBUG */
+ /* Release space for section info in file */
+ if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, old_sect_addr, old_alloc_sect_size) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space sections")
+ } /* end if */
+ } /* end if */
+
+done:
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: Leaving, ret_value = %d\n", FUNC, ret_value);
+#endif /* H5FS_SINFO_DEBUG */
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5FS_sinfo_unlock() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FS_sect_serialize_size
+ *
+ * Purpose: Determine serialized size of all sections in free space manager
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Monday, May 8, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FS_sect_serialize_size(H5FS_t *fspace)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_sect_serialize_size)
+
+ /* Check arguments. */
+ HDassert(fspace);
#ifdef QAK
-HDfprintf(stderr, "%s: Reading in existing sections, fspace->sect_addr = %a\n", FUNC, fspace->sect_addr);
+HDfprintf(stderr, "%s: Check 1.0 - fspace->sect_size = %Hu\n", "H5FS_sect_serialize_size", fspace->sect_size);
+HDfprintf(stderr, "%s: fspace->serial_sect_count = %Zu\n", "H5FS_sect_serialize_size", fspace->serial_sect_count);
+HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu\n", "H5FS_sect_serialize_size", fspace->alloc_sect_size);
+HDfprintf(stderr, "%s: fspace->sinfo->serial_size_count = %Zu\n", "H5FS_sect_serialize_size", fspace->sinfo->serial_size_count);
#endif /* QAK */
- /* Protect the free space sections */
- if(NULL == (sinfo = H5AC_protect(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, NULL, fspace, H5AC_WRITE)))
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTPROTECT, NULL, "unable to load free space sections")
- /* Pin them in the cache */
- if(H5AC_pin_protected_entry(f, sinfo) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTPIN, NULL, "unable to pin free space sections")
+ /* Compute the size of the buffer required to serialize all the sections */
+ if(fspace->serial_sect_count > 0) {
+ size_t sect_buf_size; /* Section buffer size */
- /* Unlock free space sections, now pinned */
- if(H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_SINFO, fspace->sect_addr, sinfo, H5AC__NO_FLAGS_SET) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPROTECT, NULL, "unable to release free space sections")
- } /* end else */
+ /* Serialized sections prefix */
+ sect_buf_size = fspace->sinfo->sect_prefix_size;
+
+ /* Count for each differently sized serializable section */
#ifdef QAK
-HDfprintf(stderr, "%s: sinfo->serial_size_count = %Zu\n", FUNC, sinfo->serial_size_count);
+HDfprintf(stderr, "%s: fspace->sinfo->serial_size_count = %Zu\n", "H5FS_sect_serialize_size", fspace->sinfo->serial_size_count);
+HDfprintf(stderr, "%s: fspace->serial_sect_count = %Hu\n", "H5FS_sect_serialize_size", fspace->serial_sect_count);
#endif /* QAK */
+ sect_buf_size += fspace->sinfo->serial_size_count * H5V_limit_enc_size((uint64_t)fspace->serial_sect_count);
- /* Update pointer to free space header for section info */
- sinfo->fspace = fspace;
+ /* Size for each differently sized serializable section */
+ sect_buf_size += fspace->sinfo->serial_size_count * fspace->sinfo->sect_len_size;
- /* Set return value */
- ret_value = sinfo;
+ /* Offsets of each section in address space */
+ sect_buf_size += fspace->serial_sect_count * fspace->sinfo->sect_off_size;
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5FS_sinfo_pin() */
+ /* Class of each section */
+ sect_buf_size += fspace->serial_sect_count * 1 /* byte */;
+
+ /* Extra space required to serialize each section */
+ sect_buf_size += fspace->sinfo->serial_size;
+
+ /* Update section size in header */
+ fspace->sect_size = sect_buf_size;
+ } /* end if */
+ else
+ /* Reset section size in header */
+ fspace->sect_size = fspace->sinfo->sect_prefix_size;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5FS_sect_serialize_size() */
/*-------------------------------------------------------------------------
@@ -255,7 +525,6 @@ done:
* on disk
*
* Return: Success: non-negative
- *
* Failure: negative
*
* Programmer: Quincey Koziol
@@ -264,8 +533,8 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_sect_increase(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
- const H5FS_section_class_t *cls, unsigned flags)
+H5FS_sect_increase(H5FS_t *fspace, const H5FS_section_class_t *cls,
+ unsigned flags)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -301,15 +570,11 @@ HDfprintf(stderr, "%s: cls->serial_size = %Zu\n", FUNC, cls->serial_size);
/* Update the free space sections' serialized size */
/* (if we're not deserializing the sections from disk) */
if(!(flags & H5FS_ADD_DESERIALIZING)) {
- if(H5FS_sect_serialize_size(f, dxpl_id, fspace) < 0)
+ if(H5FS_sect_serialize_size(fspace) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTCOMPUTE, FAIL, "can't adjust free space section size on disk")
} /* end if */
} /* end else */
- /* Mark free space header as dirty */
- if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty")
-
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5FS_sect_increase() */
@@ -331,7 +596,7 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_sect_decrease(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, const H5FS_section_class_t *cls)
+H5FS_sect_decrease(H5FS_t *fspace, const H5FS_section_class_t *cls)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -365,14 +630,10 @@ HDfprintf(stderr, "%s: cls->serial_size = %Zu\n", FUNC, cls->serial_size);
fspace->sinfo->serial_size -= cls->serial_size;
/* Update the free space sections' serialized size */
- if(H5FS_sect_serialize_size(f, dxpl_id, fspace) < 0)
+ if(H5FS_sect_serialize_size(fspace) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTCOMPUTE, FAIL, "can't adjust free space section size on disk")
} /* end else */
- /* Mark free space header as dirty */
- if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty")
-
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5FS_sect_decrease() */
@@ -446,7 +707,7 @@ HDfprintf(stderr, "%s: sinfo->bins[%u].sect_count = %Zu\n", FUNC, bin, sinfo->bi
HDassert(fspace_node->serial_count == 0);
/* Remove size tracking list from bin */
- tmp_fspace_node = H5SL_remove(sinfo->bins[bin].bin_list, &fspace_node->sect_size);
+ tmp_fspace_node = (H5FS_node_t *)H5SL_remove(sinfo->bins[bin].bin_list, &fspace_node->sect_size);
if(tmp_fspace_node == NULL || tmp_fspace_node != fspace_node)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space node from skip list")
@@ -455,7 +716,7 @@ HDfprintf(stderr, "%s: sinfo->bins[%u].sect_count = %Zu\n", FUNC, bin, sinfo->bi
HGOTO_ERROR(H5E_FSPACE, H5E_CANTCLOSEOBJ, FAIL, "can't destroy size tracking node's skip list")
/* Release free space list node */
- H5FL_FREE(H5FS_node_t, fspace_node);
+ (void)H5FL_FREE(H5FS_node_t, fspace_node);
/* Decrement total number of section sizes managed */
sinfo->tot_size_count--;
@@ -504,11 +765,11 @@ H5FS_sect_unlink_size(H5FS_sinfo_t *sinfo, const H5FS_section_class_t *cls,
HGOTO_ERROR(H5E_FSPACE, H5E_NOTFOUND, FAIL, "node's bin is empty?")
/* Find space node for section's size */
- if((fspace_node = H5SL_search(sinfo->bins[bin].bin_list, &sect->size)) == NULL)
+ if((fspace_node = (H5FS_node_t *)H5SL_search(sinfo->bins[bin].bin_list, &sect->size)) == NULL)
HGOTO_ERROR(H5E_FSPACE, H5E_NOTFOUND, FAIL, "can't find section size node")
/* Remove the section's node from the list */
- tmp_sect_node = H5SL_remove(fspace_node->sect_list, &sect->addr);
+ tmp_sect_node = (H5FS_section_info_t *)H5SL_remove(fspace_node->sect_list, &sect->addr);
if(tmp_sect_node == NULL || tmp_sect_node != sect)
HGOTO_ERROR(H5E_FSPACE, H5E_NOTFOUND, FAIL, "can't find section node on size list")
@@ -538,15 +799,14 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_sect_unlink_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
- const H5FS_section_class_t *cls, H5FS_section_info_t *sect)
+H5FS_sect_unlink_rest(H5FS_t *fspace, const H5FS_section_class_t *cls,
+ H5FS_section_info_t *sect)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_unlink_rest)
/* Check arguments. */
- HDassert(f);
HDassert(fspace);
HDassert(fspace->sinfo);
HDassert(cls);
@@ -559,13 +819,13 @@ H5FS_sect_unlink_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
#ifdef QAK
HDfprintf(stderr, "%s: removing object from merge list, sect->type = %u\n", FUNC, (unsigned)sect->type);
#endif /* QAK */
- tmp_sect_node = H5SL_remove(fspace->sinfo->merge_list, &sect->addr);
+ tmp_sect_node = (H5FS_section_info_t *)H5SL_remove(fspace->sinfo->merge_list, &sect->addr);
if(tmp_sect_node == NULL || tmp_sect_node != sect)
HGOTO_ERROR(H5E_FSPACE, H5E_NOTFOUND, FAIL, "can't find section node on size list")
} /* end if */
/* Update section info & check if we need less room for the serialized free space sections */
- if(H5FS_sect_decrease(f, dxpl_id, fspace, cls) < 0)
+ if(H5FS_sect_decrease(fspace, cls) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't increase free space section size on disk")
/* Decrement amount of free space managed */
@@ -574,17 +834,13 @@ HDfprintf(stderr, "%s: fspace->tot_space = %Hu\n", FUNC, fspace->tot_space);
#endif /* QAK */
fspace->tot_space -= sect->size;
- /* Mark free space sections as changed */
- if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace->sinfo) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space sections as dirty")
-
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5FS_sect_unlink_rest() */
/*-------------------------------------------------------------------------
- * Function: H5FS_sect_remove
+ * Function: H5FS_sect_remove_real
*
* Purpose: Remove a section from the free space manager
*
@@ -596,17 +852,15 @@ done:
*
*-------------------------------------------------------------------------
*/
-herr_t
-H5FS_sect_remove(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
- H5FS_section_info_t *sect)
+static herr_t
+H5FS_sect_remove_real(H5FS_t *fspace, H5FS_section_info_t *sect)
{
const H5FS_section_class_t *cls; /* Class of section */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_remove)
+ FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_remove_real)
/* Check arguments. */
- HDassert(f);
HDassert(fspace);
HDassert(fspace->sinfo);
HDassert(sect);
@@ -619,11 +873,56 @@ H5FS_sect_remove(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "can't remove section from size tracking data structures")
/* Update rest of free space manager data structures for node removal */
- if(H5FS_sect_unlink_rest(f, dxpl_id, fspace, cls, sect) < 0)
+ if(H5FS_sect_unlink_rest(fspace, cls, sect) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "can't remove section from non-size tracking data structures")
done:
FUNC_LEAVE_NOAPI(ret_value)
+} /* H5FS_sect_remove_real() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FS_sect_remove
+ *
+ * Purpose: Remove a section from the free space manager
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Wednesday, May 17, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FS_sect_remove(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
+ H5FS_section_info_t *sect)
+{
+ hbool_t sinfo_valid = FALSE; /* Whether the section info is valid */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_remove)
+
+ /* Check arguments. */
+ HDassert(f);
+ HDassert(fspace);
+ HDassert(sect);
+
+ /* Get a pointer to the section info */
+ if(H5FS_sinfo_lock(f, dxpl_id, fspace, H5AC_WRITE) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't get section info")
+ sinfo_valid = TRUE;
+
+ /* Perform actual section removal */
+ if(H5FS_sect_remove_real(fspace, sect) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove section")
+
+done:
+ /* Release the section info */
+ if(sinfo_valid && H5FS_sinfo_unlock(f, dxpl_id, fspace, TRUE) < 0)
+ HDONE_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't release section info")
+
+ FUNC_LEAVE_NOAPI(ret_value)
} /* H5FS_sect_remove() */
@@ -668,7 +967,7 @@ HDfprintf(stderr, "%s: sect->size = %Hu, sect->addr = %a\n", FUNC, sect->size, s
} /* end if */
else {
/* Check for node list of the correct size already */
- fspace_node = H5SL_search(sinfo->bins[bin].bin_list, &sect->size);
+ fspace_node = (H5FS_node_t *)H5SL_search(sinfo->bins[bin].bin_list, &sect->size);
} /* end else */
/* Check if we need to create a new skip list for nodes of this size */
@@ -741,7 +1040,7 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_sect_link_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, const H5FS_section_class_t *cls,
+H5FS_sect_link_rest(H5FS_t *fspace, const H5FS_section_class_t *cls,
H5FS_section_info_t *sect, unsigned flags)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -749,7 +1048,6 @@ H5FS_sect_link_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, const H5FS_section_
FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_link_rest)
/* Check arguments. */
- HDassert(f);
HDassert(fspace);
HDassert(fspace->sinfo);
HDassert(sect);
@@ -767,7 +1065,7 @@ HDfprintf(stderr, "%s: inserting object into merge list, sect->type = %u\n", FUN
} /* end if */
/* Update section info & check if we need more room for the serialized free space sections */
- if(H5FS_sect_increase(f, dxpl_id, fspace, cls, flags) < 0)
+ if(H5FS_sect_increase(fspace, cls, flags) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't increase free space section size on disk")
/* Increment amount of free space managed */
@@ -793,8 +1091,7 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_sect_link(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
- H5FS_section_info_t *sect, unsigned flags)
+H5FS_sect_link(H5FS_t *fspace, H5FS_section_info_t *sect, unsigned flags)
{
const H5FS_section_class_t *cls; /* Class of section */
herr_t ret_value = SUCCEED; /* Return value */
@@ -802,7 +1099,6 @@ H5FS_sect_link(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_link)
/* Check arguments. */
- HDassert(f);
HDassert(fspace);
HDassert(fspace->sinfo);
HDassert(sect);
@@ -821,7 +1117,7 @@ HDfprintf(stderr, "%s: Check 1.0 - fspace->tot_space = %Hu\n", FUNC, fspace->tot
HDfprintf(stderr, "%s: Check 2.0 - fspace->tot_space = %Hu\n", FUNC, fspace->tot_space);
#endif /* QAK */
/* Update rest of free space manager data structures for section addition */
- if(H5FS_sect_link_rest(f, dxpl_id, fspace, cls, sect, flags) < 0)
+ if(H5FS_sect_link_rest(fspace, cls, sect, flags) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't add section to non-size tracking data structures")
#ifdef QAK
HDfprintf(stderr, "%s: Check 3.0 - fspace->tot_space = %Hu\n", FUNC, fspace->tot_space);
@@ -832,6 +1128,7 @@ done:
} /* H5FS_sect_link() */
+
/*-------------------------------------------------------------------------
* Function: H5FS_sect_merge
*
@@ -839,21 +1136,26 @@ done:
* free space.
*
* Return: Success: non-negative
- *
* Failure: negative
*
* Programmer: Quincey Koziol
* Wednesday, May 17, 2006
*
+ * Modifications: Vailin Choi; Sept 25th 2008
+ * Changes to the "shrinking" part--
+ * 1. Get last section node in merge-list instead of "less-than"
+ * node for further iteration
+ * 2. Remove "can-be-shrunk" section from free-space instead of
+ * "less-than" section
+ *
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
- H5FS_section_info_t **sect, void *op_data)
+H5FS_sect_merge(H5FS_t *fspace, H5FS_section_info_t **sect, void *op_data)
{
H5FS_section_class_t *sect_cls; /* Section's class */
- H5FS_section_info_t *tmp_sect_node; /* Temporary free space section */
hbool_t modified; /* Flag to indicate merge or shrink occurred */
+ hbool_t remove_sect = FALSE; /* Whether a section should be removed before shrinking */
htri_t status; /* Status value */
herr_t ret_value = SUCCEED; /* Return value */
@@ -868,43 +1170,54 @@ H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
/* Loop until no more merging */
if(fspace->sinfo->merge_list) {
do {
+ H5SL_node_t *less_sect_node; /* Skip list node for section less than new section */
+ H5SL_node_t *greater_sect_node; /* Skip list node for section greater than new section */
+ H5FS_section_info_t *tmp_sect; /* Temporary free space section */
H5FS_section_class_t *tmp_sect_cls; /* Temporary section's class */
+ hbool_t greater_sect_node_valid = FALSE; /* Indicate if 'greater than' section node is valid */
/* Reset 'modification occurred' flag */
modified = FALSE;
/* Look for neighboring section before new section */
- tmp_sect_node = H5SL_less(fspace->sinfo->merge_list, &(*sect)->addr);
+ less_sect_node = H5SL_below(fspace->sinfo->merge_list, &(*sect)->addr);
/* Check for node before new node able to merge with new node */
- if(tmp_sect_node) {
+ if(less_sect_node) {
+ /* Check for node greater than section */
+ greater_sect_node = H5SL_next(less_sect_node);
+ greater_sect_node_valid = TRUE;
+
+ /* Get section for 'less than' skip list node */
+ tmp_sect = H5SL_item(less_sect_node);
+
/* Get classes for right & left sections */
- tmp_sect_cls = &fspace->sect_cls[tmp_sect_node->type];
+ tmp_sect_cls = &fspace->sect_cls[tmp_sect->type];
sect_cls = &fspace->sect_cls[(*sect)->type];
/* Check if sections of the left most class can merge with sections
* of another class & whether the sections are the same type,
* then check for 'can merge' callback
*/
- if((!(tmp_sect_cls->flags & H5FS_CLS_MERGE_SYM) || (tmp_sect_node->type == (*sect)->type))
+ if((!(tmp_sect_cls->flags & H5FS_CLS_MERGE_SYM) || (tmp_sect->type == (*sect)->type))
&& tmp_sect_cls->can_merge) {
/* Determine if the sections can merge */
- if((status = (*tmp_sect_cls->can_merge)(tmp_sect_node, *sect, op_data)) < 0)
+ if((status = (*tmp_sect_cls->can_merge)(tmp_sect, *sect, op_data)) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTMERGE, FAIL, "can't check for merging sections")
if(status > 0) {
/* Sanity check */
HDassert(tmp_sect_cls->merge);
/* Remove 'less than' node from data structures */
- if(H5FS_sect_remove(f, dxpl_id, fspace, tmp_sect_node) < 0)
+ if(H5FS_sect_remove_real(fspace, tmp_sect) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't remove section from internal data structures")
/* Merge the two sections together */
- if((*tmp_sect_cls->merge)(tmp_sect_node, *sect, op_data) < 0)
+ if((*tmp_sect_cls->merge)(tmp_sect, *sect, op_data) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't merge two sections")
/* Retarget section pointer to 'less than' node that was merged into */
- *sect = tmp_sect_node;
+ *sect = tmp_sect;
/* Indicate successful merge occurred */
modified = TRUE;
@@ -912,35 +1225,39 @@ H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
} /* end if */
} /* end if */
- /* Look for section after new (or merged) section */
- tmp_sect_node = H5SL_greater(fspace->sinfo->merge_list, &(*sect)->addr);
+ /* Look for section after new (or merged) section, if not already determined */
+ if(!greater_sect_node_valid)
+ greater_sect_node = H5SL_above(fspace->sinfo->merge_list, &(*sect)->addr);
/* Check for node after new node able to merge with new node */
- if(tmp_sect_node) {
+ if(greater_sect_node) {
+ /* Get section for 'greater than' skip list node */
+ tmp_sect = H5SL_item(greater_sect_node);
+
/* Get classes for right & left sections */
sect_cls = &fspace->sect_cls[(*sect)->type];
- tmp_sect_cls = &fspace->sect_cls[tmp_sect_node->type];
+ tmp_sect_cls = &fspace->sect_cls[tmp_sect->type];
/* Check if sections of the left most class can merge with sections
* of another class & whether the sections are the same type,
* then check for 'can merge' callback
*/
- if((!(sect_cls->flags & H5FS_CLS_MERGE_SYM) || ((*sect)->type == tmp_sect_node->type))
+ if((!(sect_cls->flags & H5FS_CLS_MERGE_SYM) || ((*sect)->type == tmp_sect->type))
&& sect_cls->can_merge) {
/* Determine if the sections can merge */
- if((status = (*sect_cls->can_merge)(*sect, tmp_sect_node, op_data)) < 0)
+ if((status = (*sect_cls->can_merge)(*sect, tmp_sect, op_data)) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTMERGE, FAIL, "can't check for merging sections")
if(status > 0) {
/* Sanity check */
HDassert(sect_cls->merge);
/* Remove 'greater than' node from data structures */
- if(H5FS_sect_remove(f, dxpl_id, fspace, tmp_sect_node) < 0)
+ if(H5FS_sect_remove_real(fspace, tmp_sect) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't remove section from internal data structures")
/* Merge the two sections together */
- if((*sect_cls->merge)(*sect, tmp_sect_node, op_data) < 0)
+ if((*sect_cls->merge)(*sect, tmp_sect, op_data) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't merge two sections")
/* Indicate successful merge occurred */
@@ -948,7 +1265,7 @@ H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
} /* end if */
} /* end if */
} /* end if */
- } while(modified);
+ } while(modified);
} /* end if */
HDassert(*sect);
#ifdef QAK
@@ -969,15 +1286,14 @@ HDfprintf(stderr, "%s: Done merging, (*sect) = {%a, %Hu, %u, %s}\n", FUNC, (*sec
#ifdef QAK
HDfprintf(stderr, "%s: Can shrink!\n", FUNC);
#endif /* QAK */
- /* Look for neighboring section before new section */
- if(fspace->sinfo->merge_list) {
- tmp_sect_node = H5SL_less(fspace->sinfo->merge_list, &(*sect)->addr);
- /* Make certain there isn't a section after the new section */
- HDassert(H5SL_greater(fspace->sinfo->merge_list, &(*sect)->addr) == NULL);
- } /* end if */
- else
- tmp_sect_node = NULL;
+ /* Remove SECT from free-space manager */
+ /* (only possible to happen on second+ pass through loop) */
+ if(remove_sect) {
+ if(H5FS_sect_remove_real(fspace, *sect) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't remove section from internal data structures")
+ remove_sect = FALSE;
+ } /* end if */
/* Shrink the container */
/* (callback can indicate that it has discarded the section by setting *sect to NULL) */
@@ -985,20 +1301,34 @@ HDfprintf(stderr, "%s: Can shrink!\n", FUNC);
if((*sect_cls->shrink)(sect, op_data) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't shrink free space container")
- /* Check if the new section was removed */
- if(*sect == NULL && tmp_sect_node) {
- /* Remove 'less than' node from data structures */
- if(H5FS_sect_remove(f, dxpl_id, fspace, tmp_sect_node) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't remove section from internal data structures")
-
- *sect = tmp_sect_node;
- } /* end if */
+ /* If this section was shrunk away, we may need to shrink another section */
+ if(*sect == NULL) {
+ /* Check for sections on merge list */
+ if(fspace->sinfo->merge_list) {
+ H5SL_node_t *last_node; /* Last node in merge list */
+
+ /* Check for last node in the merge list */
+ if(NULL != (last_node = H5SL_last(fspace->sinfo->merge_list))) {
+ /* Get the pointer to the last section, from the last node */
+ *sect = H5SL_item(last_node);
+ HDassert(*sect);
+
+ /* Indicate that this section needs to be removed if it causes a shrink */
+ remove_sect = TRUE;
+ } /* end if */
+ } /* end if */
+ } /* end if */
/* Indicate successful merge occurred */
modified = TRUE;
} /* end if */
} /* end if */
} while(modified && *sect);
+
+ /* Check for section that was shrunk away and next section not shrinking */
+ if(remove_sect && (*sect != NULL))
+ *sect = NULL;
+
#ifdef QAK
HDfprintf(stderr, "%s: Done shrinking\n", FUNC);
if(*sect)
@@ -1034,13 +1364,15 @@ H5FS_sect_add(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t *sect
unsigned flags, void *op_data)
{
H5FS_section_class_t *cls; /* Section's class */
+ hbool_t sinfo_valid = FALSE; /* Whether the section info is valid */
+ hbool_t sinfo_modified = FALSE; /* Whether the section info was modified */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5FS_sect_add, FAIL)
-#ifdef QAK
+#ifdef H5FS_SINFO_DEBUG
HDfprintf(stderr, "%s: *sect = {%a, %Hu, %u, %s}\n", FUNC, sect->addr, sect->size, sect->type, (sect->state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED"));
-#endif /* QAK */
+#endif /* H5FS_SINFO_DEBUG */
/* Check arguments. */
HDassert(fspace);
@@ -1048,11 +1380,10 @@ HDfprintf(stderr, "%s: *sect = {%a, %Hu, %u, %s}\n", FUNC, sect->addr, sect->siz
HDassert(H5F_addr_defined(sect->addr));
HDassert(sect->size);
- /* Check if we need to go get the sections */
- if(fspace->sinfo == NULL) {
- if(NULL == (fspace->sinfo = H5FS_sinfo_pin(f, dxpl_id, fspace)))
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTDECODE, FAIL, "can't pin sections")
- } /* end if */
+ /* Get a pointer to the section info */
+ if(H5FS_sinfo_lock(f, dxpl_id, fspace, H5AC_WRITE) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't get section info")
+ sinfo_valid = TRUE;
/* Call "add" section class callback, if there is one */
cls = &fspace->sect_cls[sect->type];
@@ -1063,12 +1394,12 @@ HDfprintf(stderr, "%s: *sect = {%a, %Hu, %u, %s}\n", FUNC, sect->addr, sect->siz
/* Check for merging returned space with existing section node */
if(flags & H5FS_ADD_RETURNED_SPACE) {
-#ifdef QAK
+#ifdef H5FS_SINFO_DEBUG
HDfprintf(stderr, "%s: Returning space\n", FUNC);
-#endif /* QAK */
+#endif /* H5FS_SINFO_DEBUG */
/* Attempt to merge returned section with existing sections */
- if(H5FS_sect_merge(f, dxpl_id, fspace, &sect, op_data) < 0)
+ if(H5FS_sect_merge(fspace, &sect, op_data) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTMERGE, FAIL, "can't merge sections")
} /* end if */
@@ -1077,29 +1408,157 @@ HDfprintf(stderr, "%s: Returning space\n", FUNC);
* be NULL at this point - QAK)
*/
if(sect)
- if(H5FS_sect_link(f, dxpl_id, fspace, sect, flags) < 0)
+ if(H5FS_sect_link(fspace, sect, flags) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't insert free space section into skip list")
-#ifdef QAK
-HDfprintf(stderr, "%s: fspace->hdr->tot_space = %Hu\n", FUNC, fspace->hdr->tot_space);
-#endif /* QAK */
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: fspace->tot_space = %Hu\n", FUNC, fspace->tot_space);
+#endif /* H5FS_SINFO_DEBUG */
/* Mark free space sections as changed */
/* (if adding sections while deserializing sections, don't set the flag) */
- if(!(flags & H5FS_ADD_DESERIALIZING)) {
- if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace->sinfo) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space sections as dirty")
- } /* end if */
+ if(!(flags & H5FS_ADD_DESERIALIZING))
+ sinfo_modified = TRUE;
done:
-#ifdef H5FS_DEBUG
+ /* Release the section info */
+ if(sinfo_valid && H5FS_sinfo_unlock(f, dxpl_id, fspace, sinfo_modified) < 0)
+ HDONE_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't release section info")
+
+#ifdef H5FS_DEBUG_ASSERT
if(!(flags & (H5FS_ADD_DESERIALIZING | H5FS_ADD_SKIP_VALID)))
H5FS_assert(fspace);
-#endif /* H5FS_DEBUG */
+#endif /* H5FS_DEBUG_ASSERT */
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: Leaving, ret_value = %d\n", FUNC, ret_value);
+#endif /* H5FS_SINFO_DEBUG */
FUNC_LEAVE_NOAPI(ret_value)
} /* H5FS_sect_add() */
/*-------------------------------------------------------------------------
+ * Function: H5FS_sect_try_extend
+ *
+ * Purpose: Try to extend a block using space from a section on the free list
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, January 8, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5FS_sect_try_extend(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, haddr_t addr,
+ hsize_t size, hsize_t extra_requested)
+{
+ hbool_t sinfo_valid = FALSE; /* Whether the section info is valid */
+ hbool_t sinfo_modified = FALSE; /* Whether the section info was modified */
+ htri_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5FS_sect_try_extend, FAIL)
+
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: addr = %a, size = %Hu, extra_requested = %hu\n", FUNC, addr, size, extra_requested);
+#endif /* H5FS_SINFO_DEBUG */
+
+ /* Check arguments. */
+ HDassert(f);
+ HDassert(fspace);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(size > 0);
+ HDassert(extra_requested > 0);
+
+ /* Check for any sections on free space list */
+#ifdef H5FS_SINFO_DEBUG
+HDfprintf(stderr, "%s: fspace->tot_sect_count = %Hu\n", FUNC, fspace->tot_sect_count);
+HDfprintf(stderr, "%s: fspace->serial_sect_count = %Hu\n", FUNC, fspace->serial_sect_count);
+HDfprintf(stderr, "%s: fspace->ghost_sect_count = %Hu\n", FUNC, fspace->ghost_sect_count);
+#endif /* H5FS_SINFO_DEBUG */
+ if(fspace->tot_sect_count > 0) {
+ H5FS_section_info_t *sect; /* Temporary free space section */
+
+ /* Get a pointer to the section info */
+ if(H5FS_sinfo_lock(f, dxpl_id, fspace, H5AC_WRITE) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't get section info")
+ sinfo_valid = TRUE;
+
+
+/*
+
+Pseudo-code for algorithm:
+
+_section_ = <Get pointer to section with address > _region.addr_>
+if(_section_)
+ if(_section_ adjoins _region_ && _section.size_ >= _extra_requested_)
+ <remove section from data structures>
+ if(_section.size_ > _extra_requested_)
+ if(<can adjust _section_>)
+ <adjust _section_ by _extra_requested_>
+ <add adjusted section back to data structures>
+ else
+ <re-add UNadjusted section back to data structures>
+ <error>
+ <mark free space sections as changed in metadata cache>
+
+*/
+ /* Look for a section after block to extend */
+ if((sect = H5SL_greater(fspace->sinfo->merge_list, &addr))) {
+ /* Check if this section adjoins the block and is large enough to
+ * fulfill extension request.
+ *
+ * (Note: we assume that the section is fully merged with any
+ * possible neighboring nodes and is not at the end of the file
+ * (or it would have been eliminated), etc)
+ */
+ if(sect->size >= extra_requested && (addr + size) == sect->addr) {
+ /* Remove section from data structures */
+ if(H5FS_sect_remove_real(fspace, sect) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't remove section from internal data structures")
+
+ /* Check for the section needing to be adjusted and re-added */
+ /* (Note: we should probably add a can_adjust/adjust callback
+ * to the section class structure, but we don't need it
+ * for the current usage, so I've deferred messing with
+ * it. - QAK - 2008/01/08)
+ */
+ if(sect->size > extra_requested) {
+ H5FS_section_class_t *cls; /* Section's class */
+
+ /* Get class for section */
+ cls = &fspace->sect_cls[sect->type];
+
+ /* Sanity check (for now) */
+ HDassert(cls->flags & H5FS_CLS_ADJUST_OK);
+
+ /* Adjust section by amount requested */
+ sect->addr += extra_requested;
+ sect->size -= extra_requested;
+
+ /* Re-add adjusted section to free sections data structures */
+ if(H5FS_sect_link(fspace, sect, 0) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't insert free space section into skip list")
+ } /* end if */
+
+ /* Note that we modified the section info */
+ sinfo_modified = TRUE;
+
+ /* Indicate success */
+ HGOTO_DONE(TRUE);
+ } /* end if */
+ } /* end if */
+ } /* end if */
+
+done:
+ /* Release the section info */
+ if(sinfo_valid && H5FS_sinfo_unlock(f, dxpl_id, fspace, sinfo_modified) < 0)
+ HDONE_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't release section info")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5FS_sect_try_extend() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5FS_sect_find_node
*
* Purpose: Locate a section of free space (in existing free space list
@@ -1112,6 +1571,11 @@ if(!(flags & (H5FS_ADD_DESERIALIZING | H5FS_ADD_SKIP_VALID)))
* Programmer: Quincey Koziol
* Monday, March 20, 2006
*
+ * Modifications:
+ * Vailin Choi, July 29th, 2008
+ * Modified to handle alignment by going through each bin to find
+ * a section that is big enough to fulfill "request+fragment for alignment"
+ *
*-------------------------------------------------------------------------
*/
static htri_t
@@ -1121,6 +1585,10 @@ H5FS_sect_find_node(H5FS_t *fspace, hsize_t request, H5FS_section_info_t **node)
unsigned bin; /* Bin to put the free space section in */
htri_t ret_value = FALSE; /* Return value */
+ H5SL_node_t *curr_size_node=NULL;
+ const H5FS_section_class_t *cls; /* Class of section */
+ hsize_t alignment;
+
FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_find_node)
/* Check arguments. */
@@ -1133,43 +1601,113 @@ H5FS_sect_find_node(H5FS_t *fspace, hsize_t request, H5FS_section_info_t **node)
/* Determine correct bin which holds items of at least the section's size */
bin = H5V_log2_gen(request);
HDassert(bin < fspace->sinfo->nbins);
- while(bin < fspace->sinfo->nbins && fspace->sinfo->bins[bin].bin_list == NULL)
- bin++;
-
- /* Find the first free space section that is large enough to fulfill request */
- /* (Since the bins use skip lists to track the sizes of the address-ordered
- * lists, this is actually a "best fit" algorithm)
- */
#ifdef QAK
HDfprintf(stderr, "%s: fspace->sinfo->nbins = %u\n", FUNC, fspace->sinfo->nbins);
HDfprintf(stderr, "%s: bin = %u\n", FUNC, bin);
#endif /* QAK */
- if(bin < fspace->sinfo->nbins)
- do {
- /* Look for large enough free space section in this bin */
- if(fspace->sinfo->bins[bin].bin_list)
- /* Check for large enough list of sections on list */
- if((fspace_node = H5SL_greater(fspace->sinfo->bins[bin].bin_list, &request))) {
- const H5FS_section_class_t *cls; /* Class of section */
-
- /* Take first node off of the list (ie. node w/lowest address) */
- if(NULL == (*node = H5SL_remove_first(fspace_node->sect_list)))
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space node from skip list")
+ alignment = fspace->alignment;
+ if(!((alignment > 1) && (request >= fspace->threshold)))
+ alignment = 0; /* no alignment */
- /* Get section's class */
- cls = &fspace->sect_cls[(*node)->type];
+ do {
+ /* Check if there's any sections in this bin */
+ if(fspace->sinfo->bins[bin].bin_list) {
+
+ if (!alignment) { /* no alignment */
+ /* Find the first free space section that is large enough to fulfill request */
+ /* (Since the bins use skip lists to track the sizes of the address-ordered
+ * lists, this is actually a "best fit" algorithm)
+ */
+ /* Look for large enough free space section in this bin */
+ if((fspace_node = (H5FS_node_t *)H5SL_greater(fspace->sinfo->bins[bin].bin_list, &request))) {
+ /* Take first node off of the list (ie. node w/lowest address) */
+ if(NULL == (*node = (H5FS_section_info_t *)H5SL_remove_first(fspace_node->sect_list)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space node from skip list")
+
+ /* Get section's class */
+ cls = &fspace->sect_cls[(*node)->type];
+ /* Decrement # of sections in section size node */
+ if(H5FS_size_node_decr(fspace->sinfo, bin, fspace_node, cls) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space size node from skip list")
+ if(H5FS_sect_unlink_rest(fspace, cls, *node) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "can't remove section from non-size tracking data structures")
+ /* Indicate that we found a node for the request */
+ HGOTO_DONE(TRUE)
+ } /* end if */
+ } /* end if */
+ else { /* alignment is set */
+ /* get the first node of a certain size in this bin */
+ curr_size_node = H5SL_first(fspace->sinfo->bins[bin].bin_list);
+ while (curr_size_node != NULL) {
+ H5FS_node_t *curr_fspace_node=NULL;
+ H5SL_node_t *curr_sect_node=NULL;
+
+ /* Get the free space node for free space sections of the same size */
+ curr_fspace_node = H5SL_item(curr_size_node);
+
+ /* Get the Skip list which holds pointers to actual free list sections */
+ curr_sect_node = H5SL_first(curr_fspace_node->sect_list);
- /* Decrement # of sections in section size node */
- if(H5FS_size_node_decr(fspace->sinfo, bin, fspace_node, cls) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space size node from skip list")
+ while(curr_sect_node != NULL) {
+ H5FS_section_info_t *curr_sect=NULL;
+ hsize_t mis_align=0, frag_size=0;
+ H5FS_section_info_t *split_sect=NULL;
+
+ /* Get section node */
+ curr_sect = H5SL_item(curr_sect_node);
+
+ HDassert(H5F_addr_defined(curr_sect->addr));
+ HDassert(curr_fspace_node->sect_size == curr_sect->size);
+
+ cls = &fspace->sect_cls[curr_sect->type];
+
+ HDassert(alignment);
+ HDassert(cls);
+
+ if ((mis_align = curr_sect->addr % alignment))
+ frag_size = alignment - mis_align;
+
+ if ((curr_sect->size >= (request + frag_size)) && (cls->split)) {
+ /* remove the section with aligned address */
+ if(NULL == (*node = H5SL_remove(curr_fspace_node->sect_list, &curr_sect->addr)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space node from skip list")
+ /* Decrement # of sections in section size node */
+ if(H5FS_size_node_decr(fspace->sinfo, bin, curr_fspace_node, cls) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTREMOVE, FAIL, "can't remove free space size node from skip list")
+
+ if(H5FS_sect_unlink_rest(fspace, cls, *node) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "can't remove section from non-size tracking data structures")
+
+ /*
+ * The split() callback splits NODE into 2 sections:
+ * split_sect is the unused fragment for aligning NODE
+ * NODE's addr & size are updated to point to the remaining aligned section
+ * split_sect is re-added to free-space
+ */
+ if (mis_align) {
+ split_sect = cls->split(*node, frag_size);
+ if((H5FS_sect_link(fspace, split_sect, 0) < 0))
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't insert free space section into skip list")
+ /* sanity check */
+ HDassert(split_sect->addr < (*node)->addr);
+ HDassert(request <= (*node)->size);
+ }
+ /* Indicate that we found a node for the request */
+ HGOTO_DONE(TRUE)
+ }
- /* Indicate that we found a node for the request */
- HGOTO_DONE(TRUE)
- } /* end if */
+ /* Get the next section node in the list */
+ curr_sect_node = H5SL_next(curr_sect_node);
+ } /* end while of curr_sect_node */
- /* Advance to next larger bin */
- bin++;
- } while(bin < fspace->sinfo->nbins);
+ /* Get the next size node in the bin */
+ curr_size_node = H5SL_next(curr_size_node);
+ } /* end while of curr_size_node */
+ } /* else of alignment */
+ } /* if bin_list */
+ /* Advance to next larger bin */
+ bin++;
+ } while(bin < fspace->sinfo->nbins);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1189,12 +1727,18 @@ done:
* Programmer: Quincey Koziol
* Tuesday, March 7, 2006
*
+ * Modifications:
+ * Vailin Choi, July 29th 2008
+ * Move H5FS_sect_unlink_rest() to H5FS_sect_find_node()
+ *
*-------------------------------------------------------------------------
*/
htri_t
H5FS_sect_find(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, hsize_t request,
H5FS_section_info_t **node)
{
+ hbool_t sinfo_valid = FALSE; /* Whether the section info is valid */
+ hbool_t sinfo_modified = FALSE; /* Whether the section info was modified */
htri_t ret_value = FALSE; /* Return value */
FUNC_ENTER_NOAPI(H5FS_sect_find, FAIL)
@@ -1209,12 +1753,6 @@ HDfprintf(stderr, "%s: request = %Hu\n", FUNC, request);
HDassert(request);
HDassert(node);
- /* Check if we need to go get the sections */
- if(fspace->sinfo == NULL) {
- if(NULL == (fspace->sinfo = H5FS_sinfo_pin(f, dxpl_id, fspace)))
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTDECODE, FAIL, "can't pin sections")
- } /* end if */
-
/* Check for any sections on free space list */
#ifdef QAK
HDfprintf(stderr, "%s: fspace->tot_sect_count = %Hu\n", FUNC, fspace->tot_sect_count);
@@ -1222,215 +1760,38 @@ HDfprintf(stderr, "%s: fspace->serial_sect_count = %Hu\n", FUNC, fspace->serial_
HDfprintf(stderr, "%s: fspace->ghost_sect_count = %Hu\n", FUNC, fspace->ghost_sect_count);
#endif /* QAK */
if(fspace->tot_sect_count > 0) {
+ /* Get a pointer to the section info */
+ if(H5FS_sinfo_lock(f, dxpl_id, fspace, H5AC_WRITE) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't get section info")
+ sinfo_valid = TRUE;
+
/* Look for node in bins */
if((ret_value = H5FS_sect_find_node(fspace, request, node)) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "can't remove section from bins")
/* Decrement # of sections on free list, if we found an object */
if(ret_value > 0) {
- const H5FS_section_class_t *cls; /* Class of section */
-
- /* Get section's class */
- cls = &fspace->sect_cls[(*node)->type];
-
- /* Update rest of free space manager data structures for node removal */
- if(H5FS_sect_unlink_rest(f, dxpl_id, fspace, cls, *node) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "can't remove section from non-size tracking data structures")
+ /* Note that we've modified the section info */
+ sinfo_modified = TRUE;
#ifdef QAK
HDfprintf(stderr, "%s: (*node)->size = %Hu, (*node)->addr = %a, (*node)->type = %u\n", FUNC, (*node)->size, (*node)->addr, (*node)->type);
#endif /* QAK */
- } /* end if */
+ }
} /* end if */
done:
-#ifdef H5FS_DEBUG
+ /* Release the section info */
+ if(sinfo_valid && H5FS_sinfo_unlock(f, dxpl_id, fspace, sinfo_modified) < 0)
+ HDONE_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't release section info")
+
+#ifdef H5FS_DEBUG_ASSERT
H5FS_assert(fspace);
-#endif /* H5FS_DEBUG */
+#endif /* H5FS_DEBUG_ASSERT */
FUNC_LEAVE_NOAPI(ret_value)
} /* H5FS_sect_find() */
/*-------------------------------------------------------------------------
- * Function: H5FS_sect_serialize_size
- *
- * Purpose: Determine serialized size of all sections in free space manager
- * And adjust space on disk for storing serialized sections
- *
- * Return: Success: non-negative
- * Failure: negative
- *
- * Programmer: Quincey Koziol
- * Monday, May 8, 2006
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5FS_sect_serialize_size(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace)
-{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_serialize_size)
-
- /* Check arguments. */
- HDassert(fspace);
-#ifdef QAK
-HDfprintf(stderr, "%s: Check 1.0 - fspace->sect_size = %Hu\n", FUNC, fspace->sect_size);
-HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu\n", FUNC, fspace->alloc_sect_size);
-HDfprintf(stderr, "%s: fspace->sinfo->serial_size_count = %Zu\n", FUNC, fspace->sinfo->serial_size_count);
-#endif /* QAK */
-
- /* Compute the size of the buffer required to serialize all the sections */
- if(fspace->serial_sect_count > 0) {
- size_t sect_buf_size; /* Section buffer size */
-
- /* Serialized sections prefix */
- sect_buf_size = fspace->sinfo->sect_prefix_size;
-
- /* Count for each differently sized serializable section */
-#ifdef QAK
-HDfprintf(stderr, "%s: fspace->sinfo->serial_size_count = %Zu\n", FUNC, fspace->sinfo->serial_size_count);
-HDfprintf(stderr, "%s: fspace->serial_sect_count = %Hu\n", FUNC, fspace->serial_sect_count);
-#endif /* QAK */
- sect_buf_size += fspace->sinfo->serial_size_count * MAX(1, ((H5V_log2_gen(fspace->serial_sect_count) + 7) / 8));
-
- /* Size for each differently sized serializable section */
- sect_buf_size += fspace->sinfo->serial_size_count * fspace->sinfo->sect_len_size;
-
- /* Offsets of each section in address space */
- sect_buf_size += fspace->serial_sect_count * fspace->sinfo->sect_off_size;
-
- /* Class of each section */
- sect_buf_size += fspace->serial_sect_count * 1;
-
- /* Extra space required to serialize each section */
- sect_buf_size += fspace->sinfo->serial_size;
-
- /* Update section size in header */
- fspace->sect_size = sect_buf_size;
- } /* end if */
- else
- /* Reset section size in header */
- fspace->sect_size = H5FS_SINFO_SIZE_DEFAULT;
-
-#ifdef QAK
-HDfprintf(stderr, "%s: Check 2.0 - fspace->sect_size = %Hu\n", FUNC, fspace->sect_size);
-HDfprintf(stderr, "%s: fspace->alloc_sect_size = %Hu\n", FUNC, fspace->alloc_sect_size);
-#endif /* QAK */
- if(fspace->sect_size > fspace->alloc_sect_size) {
- size_t new_size; /* New size of space for serialized sections */
- haddr_t old_addr; /* Old address of serialized sections */
-
-/* Currently, the old block data is "thrown away" after the space is reallocated,
- * so avoid data copy in H5MF_realloc() call by just free'ing the space and
- * allocating new space.
- *
- * This also keeps the file smaller, by freeing the space and then
- * allocating new space, instead of vice versa (in H5MF_realloc).
- *
- * QAK - 5/ 8/2006
- */
- /* Free previous serialized sections disk space */
- old_addr = fspace->sect_addr;
- if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, old_addr, fspace->alloc_sect_size) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space sections")
-
- /* Compute new size */
- H5_ASSIGN_OVERFLOW(/* To: */ new_size, /* From: */ fspace->alloc_sect_size, /* From: */ hsize_t, /* To: */ size_t);
- while(new_size < fspace->sect_size)
- new_size *= (double)fspace->expand_percent / 100.0;
- fspace->alloc_sect_size = new_size;
-
- /* Allocate space for the new serialized sections on disk */
-#ifdef QAK
-HDfprintf(stderr, "%s: Allocating space for larger serialized sections, new_size = %Zu\n", FUNC, new_size);
-HDfprintf(stderr, "%s: fspace->sect_size = %Hu\n", FUNC, fspace->sect_size);
-#endif /* QAK */
- if(HADDR_UNDEF == (fspace->sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, (hsize_t)fspace->alloc_sect_size)))
- HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections")
-#ifdef QAK
-HDfprintf(stderr, "%s: old_addr = %a, fspace->sect_addr = %a\n", FUNC, old_addr, fspace->sect_addr);
-#endif /* QAK */
-
- /* Move object in cache, if it actually was relocated */
- if(H5F_addr_ne(fspace->sect_addr, old_addr)) {
- if(H5AC_rename(f, H5AC_FSPACE_SINFO, old_addr, fspace->sect_addr) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTRENAME, FAIL, "unable to move free space section info")
- } /* end if */
- else {
- /* Mark free space section as dirty */
- if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace->sinfo) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space section info as dirty")
- } /* end else */
-
- /* Mark free space header as dirty */
- if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty")
- } /* end if */
- else {
- size_t decrease_threshold; /* Size threshold for decreasing serialized section size */
- haddr_t old_addr; /* Old address of serialized sections */
-
- /* Compute the threshold for decreasing the sections' serialized size */
- decrease_threshold = (size_t)(((size_t)fspace->alloc_sect_size * (double)fspace->shrink_percent) / 100.0);
-
- if(fspace->alloc_sect_size > H5FS_SINFO_SIZE_DEFAULT &&
- fspace->sect_size < decrease_threshold) {
- size_t new_size = 0; /* New size of space for serialized sections */
-
-/* Currently, the old block data is "thrown away" after the space is reallocated,
- * so avoid data copy in H5MF_realloc() call by just free'ing the space and
- * allocating new space.
- *
- * This also keeps the file smaller, by freeing the space and then
- * allocating new space, instead of vice versa (in H5MF_realloc).
- *
- * QAK - 5/ 8/2006
- */
- /* Free previous serialized sections disk space */
- old_addr = fspace->sect_addr;
- if(H5MF_xfree(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, old_addr, fspace->alloc_sect_size) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to free free space sections")
-
- /* Compute new size */
- while(fspace->sect_size < decrease_threshold) {
- new_size = decrease_threshold;
-
- decrease_threshold *= (double)fspace->shrink_percent / 100.0;
- } /* end while */
- if(new_size < H5FS_SINFO_SIZE_DEFAULT)
- new_size = H5FS_SINFO_SIZE_DEFAULT;
- fspace->alloc_sect_size = new_size;
-
- /* Allocate space for the new serialized sections on disk */
-#ifdef QAK
-HDfprintf(stderr, "%s: Allocating space for smaller serialized sections, new_size = %Zu\n", FUNC, new_size);
-#endif /* QAK */
- if(HADDR_UNDEF == (fspace->sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SINFO, dxpl_id, (hsize_t)fspace->alloc_sect_size)))
- HGOTO_ERROR(H5E_FSPACE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections")
-
- /* Move object in cache, if it actually was relocated */
- if(H5F_addr_ne(fspace->sect_addr, old_addr)) {
- if(H5AC_rename(f, H5AC_FSPACE_SINFO, old_addr, fspace->sect_addr) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTRENAME, FAIL, "unable to move free space section info")
- } /* end if */
- else {
- /* Mark free space section as dirty */
- if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace->sinfo) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space section info as dirty")
- } /* end else */
-
- /* Mark free space header as dirty */
- if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space header as dirty")
- } /* end if */
- } /* end else */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5FS_sect_serialize_size() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5FS_iterate_sect_cb
*
* Purpose: Skip list iterator callback to iterate over free space sections
@@ -1524,7 +1885,8 @@ done:
herr_t
H5FS_sect_iterate(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_operator_t op, void *op_data)
{
- H5FS_iter_ud_t udata; /* User data for callbacks */
+ H5FS_iter_ud_t udata; /* User data for callbacks */
+ hbool_t sinfo_valid = FALSE; /* Whether the section info is valid */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_iterate)
@@ -1533,14 +1895,8 @@ H5FS_sect_iterate(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_operator_t op, v
HDassert(fspace);
HDassert(op);
- /* Check if we need to go get the sections */
- if(fspace->sinfo == NULL) {
- if(NULL == (fspace->sinfo = H5FS_sinfo_pin(f, dxpl_id, fspace)))
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTDECODE, FAIL, "can't pin sections")
- } /* end if */
-
#ifdef QAK
-HDfprintf(stderr, "%s: fspace->hdr->sect_count = %Hu\n", FUNC, fspace->hdr->sect_count);
+HDfprintf(stderr, "%s: fspace->tot_sect_count = %Hu\n", FUNC, fspace->tot_sect_count);
#endif /* QAK */
/* Set up user data for iterator */
@@ -1552,6 +1908,11 @@ HDfprintf(stderr, "%s: fspace->hdr->sect_count = %Hu\n", FUNC, fspace->hdr->sect
if(fspace->tot_sect_count) {
unsigned bin; /* Current bin we are on */
+ /* Get a pointer to the section info */
+ if(H5FS_sinfo_lock(f, dxpl_id, fspace, H5AC_READ) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't get section info")
+ sinfo_valid = TRUE;
+
/* Iterate over all the bins */
#ifdef QAK
HDfprintf(stderr, "%s: Iterate over section bins\n", FUNC);
@@ -1567,17 +1928,20 @@ HDfprintf(stderr, "%s: Iterate over section bins\n", FUNC);
} /* end if */
done:
+ /* Release the section info */
+ if(sinfo_valid && H5FS_sinfo_unlock(f, dxpl_id, fspace, FALSE) < 0)
+ HDONE_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't release section info")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* H5FS_sect_iterate() */
/*-------------------------------------------------------------------------
- * Function: H5FS_get_sect_count
+ * Function: H5FS_sect_stats
*
- * Purpose: Retrieve the number of sections managed
+ * Purpose: Retrieve info about the sections managed
*
* Return: Success: non-negative
- *
* Failure: negative
*
* Programmer: Quincey Koziol
@@ -1586,19 +1950,21 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5FS_get_sect_count(const H5FS_t *fspace, hsize_t *nsects)
+H5FS_sect_stats(const H5FS_t *fspace, hsize_t *tot_space, hsize_t *nsects)
{
- FUNC_ENTER_NOAPI_NOFUNC(H5FS_get_sect_count)
+ FUNC_ENTER_NOAPI_NOFUNC(H5FS_sect_stats)
/* Check arguments. */
HDassert(fspace);
- HDassert(nsects);
- /* Get the section count */
- *nsects = fspace->tot_sect_count;
+ /* Get the stats desired */
+ if(tot_space)
+ *tot_space = fspace->tot_space;
+ if(nsects)
+ *nsects = fspace->tot_sect_count;
FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5FS_get_sect_count() */
+} /* H5FS_sect_stats() */
/*-------------------------------------------------------------------------
@@ -1623,17 +1989,22 @@ H5FS_sect_change_class(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
const H5FS_section_class_t *old_cls; /* Old class of section */
const H5FS_section_class_t *new_cls; /* New class of section */
unsigned old_class; /* Old class ID of section */
+ hbool_t sinfo_valid = FALSE; /* Whether the section info is valid */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_change_class)
/* Check arguments. */
HDassert(fspace);
- HDassert(fspace->sinfo);
HDassert(sect);
HDassert(sect->type < fspace->nclasses);
HDassert(new_class < fspace->nclasses);
+ /* Get a pointer to the section info */
+ if(H5FS_sinfo_lock(f, dxpl_id, fspace, H5AC_WRITE) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't get section info")
+ sinfo_valid = TRUE;
+
/* Get class info */
old_class = sect->type;
old_cls = &fspace->sect_cls[sect->type];
@@ -1667,7 +2038,7 @@ HDfprintf(stderr, "%s: to_ghost = %u\n", FUNC, to_ghost);
HDassert(fspace->sinfo->bins[bin].bin_list);
/* Get space node for section's size */
- fspace_node = H5SL_search(fspace->sinfo->bins[bin].bin_list, &sect->size);
+ fspace_node = (H5FS_node_t *)H5SL_search(fspace->sinfo->bins[bin].bin_list, &sect->size);
HDassert(fspace_node);
/* Adjust serializable/ghost counts */
@@ -1741,7 +2112,7 @@ HDfprintf(stderr, "%s: inserting object into merge list, sect->type = %u\n", FUN
#ifdef QAK
HDfprintf(stderr, "%s: removing object from merge list, sect->type = %u\n", FUNC, (unsigned)sect->type);
#endif /* QAK */
- tmp_sect_node = H5SL_remove(fspace->sinfo->merge_list, &sect->addr);
+ tmp_sect_node = (H5FS_section_info_t *)H5SL_remove(fspace->sinfo->merge_list, &sect->addr);
if(tmp_sect_node == NULL || tmp_sect_node != sect)
HGOTO_ERROR(H5E_FSPACE, H5E_NOTFOUND, FAIL, "can't find section node on size list")
} /* end else */
@@ -1755,18 +2126,18 @@ HDfprintf(stderr, "%s: removing object from merge list, sect->type = %u\n", FUNC
fspace->sinfo->serial_size += fspace->sect_cls[new_class].serial_size;
/* Update current space used for free space sections */
- if(H5FS_sect_serialize_size(f, dxpl_id, fspace) < 0)
+ if(H5FS_sect_serialize_size(fspace) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTCOMPUTE, FAIL, "can't adjust free space section size on disk")
-
- /* Mark free space sections as dirty */
- if(H5AC_mark_pinned_or_protected_entry_dirty(f, fspace->sinfo) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTMARKDIRTY, FAIL, "unable to mark free space sections as dirty")
done:
+ /* Release the section info */
+ if(sinfo_valid && H5FS_sinfo_unlock(f, dxpl_id, fspace, TRUE) < 0)
+ HDONE_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't release section info")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* H5FS_sect_change_class() */
-#ifdef H5FS_DEBUG
+#ifdef H5FS_DEBUG_ASSERT
/*-------------------------------------------------------------------------
* Function: H5FS_sect_assert
@@ -1787,8 +2158,8 @@ H5FS_sect_assert(const H5FS_t *fspace)
hsize_t separate_obj; /* The number of separate objects managed */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_sect_assert)
-#ifdef QAK
-HDfprintf(stderr, "%s: fspace->hdr->tot_sect_count = %Hu\n", "H5FS_sect_assert", fspace->hdr->tot_sect_count);
+#ifndef QAK
+HDfprintf(stderr, "%s: fspace->tot_sect_count = %Hu\n", "H5FS_sect_assert", fspace->tot_sect_count);
#endif /* QAK */
/* Initialize state */
@@ -1916,5 +2287,5 @@ HDfprintf(stderr, "%s: sect->size = %Hu, sect->addr = %a, sect->type = %u\n", "H
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5FS_sect_assert() */
-#endif /* H5FS_DEBUG */
+#endif /* H5FS_DEBUG_ASSERT */
diff --git a/src/H5FSstat.c b/src/H5FSstat.c
new file mode 100644
index 0000000..7b2cb0d
--- /dev/null
+++ b/src/H5FSstat.c
@@ -0,0 +1,101 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Purpose: Free-space metadata statistics functions.
+ *
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5FS_PACKAGE /*suppress error about including H5FSpkg */
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5FSpkg.h" /* Free-space manager */
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FS_stat_info
+ *
+ * Purpose: Retrieve metadata statistics for the free-space manager
+ *
+ * Return: Success: non-negative
+ *
+ * Failure: does not fail
+ *
+ * Programmer: Vailin Choi
+ * August 25th, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FS_stat_info(const H5FS_t *frsp, H5FS_stat_t *stats)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_stat_info)
+
+ /* Check arguments. */
+ HDassert(frsp);
+ HDassert(stats);
+
+ /* Report statistics for free space */
+ stats->tot_space = frsp->tot_space;
+ stats->tot_sect_count = frsp->tot_sect_count;
+ stats->serial_sect_count = frsp->serial_sect_count;
+ stats->ghost_sect_count = frsp->ghost_sect_count;
+ /* can add more metadata statistics for the free-space manager */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5FS_stat_info() */
diff --git a/src/H5FStest.c b/src/H5FStest.c
new file mode 100644
index 0000000..719e553
--- /dev/null
+++ b/src/H5FStest.c
@@ -0,0 +1,154 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Purpose: Free-space manager testing functions.
+ *
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5FS_PACKAGE /*suppress error about including H5FSpkg */
+#define H5FS_TESTING /*suppress warning about H5FS testing funcs */
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5FSpkg.h" /* Free-space manager */
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_get_cparam_test
+ *
+ * Purpose: Retrieve the parameters used to create the free-space manager
+ *
+ * Return: Success: non-negative
+ *
+ * Failure: negative
+ *
+ * Programmer: similar to H5HF_get_cparam_test()
+ * Vailin Choi; August 25th, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FS_get_cparam_test(const H5FS_t *frsp, H5FS_create_t *cparam)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_get_cparam_test)
+
+ /* Check arguments. */
+ HDassert(frsp);
+ HDassert(cparam);
+
+ cparam->client = frsp->client;
+ cparam->shrink_percent = frsp->shrink_percent;
+ cparam->expand_percent = frsp->expand_percent;
+ cparam->max_sect_addr = frsp->max_sect_addr;
+ cparam->max_sect_size = frsp->max_sect_size;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5FS_get_cparam_test() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_cmp_cparam_test
+ *
+ * Purpose: Compare the parameters used to create the fractal heap
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: similar to H5HF_cmp_cparam_test()
+ * Vailin Choi; August 25th, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+H5FS_cmp_cparam_test(const H5FS_create_t *cparam1, const H5FS_create_t *cparam2)
+{
+ int ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_cmp_cparam_test)
+
+ /* Check arguments. */
+ HDassert(cparam1);
+ HDassert(cparam2);
+
+ if(cparam1->client < cparam2->client)
+ HGOTO_DONE(-1)
+ else if(cparam1->client > cparam2->client)
+ HGOTO_DONE(1)
+
+ if(cparam1->shrink_percent < cparam2->shrink_percent)
+ HGOTO_DONE(-1)
+ else if(cparam1->shrink_percent > cparam2->shrink_percent)
+ HGOTO_DONE(1)
+
+ if(cparam1->expand_percent < cparam2->expand_percent)
+ HGOTO_DONE(-1)
+ else if(cparam1->expand_percent > cparam2->expand_percent)
+ HGOTO_DONE(1)
+
+ if(cparam1->max_sect_size < cparam2->max_sect_size)
+ HGOTO_DONE(-1)
+ else if(cparam1->max_sect_size > cparam2->max_sect_size)
+ HGOTO_DONE(1)
+
+ if(cparam1->max_sect_addr < cparam2->max_sect_addr)
+ HGOTO_DONE(-1)
+ else if(cparam1->max_sect_addr > cparam2->max_sect_addr)
+ HGOTO_DONE(1)
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5FS_cmp_cparam_test */
diff --git a/src/H5Faccum.c b/src/H5Faccum.c
new file mode 100644
index 0000000..05f6910
--- /dev/null
+++ b/src/H5Faccum.c
@@ -0,0 +1,656 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5Faccum.c
+ * Jan 10 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: File metadata "accumulator" routines. (Used to
+ * cache small metadata I/Os and group them into a
+ * single larger I/O)
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5F_PACKAGE /*suppress error about including H5Fpkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fpkg.h" /* File access */
+#include "H5FDprivate.h" /* File drivers */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+/* Metadata accumulator controls */
+#define H5F_ACCUM_THROTTLE 8
+#define H5F_ACCUM_THRESHOLD 2048
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* Declare a PQ free list to manage the metadata accumulator buffer */
+H5FL_BLK_DEFINE_STATIC(meta_accum);
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_accum_read
+ *
+ * Purpose: Attempts to read some data from the metadata accumulator for
+ * a file into a buffer.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jan 10 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5F_accum_read(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr,
+ size_t size, void *buf/*out*/)
+{
+ htri_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5F_accum_read, FAIL)
+
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(buf);
+
+ /* Check if this information is in the metadata accumulator */
+ if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && type != H5FD_MEM_DRAW) {
+ /* Current read overlaps with metadata accumulator */
+ if(H5F_addr_overlap(addr, size, f->shared->accum.loc, f->shared->accum.size)) {
+ unsigned char *read_buf = (unsigned char *)buf; /* Pointer to the buffer being read in */
+ size_t amount_read; /* Amount to read at a time */
+ hsize_t read_off; /* Offset to read from */
+
+ /* Read the part before the metadata accumulator */
+ if(addr < f->shared->accum.loc) {
+ /* Set the amount to read */
+ H5_ASSIGN_OVERFLOW(amount_read, (f->shared->accum.loc - addr), hsize_t, size_t);
+
+ /* Dispatch to driver */
+ if(H5FD_read(f->shared->lf, dxpl_id, type, addr, amount_read, read_buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed")
+
+ /* Adjust the buffer, address & size */
+ read_buf += amount_read;
+ addr += amount_read;
+ size -= amount_read;
+ } /* end if */
+
+ /* Copy the part overlapping the metadata accumulator */
+ if(size > 0 && (addr >= f->shared->accum.loc && addr < (f->shared->accum.loc + f->shared->accum.size))) {
+ /* Set the offset to "read" from */
+ read_off = addr - f->shared->accum.loc;
+
+ /* Set the amount to "read" */
+#ifndef NDEBUG
+{
+ hsize_t tempamount_read; /* Amount to read at a time */
+
+ tempamount_read = f->shared->accum.size - read_off;
+ H5_CHECK_OVERFLOW(tempamount_read, hsize_t, size_t);
+ amount_read = MIN(size, (size_t)tempamount_read);
+}
+#else /* NDEBUG */
+ amount_read = MIN(size, (size_t)(f->shared->accum.size - read_off));
+#endif /* NDEBUG */
+
+ /* Copy the data out of the buffer */
+ HDmemcpy(read_buf, f->shared->accum.buf + read_off, amount_read);
+
+ /* Adjust the buffer, address & size */
+ read_buf += amount_read;
+ addr += amount_read;
+ size -= amount_read;
+ } /* end if */
+
+ /* Read the part after the metadata accumulator */
+ if(size > 0 && addr >= (f->shared->accum.loc + f->shared->accum.size)) {
+ /* Dispatch to driver */
+ if(H5FD_read(f->shared->lf, dxpl_id, type, addr, size, read_buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed")
+
+ /* Adjust the buffer, address & size */
+ read_buf += size;
+ addr += size;
+ size -= size;
+ } /* end if */
+
+ /* Make certain we've read it all */
+ HDassert(size == 0);
+ } /* end if */
+ /* Current read doesn't overlap with metadata accumulator, read it into accumulator */
+ else {
+ /* Only update the metadata accumulator if it is not dirty or if
+ * we are allowed to write the accumulator out during reads (when
+ * it is dirty)
+ */
+ if(f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA_READ || !f->shared->accum.dirty) {
+ /* Flush current contents, if dirty */
+ if(f->shared->accum.dirty) {
+ if(H5FD_write(f->shared->lf, dxpl_id, H5FD_MEM_DEFAULT, f->shared->accum.loc, f->shared->accum.size, f->shared->accum.buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "driver write request failed")
+
+ /* Reset accumulator dirty flag */
+ f->shared->accum.dirty = FALSE;
+ } /* end if */
+
+ /* Cache the new piece of metadata */
+ /* Check if we need to resize the buffer */
+ if(size > f->shared->accum.alloc_size) {
+ /* Grow the metadata accumulator buffer */
+ if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
+
+ /* Note the new buffer size */
+ f->shared->accum.alloc_size = size;
+ } /* end if */
+ else {
+ /* Check if we should shrink the accumulator buffer */
+ if(size < (f->shared->accum.alloc_size / H5F_ACCUM_THROTTLE) &&
+ f->shared->accum.alloc_size > H5F_ACCUM_THRESHOLD) {
+ size_t new_size = (f->shared->accum.alloc_size / H5F_ACCUM_THROTTLE); /* New size of accumulator buffer */
+
+ /* Shrink the accumulator buffer */
+ if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, new_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
+
+ /* Note the new buffer size */
+ f->shared->accum.alloc_size = new_size;
+ } /* end if */
+ } /* end else */
+
+ /* Update accumulator information */
+ f->shared->accum.loc = addr;
+ f->shared->accum.size = size;
+ f->shared->accum.dirty = FALSE;
+
+ /* Read into accumulator */
+ if(H5FD_read(f->shared->lf, dxpl_id, H5FD_MEM_DEFAULT, f->shared->accum.loc, f->shared->accum.size, f->shared->accum.buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed")
+
+ /* Copy into buffer */
+ HDmemcpy(buf, f->shared->accum.buf, size);
+ } /* end if */
+ else {
+ /* Dispatch to driver */
+ if(H5FD_read(f->shared->lf, dxpl_id, type, addr, size, buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed")
+ } /* end else */
+ } /* end else */
+
+ /* Indicate success */
+ HGOTO_DONE(TRUE);
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_accum_read() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_accum_write
+ *
+ * Purpose: Attempts to read some data from the metadata accumulator for
+ * a file into a buffer.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jan 10 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5F_accum_write(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr,
+ size_t size, const void *buf)
+{
+ htri_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5F_accum_write, FAIL)
+
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(f->intent & H5F_ACC_RDWR);
+ HDassert(buf);
+
+ /* Check for accumulating metadata */
+ if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && type != H5FD_MEM_DRAW) {
+ /* Check if there is already metadata in the accumulator */
+ if(f->shared->accum.size > 0) {
+ /* Check if the new metadata adjoins the beginning of the current accumulator */
+ if((addr + size) == f->shared->accum.loc) {
+ /* Check if we need more buffer space */
+ if((size + f->shared->accum.size) > f->shared->accum.alloc_size) {
+ /* Adjust the buffer size, by doubling it */
+ f->shared->accum.alloc_size = MAX(f->shared->accum.alloc_size * 2, size + f->shared->accum.size);
+
+ /* Reallocate the metadata accumulator buffer */
+ if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, f->shared->accum.alloc_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
+#ifdef H5_CLEAR_MEMORY
+HDmemset(f->shared->accum.buf + f->shared->accum.size, 0, (f->shared->accum.alloc_size - (f->shared->accum.size + size)));
+#endif /* H5_CLEAR_MEMORY */
+ } /* end if */
+
+ /* Move the existing metadata to the proper location */
+ HDmemmove(f->shared->accum.buf + size, f->shared->accum.buf, f->shared->accum.size);
+
+ /* Copy the new metadata at the front */
+ HDmemcpy(f->shared->accum.buf, buf, size);
+
+ /* Set the new size & location of the metadata accumulator */
+ f->shared->accum.loc = addr;
+ f->shared->accum.size += size;
+
+ /* Mark it as written to */
+ f->shared->accum.dirty = TRUE;
+ } /* end if */
+ /* Check if the new metadata adjoins the end of the current accumulator */
+ else if(addr == (f->shared->accum.loc + f->shared->accum.size)) {
+ /* Check if we need more buffer space */
+ if((size + f->shared->accum.size) > f->shared->accum.alloc_size) {
+ /* Adjust the buffer size, by doubling it */
+ f->shared->accum.alloc_size = MAX(f->shared->accum.alloc_size * 2, size + f->shared->accum.size);
+
+ /* Reallocate the metadata accumulator buffer */
+ if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, f->shared->accum.alloc_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
+#ifdef H5_CLEAR_MEMORY
+HDmemset(f->shared->accum.buf + f->shared->accum.size + size, 0, (f->shared->accum.alloc_size - (f->shared->accum.size + size)));
+#endif /* H5_CLEAR_MEMORY */
+ } /* end if */
+
+ /* Copy the new metadata to the end */
+ HDmemcpy(f->shared->accum.buf + f->shared->accum.size, buf, size);
+
+ /* Set the new size of the metadata accumulator */
+ f->shared->accum.size += size;
+
+ /* Mark it as written to */
+ f->shared->accum.dirty = TRUE;
+ } /* end if */
+ /* Check if the piece of metadata being written overlaps the metadata accumulator */
+ else if(H5F_addr_overlap(addr, size, f->shared->accum.loc, f->shared->accum.size)) {
+ size_t new_size; /* New size of the accumulator buffer */
+
+ /* Check if the new metadata is entirely within the current accumulator */
+ if(addr >= f->shared->accum.loc && (addr + size) <= (f->shared->accum.loc + f->shared->accum.size)) {
+ /* Copy the new metadata to the proper location within the accumulator */
+ HDmemcpy(f->shared->accum.buf + (addr - f->shared->accum.loc), buf, size);
+
+ /* Mark it as written to */
+ f->shared->accum.dirty = TRUE;
+ } /* end if */
+ /* Check if the new metadata overlaps the beginning of the current accumulator */
+ else if(addr < f->shared->accum.loc && (addr + size) <= (f->shared->accum.loc + f->shared->accum.size)) {
+ size_t old_offset; /* Offset of old data within the accumulator buffer */
+
+ /* Calculate the new accumulator size, based on the amount of overlap */
+ H5_ASSIGN_OVERFLOW(new_size, (f->shared->accum.loc - addr) + f->shared->accum.size, hsize_t, size_t);
+
+ /* Check if we need more buffer space */
+ if(new_size > f->shared->accum.alloc_size) {
+ /* Adjust the buffer size, by doubling it */
+ f->shared->accum.alloc_size = MAX(f->shared->accum.alloc_size + 2, new_size);
+
+ /* Reallocate the metadata accumulator buffer */
+ if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, f->shared->accum.alloc_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
+#ifdef H5_CLEAR_MEMORY
+HDmemset(f->shared->accum.buf + f->shared->accum.size, 0, (f->shared->accum.alloc_size - f->shared->accum.size));
+#endif /* H5_CLEAR_MEMORY */
+ } /* end if */
+
+ /* Calculate the proper offset of the existing metadata */
+ H5_ASSIGN_OVERFLOW(old_offset, (addr + size) - f->shared->accum.loc, hsize_t, size_t);
+
+ /* Move the existing metadata to the proper location */
+ HDmemmove(f->shared->accum.buf + size, f->shared->accum.buf + old_offset, (f->shared->accum.size - old_offset));
+
+ /* Copy the new metadata at the front */
+ HDmemcpy(f->shared->accum.buf, buf, size);
+
+ /* Set the new size & location of the metadata accumulator */
+ f->shared->accum.loc = addr;
+ f->shared->accum.size = new_size;
+
+ /* Mark it as written to */
+ f->shared->accum.dirty = TRUE;
+ } /* end if */
+ /* Check if the new metadata overlaps the end of the current accumulator */
+ else if(addr >= f->shared->accum.loc && (addr + size) > (f->shared->accum.loc + f->shared->accum.size)) {
+ /* Calculate the new accumulator size, based on the amount of overlap */
+ H5_ASSIGN_OVERFLOW(new_size, (addr - f->shared->accum.loc) + size, hsize_t, size_t);
+
+ /* Check if we need more buffer space */
+ if(new_size > f->shared->accum.alloc_size) {
+ /* Adjust the buffer size, by doubling it */
+ f->shared->accum.alloc_size = MAX(f->shared->accum.alloc_size * 2, new_size);
+
+ /* Reallocate the metadata accumulator buffer */
+ if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, f->shared->accum.alloc_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
+#ifdef H5_CLEAR_MEMORY
+HDmemset(f->shared->accum.buf + f->shared->accum.size, 0, (f->shared->accum.alloc_size - f->shared->accum.size));
+#endif /* H5_CLEAR_MEMORY */
+ } /* end if */
+
+ /* Copy the new metadata to the end */
+ HDmemcpy(f->shared->accum.buf + (addr - f->shared->accum.loc), buf, size);
+
+ /* Set the new size & location of the metadata accumulator */
+ f->shared->accum.size = new_size;
+
+ /* Mark it as written to */
+ f->shared->accum.dirty = TRUE;
+ } /* end if */
+ else {
+ HDassert(0 && "New metadata overlapped both beginning and end of existing metadata accumulator!");
+ } /* end else */
+ } /* end if */
+ /* New piece of metadata doesn't adjoin or overlap the existing accumulator */
+ else {
+ /* Write out the existing metadata accumulator, with dispatch to driver */
+ if(f->shared->accum.dirty) {
+ if(H5FD_write(f->shared->lf, dxpl_id, H5FD_MEM_DEFAULT, f->shared->accum.loc, f->shared->accum.size, f->shared->accum.buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
+
+ /* Reset accumulator dirty flag */
+ f->shared->accum.dirty = FALSE;
+ } /* end if */
+
+ /* Cache the new piece of metadata */
+ /* Check if we need to resize the buffer */
+ if(size > f->shared->accum.alloc_size) {
+ /* Grow the metadata accumulator buffer */
+ if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
+
+ /* Note the new buffer size */
+ f->shared->accum.alloc_size = size;
+#ifdef H5_CLEAR_MEMORY
+{
+size_t clear_size = MAX(f->shared->accum.size, size);
+HDmemset(f->shared->accum.buf + clear_size, 0, (f->shared->accum.alloc_size - clear_size));
+}
+#endif /* H5_CLEAR_MEMORY */
+ } /* end if */
+ else {
+ /* Check if we should shrink the accumulator buffer */
+ if(size < (f->shared->accum.alloc_size / H5F_ACCUM_THROTTLE) &&
+ f->shared->accum.alloc_size > H5F_ACCUM_THRESHOLD) {
+ size_t tmp_size = (f->shared->accum.alloc_size / H5F_ACCUM_THROTTLE); /* New size of accumulator buffer */
+
+ /* Shrink the accumulator buffer */
+ if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, tmp_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
+
+ /* Note the new buffer size */
+ f->shared->accum.alloc_size = tmp_size;
+ } /* end if */
+ } /* end else */
+
+ /* Update the metadata accumulator information */
+ f->shared->accum.loc = addr;
+ f->shared->accum.size = size;
+ f->shared->accum.dirty = TRUE;
+
+ /* Store the piece of metadata in the accumulator */
+ HDmemcpy(f->shared->accum.buf, buf, size);
+ } /* end else */
+ } /* end if */
+ /* No metadata in the accumulator, grab this piece and keep it */
+ else {
+ /* Check if we need to reallocate the buffer */
+ if(size > f->shared->accum.alloc_size) {
+ /* Reallocate the metadata accumulator buffer */
+ if(NULL == (f->shared->accum.buf = H5FL_BLK_REALLOC(meta_accum, f->shared->accum.buf, size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer")
+
+ /* Note the new buffer size */
+ f->shared->accum.alloc_size = size;
+ } /* end if */
+
+ /* Update the metadata accumulator information */
+ f->shared->accum.loc = addr;
+ f->shared->accum.size = size;
+ f->shared->accum.dirty = TRUE;
+
+ /* Store the piece of metadata in the accumulator */
+ HDmemcpy(f->shared->accum.buf, buf, size);
+ } /* end else */
+
+ /* Indicate success */
+ HGOTO_DONE(TRUE);
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_accum_write() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_accum_free
+ *
+ * Purpose: Check for free space invalidating [part of] a metadata
+ * accumulator.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jan 10 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_accum_free(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, haddr_t addr,
+ hsize_t size)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5F_accum_free, FAIL)
+
+ /* check arguments */
+ HDassert(f);
+
+ /* Adjust the metadata accumulator to remove the freed block, if it overlaps */
+ if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA)
+ && H5F_addr_overlap(addr, size, f->shared->accum.loc, f->shared->accum.size)) {
+ size_t overlap_size; /* Size of overlap with accumulator */
+
+ /* Sanity check */
+ /* (The metadata accumulator should not intersect w/raw data */
+ HDassert(H5FD_MEM_DRAW != type);
+
+ /* Check for overlapping the beginning of the accumulator */
+ if(H5F_addr_le(addr, f->shared->accum.loc)) {
+ /* Check for completely overlapping the accumulator */
+ if(H5F_addr_ge(addr + size, f->shared->accum.loc + f->shared->accum.size)) {
+ /* Reset the accumulator, but don't free buffer */
+ f->shared->accum.loc = HADDR_UNDEF;
+ f->shared->accum.size = 0;
+ f->shared->accum.dirty = FALSE;
+ } /* end if */
+ /* Block to free must end within the accumulator */
+ else {
+ size_t new_accum_size; /* Size of new accumulator buffer */
+
+ /* Calculate the size of the overlap with the accumulator, etc. */
+ H5_ASSIGN_OVERFLOW(overlap_size, (addr + size) - f->shared->accum.loc, haddr_t, size_t);
+ new_accum_size = f->shared->accum.size - overlap_size;
+
+ /* Move the accumulator buffer information to eliminate the freed block */
+ HDmemmove(f->shared->accum.buf, f->shared->accum.buf + overlap_size, new_accum_size);
+
+ /* Adjust the accumulator information */
+ f->shared->accum.loc += overlap_size;
+ f->shared->accum.size = new_accum_size;
+ } /* end else */
+ } /* end if */
+ /* Block to free must start within the accumulator */
+ else {
+ /* Calculate the size of the overlap with the accumulator */
+ H5_ASSIGN_OVERFLOW(overlap_size, (f->shared->accum.loc + f->shared->accum.size) - addr, haddr_t, size_t);
+
+ /* Block to free is in the middle of the accumulator */
+ if(H5F_addr_lt((addr + size), f->shared->accum.loc + f->shared->accum.size)) {
+ haddr_t tail_addr;
+ size_t tail_size;
+
+ /* Calculate the address & size of the tail to write */
+ tail_addr = addr + size;
+ H5_ASSIGN_OVERFLOW(tail_size, (f->shared->accum.loc + f->shared->accum.size) - tail_addr, haddr_t, size_t);
+
+ /* Write out the part of the accumulator after the block to free */
+ if(H5FD_write(f->shared->lf, dxpl_id, H5FD_MEM_DEFAULT, tail_addr, tail_size, f->shared->accum.buf + (tail_addr - f->shared->accum.loc)) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
+ } /* end if */
+
+ /* Adjust the accumulator information */
+ f->shared->accum.size = f->shared->accum.size - overlap_size;
+ } /* end else */
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_accum_free() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_accum_flush
+ *
+ * Purpose: Flush the metadata accumulator to the file
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jan 10 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_accum_flush(H5F_t *f, hid_t dxpl_id)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5F_accum_flush, FAIL)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ /* Check if we need to flush out the metadata accumulator */
+ if((f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && f->shared->accum.dirty && f->shared->accum.size > 0) {
+ /* Flush the metadata contents */
+ if(H5FD_write(f->shared->lf, dxpl_id, H5FD_MEM_DEFAULT, f->shared->accum.loc, f->shared->accum.size, f->shared->accum.buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
+
+ /* Reset the dirty flag */
+ f->shared->accum.dirty = FALSE;
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_accum_flush() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_accum_reset
+ *
+ * Purpose: Reset the metadata accumulator for the file
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jan 10 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_accum_reset(H5F_t *f)
+{
+ FUNC_ENTER_NOAPI_NOFUNC(H5F_accum_reset)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ /* Check if we need to reset the metadata accumulator information */
+ if(f->shared->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) {
+ /* Sanity check */
+ HDassert(!f->closing || FALSE == f->shared->accum.dirty);
+
+ /* Free the buffer */
+ if(f->shared->accum.buf)
+ f->shared->accum.buf = H5FL_BLK_FREE(meta_accum, f->shared->accum.buf);
+
+ /* Reset the buffer sizes & location */
+ f->shared->accum.alloc_size = f->shared->accum.size = 0;
+ f->shared->accum.loc = HADDR_UNDEF;
+ f->shared->accum.dirty = FALSE;
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5F_accum_reset() */
+
+
diff --git a/src/H5Fdbg.c b/src/H5Fdbg.c
index 15ca0d9..e05c32a 100644
--- a/src/H5Fdbg.c
+++ b/src/H5Fdbg.c
@@ -63,7 +63,7 @@ H5F_debug(H5F_t *f, FILE *stream, int indent, int fwidth)
HDassert(fwidth >= 0);
/* Get property list */
- if(NULL == (plist = H5I_object(f->shared->fcpl_id)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(f->shared->fcpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
/* Retrieve file creation properties */
@@ -82,7 +82,7 @@ H5F_debug(H5F_t *f, FILE *stream, int indent, int fwidth)
HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
"File open reference count:", f->shared->nrefs);
HDfprintf(stream, "%*s%-*s %a (abs)\n", indent, "", fwidth,
- "Address of super block:", f->shared->super_addr);
+ "Address of super block:", f->shared->base_addr);
HDfprintf(stream, "%*s%-*s %Hu bytes\n", indent, "", fwidth,
"Size of userblock:", userblock_size);
@@ -107,8 +107,6 @@ H5F_debug(H5F_t *f, FILE *stream, int indent, int fwidth)
"Symbol table internal node 1/2 rank:", f->shared->btree_k[H5B_SNODE_ID]);
HDfprintf(stream, "%*s%-*s 0x%02x\n", indent, "", fwidth,
"File status flags:", (unsigned)(f->shared->status_flags));
- HDfprintf(stream, "%*s%-*s %a (abs)\n", indent, "", fwidth,
- "Base address:", f->shared->base_addr);
HDfprintf(stream, "%*s%-*s %a (rel)\n", indent, "", fwidth,
"Superblock extension address:", f->shared->extension_addr);
HDfprintf(stream, "%*s%-*s %a (rel)\n", indent, "", fwidth,
diff --git a/src/H5Ffake.c b/src/H5Ffake.c
index 42a33e0..09e87f2 100644
--- a/src/H5Ffake.c
+++ b/src/H5Ffake.c
@@ -120,8 +120,8 @@ H5F_fake_free(H5F_t *f)
if(f) {
/* Destroy shared file struct */
if(f->shared)
- f->shared = H5FL_FREE(H5F_file_t, f->shared);
- H5FL_FREE(H5F_t, f);
+ f->shared = (H5F_file_t *)H5FL_FREE(H5F_file_t, f->shared);
+ (void)H5FL_FREE(H5F_t, f);
} /* end if */
FUNC_LEAVE_NOAPI(SUCCEED)
diff --git a/src/H5Fio.c b/src/H5Fio.c
new file mode 100644
index 0000000..1081a27
--- /dev/null
+++ b/src/H5Fio.c
@@ -0,0 +1,165 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5Fio.c
+ * Jan 10 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: File I/O routines.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5F_PACKAGE /*suppress error about including H5Fpkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fpkg.h" /* File access */
+#include "H5FDprivate.h" /* File drivers */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_block_read
+ *
+ * Purpose: Reads some data from a file/server/etc into a buffer.
+ * The data is contiguous. The address is relative to the base
+ * address for the file.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Jul 10 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_block_read(const H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
+ hid_t dxpl_id, void *buf/*out*/)
+{
+ htri_t accumulated; /* Whether the data was accepted by the metadata accumulator */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5F_block_read, FAIL)
+
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(buf);
+
+ /* Check if this I/O can be satisfied by the metadata accumulator */
+ if((accumulated = H5F_accum_read(f, dxpl_id, type, addr, size, buf)) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "read from metadata accumulator failed")
+ else if(accumulated == FALSE) {
+ /* Read the data */
+ if(H5FD_read(f->shared->lf, dxpl_id, type, addr, size, buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "driver read request failed")
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_block_read() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_block_write
+ *
+ * Purpose: Writes some data from memory to a file/server/etc. The
+ * data is contiguous. The address is relative to the base
+ * address.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Jul 10 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_block_write(const H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size,
+ hid_t dxpl_id, const void *buf)
+{
+ htri_t accumulated; /* Whether the data was accepted by the metadata accumulator */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5F_block_write, FAIL)
+#ifdef QAK
+HDfprintf(stderr, "%s: write to addr = %a, size = %Zu\n", FUNC, addr, size);
+#endif /* QAK */
+
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(f->intent & H5F_ACC_RDWR);
+ HDassert(buf);
+
+ /* Check for accumulating metadata */
+ if((accumulated = H5F_accum_write(f, dxpl_id, type, addr, size, buf)) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "write to metadata accumulator failed")
+ else if(accumulated == FALSE) {
+ /* Write the data */
+ if(H5FD_write(f->shared->lf, dxpl_id, type, addr, size, buf) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_block_write() */
+
diff --git a/src/H5Fmount.c b/src/H5Fmount.c
index 470d323..a428cd6 100644
--- a/src/H5Fmount.c
+++ b/src/H5Fmount.c
@@ -79,20 +79,32 @@ H5F_close_mounts(H5F_t *f)
HDassert(f);
- /* Unmount all child files */
- for (u = 0; u < f->mtab.nmounts; u++) {
- /* Detach the child file from the parent file */
- f->mtab.child[u].file->mtab.parent = NULL;
-
- /* Close the internal group maintaining the mount point */
- if(H5G_close(f->mtab.child[u].group) < 0)
+ /* Unmount all child files. Loop backwards to avoid having to adjust u when
+ * a file is unmounted. Note that we rely on unsigned u "wrapping around"
+ * to terminate the loop. */
+ for (u = f->shared->mtab.nmounts - 1; u < f->shared->mtab.nmounts; u--) {
+ /* Only unmount children mounted to this top level file structure */
+ if(f->shared->mtab.child[u].file->parent == f) {
+ /* Detach the child file from the parent file */
+ f->shared->mtab.child[u].file->parent = NULL;
+
+ /* Close the internal group maintaining the mount point */
+ if(H5G_close(f->shared->mtab.child[u].group) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "can't close child group")
- /* Close the child file */
- if(H5F_try_close(f->mtab.child[u].file) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close child file")
+ /* Close the child file */
+ if(H5F_try_close(f->shared->mtab.child[u].file) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close child file")
+
+ /* Eliminate the mount point from the table */
+ HDmemmove(f->shared->mtab.child + u, f->shared->mtab.child + u + 1,
+ (f->shared->mtab.nmounts - u - 1) * sizeof(f->shared->mtab.child[0]));
+ f->shared->mtab.nmounts--;
+ f->nmounts--;
+ }
} /* end if */
- f->mtab.nmounts = 0;
+
+ HDassert(f->nmounts == 0);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -135,7 +147,7 @@ H5F_mount(H5G_loc_t *loc, const char *name, H5F_t *child,
HDassert(child);
HDassert(TRUE == H5P_isa_class(plist_id, H5P_FILE_MOUNT));
- /* Set up dataset location to fill in */
+ /* Set up group location to fill in */
mp_loc.oloc = &mp_oloc;
mp_loc.path = &mp_path;
H5G_loc_reset(&mp_loc);
@@ -146,7 +158,7 @@ H5F_mount(H5G_loc_t *loc, const char *name, H5F_t *child,
* the parent & child files have the same file close degree, and
* that the mount wouldn't introduce a cycle in the mount tree.
*/
- if(child->mtab.parent)
+ if(child->parent)
HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "file is already mounted")
if(H5G_loc_find(loc, name, &mp_loc/*out*/, H5P_DEFAULT, dxpl_id) < 0)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "group not found")
@@ -155,12 +167,16 @@ H5F_mount(H5G_loc_t *loc, const char *name, H5F_t *child,
* user from doing this.
*/
if(mp_loc.oloc->holding_file != FALSE)
- HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "mount path cannot contain links to external files")
+ HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "mount path cannot contain links to external files")
/* Open the mount point group */
if(NULL == (mount_point = H5G_open(&mp_loc, dxpl_id)))
HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "mount point not found")
+ /* Check if the proposed mount point group is already a mount point */
+ if(H5G_MOUNTED(mount_point))
+ HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "mount point is already in use")
+
/* Retrieve information from the mount point group */
/* (Some of which we had before but was reset in mp_loc when the group
* "took over" the group location - QAK)
@@ -171,8 +187,8 @@ H5F_mount(H5G_loc_t *loc, const char *name, H5F_t *child,
HDassert(mp_loc.oloc);
mp_loc.path = H5G_nameof(mount_point);
HDassert(mp_loc.path);
- for(ancestor = parent; ancestor; ancestor = ancestor->mtab.parent) {
- if(ancestor == child)
+ for(ancestor = parent; ancestor; ancestor = ancestor->parent) {
+ if(ancestor->shared == child->shared)
HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "mount would introduce a cycle")
} /* end for */
@@ -186,13 +202,13 @@ H5F_mount(H5G_loc_t *loc, const char *name, H5F_t *child,
* `md' will be the index where the child should be inserted.
*/
lt = md = 0;
- rt = parent->mtab.nmounts;
+ rt = parent->shared->mtab.nmounts;
cmp = -1;
while(lt < rt && cmp) {
H5O_loc_t *oloc; /*temporary symbol table entry */
md = (lt + rt) / 2;
- oloc = H5G_oloc(parent->mtab.child[md].group);
+ oloc = H5G_oloc(parent->shared->mtab.child[md].group);
cmp = H5F_addr_cmp(mp_loc.oloc->addr, oloc->addr);
if(cmp < 0)
rt = md;
@@ -205,26 +221,27 @@ H5F_mount(H5G_loc_t *loc, const char *name, H5F_t *child,
HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "mount point is already in use")
/* Make room in the table */
- if(parent->mtab.nmounts >= parent->mtab.nalloc) {
- unsigned n = MAX(16, 2 * parent->mtab.nalloc);
- H5F_mount_t *x = H5MM_realloc(parent->mtab.child,
- n * sizeof(parent->mtab.child[0]));
+ if(parent->shared->mtab.nmounts >= parent->shared->mtab.nalloc) {
+ unsigned n = MAX(16, 2 * parent->shared->mtab.nalloc);
+ H5F_mount_t *x = (H5F_mount_t *)H5MM_realloc(parent->shared->mtab.child, n * sizeof(parent->shared->mtab.child[0]));
+
if(!x)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for mount table")
- parent->mtab.child = x;
- parent->mtab.nalloc = n;
+ parent->shared->mtab.child = x;
+ parent->shared->mtab.nalloc = n;
} /* end if */
/* Insert into table */
- HDmemmove(parent->mtab.child + md + 1, parent->mtab.child + md,
- (parent->mtab.nmounts-md) * sizeof(parent->mtab.child[0]));
- parent->mtab.nmounts++;
- parent->mtab.child[md].group = mount_point;
- parent->mtab.child[md].file = child;
- child->mtab.parent = parent;
+ HDmemmove(parent->shared->mtab.child + md + 1, parent->shared->mtab.child + md,
+ (parent->shared->mtab.nmounts-md) * sizeof(parent->shared->mtab.child[0]));
+ parent->shared->mtab.nmounts++;
+ parent->nmounts++;
+ parent->shared->mtab.child[md].group = mount_point;
+ parent->shared->mtab.child[md].file = child;
+ child->parent = parent;
/* Set the group's mountpoint flag */
- if(H5G_mount(parent->mtab.child[md].group) < 0)
+ if(H5G_mount(parent->shared->mtab.child[md].group) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to set group mounted flag")
/* Get the group location for the root group in the file to unmount */
@@ -311,16 +328,16 @@ H5F_unmount(H5G_loc_t *loc, const char *name, hid_t dxpl_id)
mnt_oloc = H5G_oloc(child->shared->root_grp);
child_idx = -1;
- if(child->mtab.parent && H5F_addr_eq(mp_oloc.addr, mnt_oloc->addr)) {
+ if(child->parent && H5F_addr_eq(mp_oloc.addr, mnt_oloc->addr)) {
unsigned u; /*counters */
/*
* We've been given the root group of the child. We do a reverse
* lookup in the parent's mount table to find the correct entry.
*/
- parent = child->mtab.parent;
- for(u = 0; u < parent->mtab.nmounts; u++) {
- if(parent->mtab.child[u].file == child) {
+ parent = child->parent;
+ for(u = 0; u < parent->shared->mtab.nmounts; u++) {
+ if(parent->shared->mtab.child[u].file->shared == child->shared) {
/* Found the correct index */
child_idx = u;
break;
@@ -336,11 +353,11 @@ H5F_unmount(H5G_loc_t *loc, const char *name, hid_t dxpl_id)
*/
parent = child; /*we guessed wrong*/
lt = 0;
- rt = parent->mtab.nmounts;
+ rt = parent->shared->mtab.nmounts;
cmp = -1;
while(lt < rt && cmp) {
md = (lt + rt) / 2;
- mnt_oloc = H5G_oloc(parent->mtab.child[md].group);
+ mnt_oloc = H5G_oloc(parent->shared->mtab.child[md].group);
cmp = H5F_addr_cmp(mp_oloc.addr, mnt_oloc->addr);
if (cmp<0)
rt = md;
@@ -355,13 +372,17 @@ H5F_unmount(H5G_loc_t *loc, const char *name, hid_t dxpl_id)
H5G_loc_free(&mp_loc);
mp_loc_setup = FALSE;
mp_loc.oloc = mnt_oloc;
- mp_loc.path = H5G_nameof(parent->mtab.child[md].group);
- child = parent->mtab.child[child_idx].file;
+ mp_loc.path = H5G_nameof(parent->shared->mtab.child[md].group);
+ child = parent->shared->mtab.child[child_idx].file;
+
+ /* Set the parent to be the actual parent of the discovered child.
+ * Could be different due to the shared mount table. */
+ parent = child->parent;
} /* end else */
HDassert(child_idx >= 0);
/* Save the information about the child from the mount table */
- child_group = parent->mtab.child[child_idx].group;
+ child_group = parent->shared->mtab.child[child_idx].group;
/* Get the group location for the root group in the file to unmount */
if(NULL == (root_loc.oloc = H5G_oloc(child->shared->root_grp)))
@@ -376,9 +397,10 @@ H5F_unmount(H5G_loc_t *loc, const char *name, hid_t dxpl_id)
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to replace name")
/* Eliminate the mount point from the table */
- HDmemmove(parent->mtab.child + child_idx, parent->mtab.child + child_idx + 1,
- (parent->mtab.nmounts-child_idx) * sizeof(parent->mtab.child[0]));
- parent->mtab.nmounts -= 1;
+ HDmemmove(parent->shared->mtab.child + child_idx, parent->shared->mtab.child + child_idx + 1,
+ (parent->shared->mtab.nmounts - child_idx - 1) * sizeof(parent->shared->mtab.child[0]));
+ parent->shared->mtab.nmounts -= 1;
+ parent->nmounts -= 1;
/* Unmount the child file from the parent file */
if(H5G_unmount(child_group) < 0)
@@ -387,7 +409,7 @@ H5F_unmount(H5G_loc_t *loc, const char *name, hid_t dxpl_id)
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "unable to close unmounted group")
/* Detach child file from parent & see if it should close */
- child->mtab.parent = NULL;
+ child->parent = NULL;
if(H5F_try_close(child) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close unmounted file")
@@ -401,37 +423,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5F_has_mount
- *
- * Purpose: Check if a file has mounted files within it.
- *
- * Return: Success: TRUE/FALSE
- * Failure: (can't happen)
- *
- * Programmer: Quincey Koziol
- * Thursday, January 2, 2002
- *
- *-------------------------------------------------------------------------
- */
-hbool_t
-H5F_has_mount(const H5F_t *file)
-{
- hbool_t ret_value; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_has_mount)
-
- HDassert(file);
-
- if(file->mtab.nmounts > 0)
- ret_value = TRUE;
- else
- ret_value = FALSE;
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_has_mount() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5F_is_mount
*
* Purpose: Check if a file is mounted within another file.
@@ -453,7 +444,7 @@ H5F_is_mount(const H5F_t *file)
HDassert(file);
- if(file->mtab.parent != NULL)
+ if(file->parent != NULL)
ret_value = TRUE;
else
ret_value = FALSE;
@@ -480,7 +471,7 @@ H5Fmount(hid_t loc_id, const char *name, hid_t child_id, hid_t plist_id)
{
H5G_loc_t loc;
H5F_t *child = NULL;
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(H5Fmount, FAIL)
H5TRACE4("e", "i*sii", loc_id, name, child_id, plist_id);
@@ -490,7 +481,7 @@ H5Fmount(hid_t loc_id, const char *name, hid_t child_id, hid_t plist_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name")
- if(NULL == (child = H5I_object_verify(child_id,H5I_FILE)))
+ if(NULL == (child = (H5F_t *)H5I_object_verify(child_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
if(H5P_DEFAULT == plist_id)
plist_id = H5P_FILE_MOUNT_DEFAULT;
@@ -583,15 +574,18 @@ H5F_mount_count_ids_recurse(H5F_t *f, unsigned *nopen_files, unsigned *nopen_obj
* (Reduced by number of mounted files, we'll add back in the mount point's
* groups later, if they are open)
*/
- *nopen_objs += (f->nopen_objs - f->mtab.nmounts);
+ *nopen_objs += (f->nopen_objs - f->nmounts);
/* Iterate over files mounted in this file and add in their open ID counts also */
- for(u = 0; u < f->mtab.nmounts; u++) {
- /* Increment the open object count if the mount point group has an open ID */
- if(H5G_get_shared_count(f->mtab.child[u].group) > 1)
- *nopen_objs += 1;
-
- H5F_mount_count_ids_recurse(f->mtab.child[u].file, nopen_files, nopen_objs);
+ for(u = 0; u < f->shared->mtab.nmounts; u++) {
+ /* Only recurse on children mounted to this top level file structure */
+ if(f->shared->mtab.child[u].file->parent == f) {
+ /* Increment the open object count if the mount point group has an open ID */
+ if(H5G_get_shared_count(f->shared->mtab.child[u].group) > 1)
+ *nopen_objs += 1;
+
+ H5F_mount_count_ids_recurse(f->shared->mtab.child[u].file, nopen_files, nopen_objs);
+ }
} /* end for */
FUNC_LEAVE_NOAPI_VOID
@@ -623,8 +617,8 @@ H5F_mount_count_ids(H5F_t *f, unsigned *nopen_files, unsigned *nopen_objs)
HDassert(nopen_objs);
/* Find the top file in the mounting hierarchy */
- while(f->mtab.parent)
- f = f->mtab.parent;
+ while(f->parent)
+ f = f->parent;
/* Count open IDs in the hierarchy */
H5F_mount_count_ids_recurse(f, nopen_files, nopen_objs);
diff --git a/src/H5Fmpi.c b/src/H5Fmpi.c
new file mode 100644
index 0000000..c90ad7c
--- /dev/null
+++ b/src/H5Fmpi.c
@@ -0,0 +1,181 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5Fmpi.c
+ * Jan 10 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: MPI-related routines.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5F_PACKAGE /*suppress error about including H5Fpkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fpkg.h" /* File access */
+#include "H5FDmpi.h" /* MPI-based file drivers */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+#ifdef H5_HAVE_PARALLEL
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_mpi_get_rank
+ *
+ * Purpose: Retrieves the rank of an MPI process.
+ *
+ * Return: Success: The rank (non-negative)
+ *
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Friday, January 30, 2004
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+H5F_mpi_get_rank(const H5F_t *f)
+{
+ int ret_value;
+
+ FUNC_ENTER_NOAPI(H5F_mpi_get_rank, FAIL)
+
+ assert(f && f->shared);
+
+ /* Dispatch to driver */
+ if ((ret_value=H5FD_mpi_get_rank(f->shared->lf)) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "driver get_rank request failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_mpi_get_rank() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_mpi_get_comm
+ *
+ * Purpose: Retrieves the file's communicator
+ *
+ * Return: Success: The communicator (non-negative)
+ *
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Friday, January 30, 2004
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+MPI_Comm
+H5F_mpi_get_comm(const H5F_t *f)
+{
+ MPI_Comm ret_value;
+
+ FUNC_ENTER_NOAPI(H5F_mpi_get_comm, MPI_COMM_NULL)
+
+ assert(f && f->shared);
+
+ /* Dispatch to driver */
+ if ((ret_value=H5FD_mpi_get_comm(f->shared->lf))==MPI_COMM_NULL)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTGET, MPI_COMM_NULL, "driver get_comm request failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_mpi_get_comm() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_mpi_get_size
+ *
+ * Purpose: Retrieves the size of an MPI process.
+ *
+ * Return: Success: The size (positive)
+ *
+ * Failure: Negative
+ *
+ * Programmer: John Mainzer
+ * Friday, May 6, 2005
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+H5F_mpi_get_size(const H5F_t *f)
+{
+ int ret_value;
+
+ FUNC_ENTER_NOAPI(H5F_mpi_get_size, FAIL)
+
+ assert(f && f->shared);
+
+ /* Dispatch to driver */
+ if ((ret_value=H5FD_mpi_get_size(f->shared->lf)) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "driver get_size request failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_mpi_get_size() */
+#endif /* H5_HAVE_PARALLEL */
+
diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h
index a104e61..cc74a80 100644
--- a/src/H5Fpkg.h
+++ b/src/H5Fpkg.h
@@ -38,6 +38,7 @@
#include "H5private.h" /* Generic Functions */
#include "H5FLprivate.h" /* Free Lists */
#include "H5FOprivate.h" /* File objects */
+#include "H5FSprivate.h" /* File free space */
#include "H5Gprivate.h" /* Groups */
#include "H5Oprivate.h" /* Object header messages */
#include "H5RCprivate.h" /* Reference counted object functions */
@@ -62,6 +63,51 @@
/* Mask for removing private file access flags */
#define H5F_ACC_PUBLIC_FLAGS 0x00ffu
+/* Free space section+aggregator merge flags */
+#define H5F_FS_MERGE_METADATA 0x01 /* Section can merge with metadata aggregator */
+#define H5F_FS_MERGE_RAWDATA 0x02 /* Section can merge with small 'raw' data aggregator */
+
+/* Structure for metadata & "small [raw] data" block aggregation fields */
+struct H5F_blk_aggr_t {
+ unsigned long feature_flag; /* Feature flag type */
+ hsize_t alloc_size; /* Size for allocating new blocks */
+ hsize_t tot_size; /* Total amount of bytes aggregated into block */
+ hsize_t size; /* Current size of block left */
+ haddr_t addr; /* Location of block left */
+};
+
+/* Structure for metadata accumulator fields */
+typedef struct H5F_meta_accum_t {
+ unsigned char *buf; /* Buffer to hold the accumulated metadata */
+ haddr_t loc; /* File location (offset) of the accumulated metadata */
+ size_t size; /* Size of the accumulated metadata buffer used (in bytes) */
+ size_t alloc_size; /* Size of the accumulated metadata buffer allocated (in bytes) */
+ hbool_t dirty; /* Flag to indicate that the accumulated metadata is dirty */
+} H5F_meta_accum_t;
+
+/* Enum for free space manager state */
+typedef enum H5F_fs_state_t {
+ H5F_FS_STATE_CLOSED, /* Free space manager is closed */
+ H5F_FS_STATE_OPEN, /* Free space manager has been opened */
+ H5F_FS_STATE_DELETING /* Free space manager is being deleted */
+} H5F_fs_state_t;
+
+/* A record of the mount table */
+typedef struct H5F_mount_t {
+ struct H5G_t *group; /* Mount point group held open */
+ struct H5F_t *file; /* File mounted at that point */
+} H5F_mount_t;
+
+/*
+ * The mount table describes what files are attached to (mounted on) the file
+ * to which this table belongs.
+ */
+typedef struct H5F_mtab_t {
+ unsigned nmounts;/* Number of children which are mounted */
+ unsigned nalloc; /* Number of mount slots allocated */
+ H5F_mount_t *child; /* An array of mount records */
+} H5F_mtab_t;
+
/*
* Define the structure to store the file information for HDF5 files. One of
* these structures is allocated per file, not per H5Fopen(). That is, set of
@@ -74,20 +120,22 @@ typedef struct H5F_file_t {
unsigned nrefs; /* Ref count for times file is opened */
uint8_t status_flags; /* File status flags */
unsigned flags; /* Access Permissions for file */
+ H5F_mtab_t mtab; /* File mount table */
/* Cached values from FCPL/superblock */
unsigned sym_leaf_k; /* Size of leaves in symbol tables */
unsigned btree_k[H5B_NUM_BTREE_ID]; /* B-tree key values for each type */
size_t sizeof_addr; /* Size of addresses in file */
size_t sizeof_size; /* Size of offsets in file */
- haddr_t super_addr; /* Absolute address of super block */
haddr_t base_addr; /* Absolute base address for rel.addrs. */
+ /* (superblock for file is at this offset) */
haddr_t extension_addr; /* Relative address of superblock extension */
haddr_t sohm_addr; /* Relative address of shared object header message table */
unsigned sohm_vers; /* Version of shared message table on disk */
unsigned sohm_nindexes; /* Number of shared messages indexes in the table */
haddr_t driver_addr; /* File driver information block address*/
- hbool_t fam_to_sec2; /* Is h5repart changing driver from family to sec2 */
+ unsigned long feature_flags; /* VFL Driver feature Flags */
+ haddr_t maxaddr; /* Maximum address for file */
H5AC_t *cache; /* The object cache */
H5AC_cache_config_t
@@ -97,7 +145,7 @@ typedef struct H5F_file_t {
/* not change thereafter. */
hid_t fcpl_id; /* File creation property list ID */
H5F_close_degree_t fc_degree; /* File close behavior degree */
- size_t rdcc_nelmts; /* Size of raw data chunk cache (elmts) */
+ size_t rdcc_nslots; /* Size of raw data chunk cache (slots) */
size_t rdcc_nbytes; /* Size of raw data chunk cache (bytes) */
double rdcc_w0; /* Preempt read chunks first? [0.0..1.0]*/
size_t sieve_buf_size; /* Size of the data sieve buffer allocated (in bytes) */
@@ -105,30 +153,28 @@ typedef struct H5F_file_t {
hsize_t alignment; /* Alignment */
unsigned gc_ref; /* Garbage-collect references? */
hbool_t latest_format; /* Always use the latest format? */
- hbool_t store_msg_crt_idx; /* Store creation index for object header messages? */
+ hbool_t store_msg_crt_idx; /* Store creation index for object header messages? */
+ hbool_t fam_to_sec2; /* Is h5repart changing driver from family to sec2? */
int ncwfs; /* Num entries on cwfs list */
struct H5HG_heap_t **cwfs; /* Global heap cache */
struct H5G_t *root_grp; /* Open root group */
H5FO_t *open_objs; /* Open objects in file */
H5RC_t *grp_btree_shared; /* Ref-counted group B-tree node info */
-} H5F_file_t;
-/* A record of the mount table */
-typedef struct H5F_mount_t {
- struct H5G_t *group; /* Mount point group held open */
- struct H5F_t *file; /* File mounted at that point */
-} H5F_mount_t;
-
-/*
- * The mount table describes what files are attached to (mounted on) the file
- * to which this table belongs.
- */
-typedef struct H5F_mtab_t {
- struct H5F_t *parent;/* Parent file */
- unsigned nmounts;/* Number of children which are mounted */
- unsigned nalloc; /* Number of mount slots allocated */
- H5F_mount_t *child; /* An array of mount records */
-} H5F_mtab_t;
+ /* File space allocation information */
+ unsigned fs_aggr_merge[H5FD_MEM_NTYPES]; /* Flags for whether free space can merge with aggregator(s) */
+ H5F_fs_state_t fs_state[H5FD_MEM_NTYPES]; /* State of free space manager for each type */
+ haddr_t fs_addr[H5FD_MEM_NTYPES]; /* Address of free space manager info for each type */
+ H5FS_t *fs_man[H5FD_MEM_NTYPES]; /* Free space manager for each file space type */
+ H5FD_mem_t fs_type_map[H5FD_MEM_NTYPES]; /* Mapping of "real" file space type into tracked type */
+ H5F_blk_aggr_t meta_aggr; /* Metadata aggregation info */
+ /* (if aggregating metadata allocations) */
+ H5F_blk_aggr_t sdata_aggr; /* "Small data" aggregation info */
+ /* (if aggregating "small data" allocations) */
+
+ /* Metadata accumulator information */
+ H5F_meta_accum_t accum; /* Metadata accumulator info */
+} H5F_file_t;
/*
* This is the top-level file descriptor. One of these structures is
@@ -141,12 +187,14 @@ typedef struct H5F_mtab_t {
struct H5F_t {
unsigned intent; /* The flags passed to H5F_open()*/
char *name; /* Name used to open file */
+ char *extpath; /* Path for searching target external link file */
H5F_file_t *shared; /* The shared file info */
unsigned nopen_objs; /* Number of open object headers*/
H5FO_t *obj_count; /* # of time each object is opened through top file structure */
hid_t file_id; /* ID of this file */
hbool_t closing; /* File is in the process of being closed */
- H5F_mtab_t mtab; /* File mount table */
+ struct H5F_t *parent; /* Parent file that this file is mounted to */
+ unsigned nmounts; /* Number of children mounted to this file */
};
/*****************************/
@@ -179,6 +227,15 @@ H5_DLL herr_t H5F_super_write(H5F_t *f, hid_t dxpl_id);
H5_DLL herr_t H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc);
H5_DLL herr_t H5F_super_ext_size(H5F_t *f, hid_t dxpl_id, hsize_t *super_ext_info);
+/* Metadata accumulator routines */
+H5_DLL htri_t H5F_accum_read(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type,
+ haddr_t addr, size_t size, void *buf);
+H5_DLL htri_t H5F_accum_write(const H5F_t *f, hid_t dxpl_id, H5FD_mem_t type,
+ haddr_t addr, size_t size, const void *buf);
+H5_DLL herr_t H5F_accum_free(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type,
+ haddr_t addr, hsize_t size);
+H5_DLL herr_t H5F_accum_flush(H5F_t *f, hid_t dxpl_id);
+H5_DLL herr_t H5F_accum_reset(H5F_t *f);
/* Shared file list related routines */
H5_DLL herr_t H5F_sfile_add(H5F_file_t *shared);
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
index f9a1f57..fb28c4e 100644
--- a/src/H5Fprivate.h
+++ b/src/H5Fprivate.h
@@ -35,6 +35,9 @@
/* Main file structure */
typedef struct H5F_t H5F_t;
+/* Block aggregation structure */
+typedef struct H5F_blk_aggr_t H5F_blk_aggr_t;
+
/*===----------------------------------------------------------------------===
* Flush Flags
*===----------------------------------------------------------------------===
@@ -214,7 +217,7 @@ typedef struct H5F_t H5F_t;
HADDR_UNDEF==(X)+(haddr_t)(Z) || \
(X)+(haddr_t)(Z)<(X))
#define H5F_addr_hash(X,M) ((unsigned)((X)%(M)))
-#define H5F_addr_defined(X) (X!=HADDR_UNDEF)
+#define H5F_addr_defined(X) ((X)!=HADDR_UNDEF)
/* The H5F_addr_eq() macro guarantees that Y is not HADDR_UNDEF by making
* certain that X is not HADDR_UNDEF and then checking that X equals Y
*/
@@ -233,58 +236,55 @@ typedef struct H5F_t H5F_t;
#define H5F_addr_ge(X,Y) ((X)!=HADDR_UNDEF && \
(Y)!=HADDR_UNDEF && \
(X)>=(Y))
-#define H5F_addr_cmp(X,Y) (H5F_addr_eq(X,Y)?0: \
- (H5F_addr_lt(X, Y)?-1:1))
+#define H5F_addr_cmp(X,Y) (H5F_addr_eq((X), (Y)) ? 0 : \
+ (H5F_addr_lt((X), (Y)) ? -1 : 1))
#define H5F_addr_pow2(N) ((haddr_t)1<<(N))
-#define H5F_addr_overlap(O1,L1,O2,L2) ((O1<O2 && (O1+L1)>O2) || \
- (O1>=O2 && O1<(O2+L2)))
+#define H5F_addr_overlap(O1,L1,O2,L2) (((O1) < (O2) && ((O1) + (L1)) > (O2)) || \
+ ((O1) >= (O2) && (O1) < ((O2) + (L2))))
/* If the module using this macro is allowed access to the private variables, access them directly */
#ifdef H5F_PACKAGE
-/* The FCPL itself */
+#define H5F_INTENT(F) ((F)->intent)
#define H5F_FCPL(F) ((F)->shared->fcpl_id)
-/* size of size_t and off_t as they exist on disk */
#define H5F_SIZEOF_ADDR(F) ((F)->shared->sizeof_addr)
#define H5F_SIZEOF_SIZE(F) ((F)->shared->sizeof_size)
-/* Size of symbol table leafs */
#define H5F_SYM_LEAF_K(F) ((F)->shared->sym_leaf_k)
-/* B-tree key value size */
#define H5F_KVALUE(F,T) ((F)->shared->btree_k[(T)->id])
-/* Raw data cache values */
-#define H5F_RDCC_NELMTS(F) ((F)->shared->rdcc_nelmts)
+#define H5F_RDCC_NSLOTS(F) ((F)->shared->rdcc_nslots)
#define H5F_RDCC_NBYTES(F) ((F)->shared->rdcc_nbytes)
#define H5F_RDCC_W0(F) ((F)->shared->rdcc_w0)
-/* Check for file driver feature enabled */
-#define H5F_HAS_FEATURE(F,FL) ((F)->shared->lf->feature_flags & (FL))
-/* B-tree node raw page */
-#define H5F_GRP_BTREE_SHARED(F) ((F)->shared->grp_btree_shared)
-/* Base address of file */
#define H5F_BASE_ADDR(F) ((F)->shared->base_addr)
-/* Sieve buffer size for datasets */
+#define H5F_GRP_BTREE_SHARED(F) ((F)->shared->grp_btree_shared)
#define H5F_SIEVE_BUF_SIZE(F) ((F)->shared->sieve_buf_size)
#define H5F_GC_REF(F) ((F)->shared->gc_ref)
#define H5F_USE_LATEST_FORMAT(F) ((F)->shared->latest_format)
-#define H5F_INTENT(F) ((F)->intent)
+#define H5F_EXTPATH(F) ((F)->extpath)
#define H5F_GET_FC_DEGREE(F) ((F)->shared->fc_degree)
#define H5F_STORE_MSG_CRT_IDX(F) ((F)->shared->store_msg_crt_idx)
+#define H5F_HAS_FEATURE(F,FL) ((F)->shared->lf->feature_flags & (FL))
+#define H5F_DRIVER_ID(F) ((F)->shared->lf->driver_id)
+#define H5F_GET_FILENO(F,FILENUM) ((FILENUM) = (F)->shared->lf->fileno)
#else /* H5F_PACKAGE */
+#define H5F_INTENT(F) (H5F_get_intent(F))
#define H5F_FCPL(F) (H5F_get_fcpl(F))
#define H5F_SIZEOF_ADDR(F) (H5F_sizeof_addr(F))
#define H5F_SIZEOF_SIZE(F) (H5F_sizeof_size(F))
#define H5F_SYM_LEAF_K(F) (H5F_sym_leaf_k(F))
#define H5F_KVALUE(F,T) (H5F_Kvalue(F,T))
-#define H5F_RDCC_NELMTS(F) (H5F_rdcc_nelmts(F))
+#define H5F_RDCC_NSLOTS(F) (H5F_rdcc_nslots(F))
#define H5F_RDCC_NBYTES(F) (H5F_rdcc_nbytes(F))
#define H5F_RDCC_W0(F) (H5F_rdcc_w0(F))
-#define H5F_HAS_FEATURE(F,FL) (H5F_has_feature(F,FL))
-#define H5F_GRP_BTREE_SHARED(F) (H5F_grp_btree_shared(F))
#define H5F_BASE_ADDR(F) (H5F_get_base_addr(F))
+#define H5F_GRP_BTREE_SHARED(F) (H5F_grp_btree_shared(F))
#define H5F_SIEVE_BUF_SIZE(F) (H5F_sieve_buf_size(F))
#define H5F_GC_REF(F) (H5F_gc_ref(F))
#define H5F_USE_LATEST_FORMAT(F) (H5F_use_latest_format(F))
-#define H5F_INTENT(F) (H5F_get_intent(F))
+#define H5F_EXTPATH(F) (H5F_get_extpath(F))
#define H5F_GET_FC_DEGREE(F) (H5F_get_fc_degree(F))
-#define H5F_STORE_MSG_CRT_IDX(F) (H5F_store_msg_crt_idx(F))
+#define H5F_STORE_MSG_CRT_IDX(F) (H5F_store_msg_crt_idx(F))
+#define H5F_HAS_FEATURE(F,FL) (H5F_has_feature(F,FL))
+#define H5F_DRIVER_ID(F) (H5F_get_driver_id(F))
+#define H5F_GET_FILENO(F,FILENUM) (H5F_get_fileno((F), &(FILENUM)))
#endif /* H5F_PACKAGE */
@@ -305,12 +305,14 @@ typedef struct H5F_t H5F_t;
case 4: UINT32ENCODE(p,l); break; \
case 8: UINT64ENCODE(p,l); break; \
case 2: UINT16ENCODE(p,l); break; \
+ default: HDassert("bad sizeof size" && 0); \
}
#define H5F_DECODE_LENGTH(f,p,l) switch(H5F_SIZEOF_SIZE(f)) { \
case 4: UINT32DECODE(p,l); break; \
case 8: UINT64DECODE(p,l); break; \
case 2: UINT16DECODE(p,l); break; \
+ default: HDassert("bad sizeof size" && 0); \
}
/*
@@ -356,7 +358,7 @@ typedef struct H5F_t H5F_t;
/* ========= File Access properties ============ */
#define H5F_ACS_META_CACHE_INIT_CONFIG_NAME "mdc_initCacheCfg" /* Initial metadata cache resize configuration */
-#define H5F_ACS_DATA_CACHE_ELMT_SIZE_NAME "rdcc_nelmts" /* Size of raw data chunk cache(elements) */
+#define H5F_ACS_DATA_CACHE_NUM_SLOTS_NAME "rdcc_nslots" /* Size of raw data chunk cache(slots) */
#define H5F_ACS_DATA_CACHE_BYTE_SIZE_NAME "rdcc_nbytes" /* Size of raw data chunk cache(bytes) */
#define H5F_ACS_PREEMPT_READ_CHUNKS_NAME "rdcc_w0" /* Preemption read chunks first */
#define H5F_ACS_ALIGN_THRHD_NAME "threshold" /* Threshold for alignment */
@@ -395,13 +397,60 @@ typedef struct H5F_t H5F_t;
/* B-tree internal 'K' values */
#define HDF5_BTREE_SNODE_IK_DEF 16
-#define HDF5_BTREE_ISTORE_IK_DEF 32 /* Note! this value is assumed
+#define HDF5_BTREE_CHUNK_IK_DEF 32 /* Note! this value is assumed
to be 32 for version 0
of the superblock and
if it is changed, the code
must compensate. -QAK
*/
+/* Macros to define signatures of all objects in the file */
+
+/* Size of signature information (on disk) */
+/* (all on-disk signatures should be this length) */
+#define H5_SIZEOF_MAGIC 4
+
+/* v1 B-tree node signature */
+#define H5B_MAGIC "TREE"
+
+/* v2 B-tree signatures */
+#define H5B2_HDR_MAGIC "BTHD" /* Header */
+#define H5B2_INT_MAGIC "BTIN" /* Internal node */
+#define H5B2_LEAF_MAGIC "BTLF" /* Leaf node */
+
+/* Extensible array signatures */
+#define H5EA_HDR_MAGIC "EAHD" /* Header */
+#define H5EA_IBLOCK_MAGIC "EAIB" /* Index block */
+#define H5EA_SBLOCK_MAGIC "EASB" /* Super block */
+#define H5EA_DBLOCK_MAGIC "EADB" /* Data block */
+
+/* Free space signatures */
+#define H5FS_HDR_MAGIC "FSHD" /* Header */
+#define H5FS_SINFO_MAGIC "FSSE" /* Serialized sections */
+
+/* Symbol table node signature */
+#define H5G_NODE_MAGIC "SNOD"
+
+/* Fractal heap signatures */
+#define H5HF_HDR_MAGIC "FRHP" /* Header */
+#define H5HF_IBLOCK_MAGIC "FHIB" /* Indirect block */
+#define H5HF_DBLOCK_MAGIC "FHDB" /* Direct block */
+
+/* Global heap signature */
+#define H5HG_MAGIC "GCOL"
+
+/* Local heap signature */
+#define H5HL_MAGIC "HEAP"
+
+/* Object header signatures */
+#define H5O_HDR_MAGIC "OHDR" /* Header */
+#define H5O_CHK_MAGIC "OCHK" /* Continuation chunk */
+
+/* Shared Message signatures */
+#define H5SM_TABLE_MAGIC "SMTB" /* Shared Message Table */
+#define H5SM_LIST_MAGIC "SMLI" /* Shared Message List */
+
+
/* Forward declarations for prototype arguments */
struct H5B_class_t;
struct H5RC_t;
@@ -410,39 +459,27 @@ struct H5RC_t;
H5_DLL H5F_t *H5F_open(const char *name, unsigned flags, hid_t fcpl_id,
hid_t fapl_id, hid_t dxpl_id);
H5_DLL herr_t H5F_try_close(H5F_t *f);
-
-/* Functions than retrieve values from the file struct */
-H5_DLL hid_t H5F_get_driver_id(const H5F_t *f);
-H5_DLL hid_t H5F_get_access_plist(H5F_t *f);
-H5_DLL unsigned H5F_get_intent(const H5F_t *f);
-H5_DLL herr_t H5F_get_fileno(const H5F_t *f, unsigned long *filenum);
-H5_DLL hid_t H5F_get_id(H5F_t *file);
-H5_DLL unsigned H5F_get_obj_count(const H5F_t *f, unsigned types);
-H5_DLL unsigned H5F_get_obj_ids(const H5F_t *f, unsigned types, int max_objs, hid_t *obj_id_list);
-H5_DLL haddr_t H5F_get_base_addr(const H5F_t *f);
-H5_DLL haddr_t H5F_get_eoa(const H5F_t *f);
-#ifdef H5_HAVE_PARALLEL
-H5_DLL int H5F_mpi_get_rank(const H5F_t *f);
-H5_DLL MPI_Comm H5F_mpi_get_comm(const H5F_t *f);
-H5_DLL int H5F_mpi_get_size(const H5F_t *f);
-#endif /* H5_HAVE_PARALLEL */
H5_DLL unsigned H5F_incr_nopen_objs(H5F_t *f);
H5_DLL unsigned H5F_decr_nopen_objs(H5F_t *f);
-/* Functions than check file mounting information */
-H5_DLL hbool_t H5F_is_mount(const H5F_t *file);
-H5_DLL hbool_t H5F_has_mount(const H5F_t *file);
+/* Functions than retrieve values from the file struct */
+H5_DLL unsigned H5F_get_intent(const H5F_t *f);
+H5_DLL hid_t H5F_get_access_plist(H5F_t *f, hbool_t app_ref);
+H5_DLL char *H5F_get_extpath(const H5F_t *f);
+H5_DLL hid_t H5F_get_id(H5F_t *file, hbool_t app_ref);
+H5_DLL size_t H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref);
+H5_DLL size_t H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *obj_id_list, hbool_t app_ref);
-/* Functions than retrieve values set from the FCPL */
+/* Functions than retrieve values set/cached from the superblock/FCPL */
H5_DLL hid_t H5F_get_fcpl(const H5F_t *f);
H5_DLL size_t H5F_sizeof_addr(const H5F_t *f);
H5_DLL size_t H5F_sizeof_size(const H5F_t *f);
H5_DLL unsigned H5F_sym_leaf_k(const H5F_t *f);
H5_DLL unsigned H5F_Kvalue(const H5F_t *f, const struct H5B_class_t *type);
-H5_DLL hbool_t H5F_has_feature(const H5F_t *f, unsigned feature);
H5_DLL size_t H5F_rdcc_nbytes(const H5F_t *f);
-H5_DLL size_t H5F_rdcc_nelmts(const H5F_t *f);
+H5_DLL size_t H5F_rdcc_nslots(const H5F_t *f);
H5_DLL double H5F_rdcc_w0(const H5F_t *f);
+H5_DLL haddr_t H5F_get_base_addr(const H5F_t *f);
H5_DLL struct H5RC_t *H5F_grp_btree_shared(const H5F_t *f);
H5_DLL size_t H5F_sieve_buf_size(const H5F_t *f);
H5_DLL unsigned H5F_gc_ref(const H5F_t *f);
@@ -450,6 +487,16 @@ H5_DLL hbool_t H5F_use_latest_format(const H5F_t *f);
H5_DLL H5F_close_degree_t H5F_get_fc_degree(const H5F_t *f);
H5_DLL hbool_t H5F_store_msg_crt_idx(const H5F_t *f);
+/* Functions that retrieve values from VFD layer */
+H5_DLL hbool_t H5F_has_feature(const H5F_t *f, unsigned feature);
+H5_DLL hid_t H5F_get_driver_id(const H5F_t *f);
+H5_DLL herr_t H5F_get_fileno(const H5F_t *f, unsigned long *filenum);
+H5_DLL haddr_t H5F_get_eoa(const H5F_t *f, H5FD_mem_t type);
+
+/* Functions than check file mounting information */
+H5_DLL hbool_t H5F_is_mount(const H5F_t *file);
+H5_DLL hbool_t H5F_has_mount(const H5F_t *file);
+
/* Functions that operate on blocks of bytes wrt super block */
H5_DLL herr_t H5F_block_read(const H5F_t *f, H5FD_mem_t type, haddr_t addr,
size_t size, hid_t dxpl_id, void *buf/*out*/);
@@ -471,6 +518,13 @@ H5_DLL herr_t H5F_sfile_assert_num(unsigned n);
H5_DLL H5F_t *H5F_fake_alloc(size_t sizeof_size);
H5_DLL herr_t H5F_fake_free(H5F_t *f);
+/* Parallel I/O (i.e. MPI) related routines */
+#ifdef H5_HAVE_PARALLEL
+H5_DLL int H5F_mpi_get_rank(const H5F_t *f);
+H5_DLL MPI_Comm H5F_mpi_get_comm(const H5F_t *f);
+H5_DLL int H5F_mpi_get_size(const H5F_t *f);
+#endif /* H5_HAVE_PARALLEL */
+
/* Debugging functions */
H5_DLL herr_t H5F_debug(H5F_t *f, FILE * stream, int indent, int fwidth);
diff --git a/src/H5Fpublic.h b/src/H5Fpublic.h
index 1d98330..312d92e 100644
--- a/src/H5Fpublic.h
+++ b/src/H5Fpublic.h
@@ -107,6 +107,12 @@ typedef struct H5F_info_t {
} sohm;
} H5F_info_t;
+/* Library's file format versions */
+typedef enum H5F_libver_t {
+ H5F_LIBVER_EARLIEST, /* Use the earliest possible format for storing objects */
+ H5F_LIBVER_LATEST /* Use the latest possible format available for storing objects*/
+} H5F_libver_t;
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -123,8 +129,8 @@ H5_DLL herr_t H5Fclose(hid_t file_id);
H5_DLL hid_t H5Fget_create_plist(hid_t file_id);
H5_DLL hid_t H5Fget_access_plist(hid_t file_id);
H5_DLL herr_t H5Fget_intent(hid_t file_id, unsigned * intent);
-H5_DLL int H5Fget_obj_count(hid_t file_id, unsigned types);
-H5_DLL int H5Fget_obj_ids(hid_t file_id, unsigned types, int max_objs, hid_t *obj_id_list);
+H5_DLL ssize_t H5Fget_obj_count(hid_t file_id, unsigned types);
+H5_DLL ssize_t H5Fget_obj_ids(hid_t file_id, unsigned types, size_t max_objs, hid_t *obj_id_list);
H5_DLL herr_t H5Fget_vfd_handle(hid_t file_id, hid_t fapl, void **file_handle);
H5_DLL herr_t H5Fmount(hid_t loc, const char *name, hid_t child, hid_t plist);
H5_DLL herr_t H5Funmount(hid_t loc, const char *name);
diff --git a/src/H5Fquery.c b/src/H5Fquery.c
new file mode 100644
index 0000000..550a507
--- /dev/null
+++ b/src/H5Fquery.c
@@ -0,0 +1,663 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5Fquery.c
+ * Jan 10 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: File structure query routines.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5F_PACKAGE /*suppress error about including H5Fpkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fpkg.h" /* File access */
+#include "H5FDprivate.h" /* File drivers */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_get_intent
+ *
+ * Purpose: Quick and dirty routine to retrieve the file's 'intent' flags
+ * (Mainly added to stop non-file routines from poking about in the
+ * H5F_t data structure)
+ *
+ * Return: 'intent' on success/abort on failure (shouldn't fail)
+ *
+ * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
+ * September 29, 2000
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned
+H5F_get_intent(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_intent)
+
+ HDassert(f);
+
+ FUNC_LEAVE_NOAPI(f->intent)
+} /* end H5F_get_intent() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_get_extpath
+ *
+ * Purpose: Retrieve the file's 'extpath' flags
+ * This is used by H5L_extern_traverse() to retrieve the main file's location
+ * when searching the target file.
+ *
+ * Return: 'extpath' on success/abort on failure (shouldn't fail)
+ *
+ * Programmer: Vailin Choi, April 2, 2008
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+char *
+H5F_get_extpath(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_extpath)
+
+ HDassert(f);
+
+ FUNC_LEAVE_NOAPI(f->extpath)
+} /* end H5F_get_extpath() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_get_fcpl
+ *
+ * Purpose: Retrieve the value of a file's FCPL.
+ *
+ * Return: Success: The FCPL for the file.
+ *
+ * Failure: ? (should not happen)
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 25 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5F_get_fcpl(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_fcpl)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->fcpl_id)
+} /* end H5F_get_fcpl() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_sizeof_addr
+ *
+ * Purpose: Quick and dirty routine to retrieve the size of the file's size_t
+ * (Mainly added to stop non-file routines from poking about in the
+ * H5F_t data structure)
+ *
+ * Return: 'sizeof_addr' on success/abort on failure (shouldn't fail)
+ *
+ * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
+ * September 29, 2000
+ *
+ *-------------------------------------------------------------------------
+ */
+size_t
+H5F_sizeof_addr(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sizeof_addr)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->sizeof_addr)
+} /* end H5F_sizeof_addr() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_sizeof_size
+ *
+ * Purpose: Quick and dirty routine to retrieve the size of the file's off_t
+ * (Mainly added to stop non-file routines from poking about in the
+ * H5F_t data structure)
+ *
+ * Return: 'sizeof_size' on success/abort on failure (shouldn't fail)
+ *
+ * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
+ * September 29, 2000
+ *
+ *-------------------------------------------------------------------------
+ */
+size_t
+H5F_sizeof_size(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sizeof_size)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->sizeof_size)
+} /* H5F_sizeof_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_sym_leaf_k
+ *
+ * Purpose: Replaced a macro to retrieve the symbol table leaf size,
+ * now that the generic properties are being used to store
+ * the values.
+ *
+ * Return: Success: Non-negative, and the symbol table leaf size is
+ * returned.
+ *
+ * Failure: Negative (should not happen)
+ *
+ * Programmer: Raymond Lu
+ * slu@ncsa.uiuc.edu
+ * Oct 14 2001
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned
+H5F_sym_leaf_k(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sym_leaf_k)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->sym_leaf_k)
+} /* end H5F_sym_leaf_k() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_Kvalue
+ *
+ * Purpose: Replaced a macro to retrieve a B-tree key value for a certain
+ * type, now that the generic properties are being used to store
+ * the B-tree values.
+ *
+ * Return: Success: Non-negative, and the B-tree key value is
+ * returned.
+ *
+ * Failure: Negative (should not happen)
+ *
+ * Programmer: Raymond Lu
+ * slu@ncsa.uiuc.edu
+ * Oct 14 2001
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned
+H5F_Kvalue(const H5F_t *f, const H5B_class_t *type)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_Kvalue)
+
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(type);
+
+ FUNC_LEAVE_NOAPI(f->shared->btree_k[type->id])
+} /* end H5F_Kvalue() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_rdcc_nslots
+ *
+ * Purpose: Replaced a macro to retrieve the raw data cache number of slots,
+ * now that the generic properties are being used to store
+ * the values.
+ *
+ * Return: Success: Non-negative, and the raw data cache number of
+ * of slots is returned.
+ *
+ * Failure: Negative (should not happen)
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Jun 1 2004
+ *
+ *-------------------------------------------------------------------------
+ */
+size_t
+H5F_rdcc_nslots(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_rdcc_nslots)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->rdcc_nslots)
+} /* end H5F_rdcc_nelmts() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_rdcc_nbytes
+ *
+ * Purpose: Replaced a macro to retrieve the raw data cache number of bytes,
+ * now that the generic properties are being used to store
+ * the values.
+ *
+ * Return: Success: Non-negative, and the raw data cache number of
+ * of bytes is returned.
+ *
+ * Failure: Negative (should not happen)
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Jun 1 2004
+ *
+ *-------------------------------------------------------------------------
+ */
+size_t
+H5F_rdcc_nbytes(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_rdcc_nbytes)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->rdcc_nbytes)
+} /* end H5F_rdcc_nbytes() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_rdcc_w0
+ *
+ * Purpose: Replaced a macro to retrieve the raw data cache 'w0' value
+ * now that the generic properties are being used to store
+ * the values.
+ *
+ * Return: Success: Non-negative, and the raw data cache 'w0' value
+ * is returned.
+ *
+ * Failure: Negative (should not happen)
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Jun 2 2004
+ *
+ *-------------------------------------------------------------------------
+ */
+double
+H5F_rdcc_w0(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_rdcc_w0)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->rdcc_w0)
+} /* end H5F_rdcc_w0() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_get_base_addr
+ *
+ * Purpose: Quick and dirty routine to retrieve the file's 'base_addr' value
+ * (Mainly added to stop non-file routines from poking about in the
+ * H5F_t data structure)
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Raymond Lu <slu@ncsa.uiuc.edu>
+ * December 20, 2002
+ *
+ *-------------------------------------------------------------------------
+ */
+haddr_t
+H5F_get_base_addr(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_base_addr)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->base_addr)
+} /* end H5F_get_base_addr() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_grp_btree_shared
+ *
+ * Purpose: Replaced a macro to retrieve the shared B-tree node info
+ * now that the generic properties are being used to store
+ * the values.
+ *
+ * Return: Success: Non-void, and the shared B-tree node info
+ * is returned.
+ *
+ * Failure: void (should not happen)
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Jul 5 2004
+ *
+ *-------------------------------------------------------------------------
+ */
+H5RC_t *
+H5F_grp_btree_shared(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_grp_btree_shared)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->grp_btree_shared)
+} /* end H5F_grp_btree_shared() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_sieve_buf_size
+ *
+ * Purpose: Replaced a macro to retrieve the dataset sieve buffer size
+ * now that the generic properties are being used to store
+ * the values.
+ *
+ * Return: Success: Non-void, and the dataset sieve buffer size
+ * is returned.
+ *
+ * Failure: void (should not happen)
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Jul 8 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+size_t
+H5F_sieve_buf_size(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_sieve_buf_size)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->sieve_buf_size)
+} /* end H5F_sieve_buf_size() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_gc_ref
+ *
+ * Purpose: Replaced a macro to retrieve the "garbage collect
+ * references flag" now that the generic properties are being used
+ * to store the values.
+ *
+ * Return: Success: The "garbage collect references flag"
+ * is returned.
+ *
+ * Failure: (should not happen)
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Jul 8 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned
+H5F_gc_ref(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_gc_ref)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->gc_ref)
+} /* end H5F_gc_ref() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_use_latest_format
+ *
+ * Purpose: Retrieve the 'use the latest version of the format' flag for
+ * the file.
+ *
+ * Return: Success: Non-negative, the 'use the latest format' flag
+ *
+ * Failure: (can't happen)
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Oct 2 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+hbool_t
+H5F_use_latest_format(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_use_latest_format)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->latest_format)
+} /* end H5F_use_latest_format() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_get_fc_degree
+ *
+ * Purpose: Retrieve the 'file close degree' for the file.
+ *
+ * Return: Success: Non-negative, the 'file close degree'
+ *
+ * Failure: (can't happen)
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Mar 5 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+H5F_close_degree_t
+H5F_get_fc_degree(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_fc_degree)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->fc_degree)
+} /* end H5F_get_fc_degree() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_store_msg_crt_idx
+ *
+ * Purpose: Retrieve the 'store message creation index' flag for the file.
+ *
+ * Return: Success: Non-negative, the 'store message creation index' flag
+ *
+ * Failure: (can't happen)
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Mar 6 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+hbool_t
+H5F_store_msg_crt_idx(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_store_msg_crt_idx)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->store_msg_crt_idx)
+} /* end H5F_store_msg_crt_idx() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_has_feature
+ *
+ * Purpose: Check if a file has a particular feature enabled
+ *
+ * Return: Success: Non-negative - TRUE or FALSE
+ * Failure: Negative (should not happen)
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 31 2004
+ *
+ *-------------------------------------------------------------------------
+ */
+hbool_t
+H5F_has_feature(const H5F_t *f, unsigned feature)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_has_feature)
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI((hbool_t)(f->shared->lf->feature_flags&feature))
+} /* end H5F_has_feature() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_get_driver_id
+ *
+ * Purpose: Quick and dirty routine to retrieve the file's 'driver_id' value
+ * (Mainly added to stop non-file routines from poking about in the
+ * H5F_t data structure)
+ *
+ * Return: 'driver_id' on success/abort on failure (shouldn't fail)
+ *
+ * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
+ * October 10, 2000
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5F_get_driver_id(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_get_driver_id)
+
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(f->shared->lf);
+
+ FUNC_LEAVE_NOAPI(f->shared->lf->driver_id)
+} /* end H5F_get_driver_id() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_get_fileno
+ *
+ * Purpose: Quick and dirty routine to retrieve the file's 'fileno' value
+ * (Mainly added to stop non-file routines from poking about in the
+ * H5F_t data structure)
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu>
+ * March 27, 2002
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_get_fileno(const H5F_t *f, unsigned long *filenum)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(H5F_get_fileno, FAIL)
+
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(f->shared->lf);
+ HDassert(filenum);
+
+ /* Retrieve the file's serial number */
+ if(H5FD_get_fileno(f->shared->lf, filenum) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_BADRANGE, FAIL, "can't retrieve fileno")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_get_fileno() */
+
diff --git a/src/H5Fsfile.c b/src/H5Fsfile.c
index 354b307..708fbf7 100644
--- a/src/H5Fsfile.c
+++ b/src/H5Fsfile.c
@@ -219,7 +219,7 @@ H5F_sfile_remove(H5F_file_t *shared)
/* Release the shared file node struct */
/* (the shared file info itself is freed elsewhere) */
- H5FL_FREE(H5F_sfile_node_t, curr);
+ (void)H5FL_FREE(H5F_sfile_node_t, curr);
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5Fsuper.c b/src/H5Fsuper.c
index cbc5f72..3c914bd 100644
--- a/src/H5Fsuper.c
+++ b/src/H5Fsuper.c
@@ -31,6 +31,7 @@
#include "H5Fpkg.h" /* File access */
#include "H5FDprivate.h" /* File drivers */
#include "H5Iprivate.h" /* IDs */
+#include "H5MFprivate.h" /* File memory management */
#include "H5Pprivate.h" /* Property lists */
#include "H5SMprivate.h" /* Shared Object Header Messages */
@@ -186,9 +187,9 @@ H5F_locate_signature(H5FD_t *file, hid_t dxpl_id)
*/
for(n = 8; n < maxpow; n++) {
addr = (8 == n) ? 0 : (haddr_t)1 << n;
- if(H5FD_set_eoa(file, H5FD_MEM_SUPER, addr+H5F_SIGNATURE_LEN) < 0)
+ if(H5FD_set_eoa(file, H5FD_MEM_SUPER, addr + H5F_SIGNATURE_LEN) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTINIT, HADDR_UNDEF, "unable to set EOA value for file signature")
- if(H5FD_read(file, H5FD_MEM_SUPER, dxpl_id, addr, (size_t)H5F_SIGNATURE_LEN, buf) < 0)
+ if(H5FD_read(file, dxpl_id, H5FD_MEM_SUPER, addr, (size_t)H5F_SIGNATURE_LEN, buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTINIT, HADDR_UNDEF, "unable to read file signature")
if(!HDmemcmp(buf, H5F_SIGNATURE, (size_t)H5F_SIGNATURE_LEN))
break;
@@ -235,6 +236,7 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
H5P_genplist_t *c_plist; /* File creation property list */
H5F_file_t *shared; /* shared part of `file' */
H5FD_t *lf; /* file driver part of `shared' */
+ haddr_t abs_super_addr; /* Absolute offset of superblock in file */
haddr_t stored_eoa; /*relative end-of-addr in file */
haddr_t eof; /*end of file address */
size_t sizeof_addr; /* Size of offsets in the file (in bytes) */
@@ -252,18 +254,18 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
lf = shared->lf;
/* Get the shared file creation property list */
- if(NULL == (c_plist = H5I_object(shared->fcpl_id)))
+ if(NULL == (c_plist = (H5P_genplist_t *)H5I_object(shared->fcpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list")
/* Find the superblock */
- if(HADDR_UNDEF == (shared->super_addr = H5F_locate_signature(lf, dxpl_id)))
+ if(HADDR_UNDEF == (abs_super_addr = H5F_locate_signature(lf, dxpl_id)))
HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "unable to find file signature")
/* Read fixed-size portion of the superblock */
p = sbuf;
- if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, shared->super_addr + fixed_size) < 0)
+ if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, abs_super_addr + fixed_size) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "set end of space allocation request failed")
- if(H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, shared->super_addr, fixed_size, p) < 0)
+ if(H5FD_read(lf, dxpl_id, H5FD_MEM_SUPER, abs_super_addr, fixed_size, p) < 0)
HGOTO_ERROR(H5E_FILE, H5E_READERROR, FAIL, "unable to read superblock")
/* Skip over signature (already checked when locating the superblock) */
@@ -285,9 +287,9 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
HDassert(fixed_size + variable_size <= sizeof(sbuf));
/* Read in variable-sized portion of superblock */
- if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, shared->super_addr + fixed_size + variable_size) < 0)
+ if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, abs_super_addr + fixed_size + variable_size) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "set end of space allocation request failed")
- if(H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, shared->super_addr + fixed_size, variable_size, p) < 0)
+ if(H5FD_read(lf, dxpl_id, H5FD_MEM_SUPER, abs_super_addr + fixed_size, variable_size, p) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read superblock")
/* Check for older version of superblock format */
@@ -354,7 +356,7 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
/* File status flags (not really used yet) */
UINT32DECODE(p, status_flags);
HDassert(status_flags <= 255);
- shared->status_flags = status_flags;
+ shared->status_flags = (uint8_t)status_flags;
if(shared->status_flags & ~H5F_SUPER_ALL_FLAGS)
HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad flag value for superblock")
@@ -363,13 +365,13 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
* storage B-tree internal 'K' value
*/
if(super_vers > HDF5_SUPERBLOCK_VERSION_DEF) {
- UINT16DECODE(p, btree_k[H5B_ISTORE_ID]);
+ UINT16DECODE(p, btree_k[H5B_CHUNK_ID]);
/* Reserved bytes are present only in version 1 */
if(super_vers == HDF5_SUPERBLOCK_VERSION_1)
p += 2; /* reserved */
} /* end if */
else
- btree_k[H5B_ISTORE_ID] = HDF5_BTREE_ISTORE_IK_DEF;
+ btree_k[H5B_CHUNK_ID] = HDF5_BTREE_CHUNK_IK_DEF;
/* Set the B-tree internal node values, etc */
if(H5P_set(c_plist, H5F_CRT_BTREE_RANK_NAME, btree_k) < 0)
@@ -388,17 +390,23 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
* Check if superblock address is different from base address and
* adjust base address and "end of address" address if so.
*/
- if(!H5F_addr_eq(shared->super_addr, shared->base_addr)) {
+ if(!H5F_addr_eq(abs_super_addr, shared->base_addr)) {
/* Check if the superblock moved earlier in the file */
- if(H5F_addr_lt(shared->super_addr, shared->base_addr))
- stored_eoa -= (shared->base_addr - shared->super_addr);
+ if(H5F_addr_lt(abs_super_addr, shared->base_addr))
+ stored_eoa -= (shared->base_addr - abs_super_addr);
else
/* The superblock moved later in the file */
- stored_eoa += (shared->super_addr - shared->base_addr);
+ stored_eoa += (abs_super_addr - shared->base_addr);
- shared->base_addr = shared->super_addr;
+ shared->base_addr = abs_super_addr;
} /* end if */
+ /* Set the base address for the file in the VFD now, after adjusting
+ * space for possible offsets of the HDF5 data in the file.
+ */
+ if(H5FD_set_base_addr(lf, shared->base_addr) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "failed to set base address for file driver")
+
/* This step is for h5repart tool only. If user wants to change file driver
* from family to sec2 while using h5repart, set the driver address to
* undefined to let the library ignore the family driver information saved
@@ -412,14 +420,13 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
uint8_t dbuf[H5F_MAX_DRVINFOBLOCK_SIZE]; /* Buffer for driver info block */
char drv_name[9]; /* Name of driver */
unsigned drv_vers; /* Version of driver info block */
- haddr_t drv_addr = shared->base_addr + shared->driver_addr;
size_t drv_variable_size; /* Size of variable-length portion of driver info block, in bytes */
/* Read in fixed-sized portion of driver info block */
p = dbuf;
- if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, drv_addr + H5F_DRVINFOBLOCK_HDR_SIZE) < 0)
+ if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, shared->driver_addr + H5F_DRVINFOBLOCK_HDR_SIZE) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "set end of space allocation request failed")
- if(H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, drv_addr, (size_t)H5F_DRVINFOBLOCK_HDR_SIZE, p) < 0)
+ if(H5FD_read(lf, dxpl_id, H5FD_MEM_SUPER, shared->driver_addr, (size_t)H5F_DRVINFOBLOCK_HDR_SIZE, p) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read driver information block")
/* Version number */
@@ -449,9 +456,9 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "multi driver should be used")
/* Read in variable-sized portion of driver info block */
- if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, drv_addr + H5F_DRVINFOBLOCK_HDR_SIZE + drv_variable_size) < 0)
+ if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, shared->driver_addr + H5F_DRVINFOBLOCK_HDR_SIZE + drv_variable_size) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "set end of space allocation request failed")
- if(H5FD_read(lf, H5FD_MEM_SUPER, dxpl_id, drv_addr + H5F_DRVINFOBLOCK_HDR_SIZE, drv_variable_size, p) < 0)
+ if(H5FD_read(lf, dxpl_id, H5FD_MEM_SUPER, shared->driver_addr + H5F_DRVINFOBLOCK_HDR_SIZE, drv_variable_size, p) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read file driver information")
/* Decode driver information */
@@ -512,16 +519,22 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
* Check if superblock address is different from base address and
* adjust base address and "end of address" address if so.
*/
- if(!H5F_addr_eq(shared->super_addr, shared->base_addr)) {
+ if(!H5F_addr_eq(abs_super_addr, shared->base_addr)) {
/* Check if the superblock moved earlier in the file */
- if(H5F_addr_lt(shared->super_addr, shared->base_addr))
- stored_eoa -= (shared->base_addr - shared->super_addr);
+ if(H5F_addr_lt(abs_super_addr, shared->base_addr))
+ stored_eoa -= (shared->base_addr - abs_super_addr);
else
/* The superblock moved later in the file */
- stored_eoa += (shared->super_addr - shared->base_addr);
+ stored_eoa += (abs_super_addr - shared->base_addr);
- shared->base_addr = shared->super_addr;
+ shared->base_addr = abs_super_addr;
} /* end if */
+
+ /* Set the base address for the file in the VFD now, after adjusting
+ * space for possible offsets of the HDF5 data in the file.
+ */
+ if(H5FD_set_base_addr(lf, shared->base_addr) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "failed to set base address for file driver")
} /* end else */
/*
@@ -538,7 +551,8 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
*/
if(HADDR_UNDEF == (eof = H5FD_get_eof(lf)))
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size")
- if(eof < stored_eoa)
+ /* (Account for the stored EOA being absolute offset -QAK) */
+ if((eof + H5F_BASE_ADDR(f)) < stored_eoa)
HGOTO_ERROR(H5E_FILE, H5E_TRUNCATED, FAIL, "truncated file")
/*
@@ -553,12 +567,25 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
H5O_loc_t ext_loc; /* "Object location" for superblock extension */
H5O_btreek_t btreek; /* v1 B-tree 'K' value message from superblock extension */
H5O_drvinfo_t drvinfo; /* Driver info message from superblock extension */
+ htri_t status; /* Status for message existing */
/* Sanity check - superblock extension should only be defined for
* superblock version >= 2.
*/
HDassert(super_vers >= HDF5_SUPERBLOCK_VERSION_2);
+ /* Check for superblock extension being located "outside" the stored
+ * 'eoa' value, which can occur with the split/multi VFD.
+ */
+ if(H5F_addr_gt(shared->extension_addr, stored_eoa)) {
+ /* Set the 'eoa' for the object header memory type large enough
+ * to give some room for a reasonably sized superblock extension.
+ * (This is _rather_ a kludge -QAK)
+ */
+ if(H5FD_set_eoa(lf, H5FD_MEM_OHDR, (haddr_t)(shared->extension_addr + 1024)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to set end-of-address marker for file")
+ } /* end if */
+
/* Set up "fake" object location for superblock extension */
H5O_loc_reset(&ext_loc);
ext_loc.file = f;
@@ -566,25 +593,46 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
/* Open the superblock extension */
if(H5O_open(&ext_loc) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENFILE, FAIL, "unable to open superblock extension")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to open superblock extension")
+
+ /* Check for the extension having a 'driver info' message */
+ if((status = H5O_msg_exists(&ext_loc, H5O_DRVINFO_ID, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to read object header")
+ if(status) {
+ /* Retrieve the 'driver info' structure */
+ if(NULL == H5O_msg_read(&ext_loc, H5O_DRVINFO_ID, &drvinfo, dxpl_id))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "driver info message not present")
+
+ /* Check if driver matches driver information saved. Unfortunately, we can't push this
+ * function to each specific driver because we're checking if the driver is correct.
+ */
+ if(!HDstrncmp(drvinfo.name, "NCSAfami", (size_t)8) && HDstrcmp(lf->cls->name, "family"))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "family driver should be used")
+ if(!HDstrncmp(drvinfo.name, "NCSAmult", (size_t)8) && HDstrcmp(lf->cls->name, "multi"))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "multi driver should be used")
+
+ /* Decode driver information */
+ if(H5FD_sb_decode(lf, drvinfo.name, drvinfo.buf) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to decode driver information")
+
+ /* Reset driver info message */
+ H5O_msg_reset(H5O_DRVINFO_ID, &drvinfo);
+ } /* end if */
/* Read in the shared OH message information if there is any */
if(H5SM_get_info(&ext_loc, c_plist, dxpl_id) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read SOHM table information")
- /* Read in v1 B-tree 'K' value message, if it exists */
- if(NULL == H5O_msg_read(&ext_loc, H5O_BTREEK_ID, &btreek, dxpl_id)) {
- /* Reset error from "failed" message read */
- H5E_clear_stack(NULL);
+ /* Check for the extension having a 'v1 B-tree "K"' message */
+ if((status = H5O_msg_exists(&ext_loc, H5O_BTREEK_ID, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to read object header")
+ if(status) {
+ /* Retrieve the 'v1 B-tree "K"' structure */
+ if(NULL == H5O_msg_read(&ext_loc, H5O_BTREEK_ID, &btreek, dxpl_id))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "v1 B-tree 'K' info message not present")
- /* No non-default v1 B-tree 'K' value info in file, use defaults */
- shared->btree_k[H5B_ISTORE_ID] = HDF5_BTREE_ISTORE_IK_DEF;
- shared->btree_k[H5B_SNODE_ID] = HDF5_BTREE_SNODE_IK_DEF;
- shared->sym_leaf_k = H5F_CRT_SYM_LEAF_DEF;
- } /* end if */
- else {
/* Set non-default v1 B-tree 'K' value info from file */
- shared->btree_k[H5B_ISTORE_ID] = btreek.btree_k[H5B_ISTORE_ID];
+ shared->btree_k[H5B_CHUNK_ID] = btreek.btree_k[H5B_CHUNK_ID];
shared->btree_k[H5B_SNODE_ID] = btreek.btree_k[H5B_SNODE_ID];
shared->sym_leaf_k = btreek.sym_leaf_k;
@@ -593,29 +641,13 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set rank for btree internal nodes")
if(H5P_set(c_plist, H5F_CRT_SYM_LEAF_NAME, &btreek.sym_leaf_k) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set rank for symbol table leaf nodes")
- } /* end else */
-
- /* Read in driver info message, if it exists */
- if(NULL == H5O_msg_read(&ext_loc, H5O_DRVINFO_ID, &drvinfo, dxpl_id)) {
- /* Reset error from "failed" message read */
- H5E_clear_stack(NULL);
} /* end if */
else {
- /* Check if driver matches driver information saved. Unfortunately, we can't push this
- * function to each specific driver because we're checking if the driver is correct.
- */
- if(!HDstrncmp(drvinfo.name, "NCSAfami", (size_t)8) && HDstrcmp(lf->cls->name, "family"))
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "family driver should be used")
- if(!HDstrncmp(drvinfo.name, "NCSAmult", (size_t)8) && HDstrcmp(lf->cls->name, "multi"))
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "multi driver should be used")
-
- /* Decode driver information */
- if(H5FD_sb_decode(lf, drvinfo.name, drvinfo.buf) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to decode driver information")
-
- /* Reset driver info message */
- H5O_msg_reset(H5O_DRVINFO_ID, &drvinfo);
- } /* end else */
+ /* No non-default v1 B-tree 'K' value info in file, use defaults */
+ shared->btree_k[H5B_CHUNK_ID] = HDF5_BTREE_CHUNK_IK_DEF;
+ shared->btree_k[H5B_SNODE_ID] = HDF5_BTREE_SNODE_IK_DEF;
+ shared->sym_leaf_k = H5F_CRT_SYM_LEAF_DEF;
+ } /* end if */
/* Close the extension. Twiddle the number of open objects to avoid
* closing the file (since this will be the only open object).
@@ -652,9 +684,8 @@ H5F_super_init(H5F_t *f, hid_t dxpl_id)
{
H5P_genplist_t *plist; /* File creation property list */
hsize_t userblock_size; /* Size of userblock, in bytes */
- size_t superblock_size; /* Size of superblock, in bytes */
+ hsize_t superblock_size; /* Size of superblock, in bytes */
size_t driver_size; /* Size of driver info block (bytes) */
- hsize_t alloc_size; /* Size to allocate on disk */
unsigned super_vers; /* Superblock version */
haddr_t super_addr; /* Address of superblock */
hbool_t need_ext; /* Whether the superblock extension is needed */
@@ -663,7 +694,7 @@ H5F_super_init(H5F_t *f, hid_t dxpl_id)
FUNC_ENTER_NOAPI(H5F_super_init, FAIL)
/* Get the shared file creation property list */
- if(NULL == (plist = H5I_object(f->shared->fcpl_id)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(f->shared->fcpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
/*
@@ -674,10 +705,19 @@ H5F_super_init(H5F_t *f, hid_t dxpl_id)
*/
if(H5P_get(plist, H5F_CRT_USER_BLOCK_NAME, &userblock_size) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get userblock size")
- f->shared->super_addr = userblock_size;
- f->shared->base_addr = f->shared->super_addr;
+ f->shared->base_addr = userblock_size;
f->shared->status_flags = 0;
+ /* Reserve space for the userblock */
+ if(H5FD_set_eoa(f->shared->lf, H5FD_MEM_SUPER, userblock_size) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to set EOA value for userblock")
+
+ /* Set the base address for the file in the VFD now, after allocating
+ * space for userblock.
+ */
+ if(H5FD_set_base_addr(f->shared->lf, f->shared->base_addr) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "failed to set base address for file driver")
+
/* Grab superblock version from property list */
if(H5P_get(plist, H5F_CRT_SUPER_VERS_NAME, &super_vers) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get superblock version")
@@ -703,11 +743,9 @@ H5F_super_init(H5F_t *f, hid_t dxpl_id)
* 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);
- alloc_size = (hsize_t)f->shared->base_addr + superblock_size;
if(super_vers < HDF5_SUPERBLOCK_VERSION_2)
- alloc_size += driver_size;
- super_addr = H5FD_alloc(f->shared->lf, H5FD_MEM_SUPER, dxpl_id, alloc_size);
+ superblock_size += driver_size;
+ super_addr = H5MF_alloc(f, H5FD_MEM_SUPER, dxpl_id, superblock_size);
if(HADDR_UNDEF == super_addr)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to allocate file space for userblock and/or superblock")
if(0 != super_addr)
@@ -722,14 +760,14 @@ H5F_super_init(H5F_t *f, hid_t dxpl_id)
HDassert(super_vers >= HDF5_SUPERBLOCK_VERSION_2);
need_ext = TRUE;
} /* end if */
- /* If we're going to use a version of the superblock format which allows
+ /* If we're going to use a version of the superblock format which allows
* for the superblock extension, check for non-default values to store
* in it.
*/
else if(super_vers >= HDF5_SUPERBLOCK_VERSION_2) {
/* Check for non-default v1 B-tree 'K' values to store */
if(f->shared->btree_k[H5B_SNODE_ID] != HDF5_BTREE_SNODE_IK_DEF ||
- f->shared->btree_k[H5B_ISTORE_ID] != HDF5_BTREE_ISTORE_IK_DEF ||
+ f->shared->btree_k[H5B_CHUNK_ID] != HDF5_BTREE_CHUNK_IK_DEF ||
f->shared->sym_leaf_k != H5F_CRT_SYM_LEAF_DEF)
need_ext = TRUE;
/* Check for driver info to store */
@@ -771,12 +809,12 @@ H5F_super_init(H5F_t *f, hid_t dxpl_id)
/* Check for non-default v1 B-tree 'K' values to store */
if(f->shared->btree_k[H5B_SNODE_ID] != HDF5_BTREE_SNODE_IK_DEF ||
- f->shared->btree_k[H5B_ISTORE_ID] != HDF5_BTREE_ISTORE_IK_DEF ||
+ f->shared->btree_k[H5B_CHUNK_ID] != HDF5_BTREE_CHUNK_IK_DEF ||
f->shared->sym_leaf_k != H5F_CRT_SYM_LEAF_DEF) {
H5O_btreek_t btreek; /* v1 B-tree 'K' value message for superblock extension */
/* Write v1 B-tree 'K' value information to the superblock extension */
- btreek.btree_k[H5B_ISTORE_ID] = f->shared->btree_k[H5B_ISTORE_ID];
+ btreek.btree_k[H5B_CHUNK_ID] = f->shared->btree_k[H5B_CHUNK_ID];
btreek.btree_k[H5B_SNODE_ID] = f->shared->btree_k[H5B_SNODE_ID];
btreek.sym_leaf_k = f->shared->sym_leaf_k;
if(H5O_msg_create(&ext_loc, H5O_BTREEK_ID, H5O_MSG_FLAG_CONSTANT | H5O_MSG_FLAG_DONTSHARE, H5O_UPDATE_TIME, &btreek, dxpl_id) < 0)
@@ -798,7 +836,7 @@ H5F_super_init(H5F_t *f, hid_t dxpl_id)
/* Write driver info information to the superblock extension */
drvinfo.len = driver_size;
drvinfo.buf = dbuf;
- if(H5O_msg_create(&ext_loc, H5O_DRVINFO_ID, H5O_MSG_FLAG_CONSTANT | H5O_MSG_FLAG_DONTSHARE, H5O_UPDATE_TIME, &drvinfo, dxpl_id) < 0)
+ if(H5O_msg_create(&ext_loc, H5O_DRVINFO_ID, H5O_MSG_FLAG_DONTSHARE, H5O_UPDATE_TIME, &drvinfo, dxpl_id) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to update driver info header message")
} /* end if */
@@ -836,6 +874,7 @@ H5F_super_write(H5F_t *f, hid_t dxpl_id)
H5P_genplist_t *plist; /* File creation property list */
uint8_t buf[H5F_MAX_SUPERBLOCK_SIZE + H5F_MAX_DRVINFOBLOCK_SIZE]; /* Superblock & driver info blockencoding buffer */
uint8_t *p; /* Ptr into encoding buffer */
+ haddr_t rel_eoa; /* Relative EOA for file */
size_t superblock_size; /* Size of superblock, in bytes */
size_t driver_size; /* Size of driver info block (bytes)*/
unsigned super_vers; /* Superblock version */
@@ -844,7 +883,7 @@ H5F_super_write(H5F_t *f, hid_t dxpl_id)
FUNC_ENTER_NOAPI(H5F_super_write, FAIL)
/* Get the shared file creation property list */
- if(NULL == (plist = H5I_object(f->shared->fcpl_id)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(f->shared->fcpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
/* Grab values from property list */
@@ -879,14 +918,15 @@ H5F_super_write(H5F_t *f, hid_t dxpl_id)
* internal 'K' value stored
*/
if(super_vers > HDF5_SUPERBLOCK_VERSION_DEF) {
- UINT16ENCODE(p, f->shared->btree_k[H5B_ISTORE_ID]);
+ UINT16ENCODE(p, f->shared->btree_k[H5B_CHUNK_ID]);
*p++ = 0; /*reserved */
*p++ = 0; /*reserved */
} /* end if */
H5F_addr_encode(f, &p, f->shared->base_addr);
H5F_addr_encode(f, &p, f->shared->extension_addr);
- H5F_addr_encode(f, &p, H5FD_get_eoa(f->shared->lf, H5FD_MEM_SUPER));
+ rel_eoa = H5FD_get_eoa(f->shared->lf, H5FD_MEM_SUPER);
+ H5F_addr_encode(f, &p, (rel_eoa + f->shared->base_addr));
H5F_addr_encode(f, &p, f->shared->driver_addr);
if(H5G_obj_ent_encode(f, &p, H5G_oloc(f->shared->root_grp)) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to encode root group information")
@@ -932,7 +972,8 @@ H5F_super_write(H5F_t *f, hid_t dxpl_id)
/* Base, superblock extension & end of file addresses */
H5F_addr_encode(f, &p, f->shared->base_addr);
H5F_addr_encode(f, &p, f->shared->extension_addr);
- H5F_addr_encode(f, &p, H5FD_get_eoa(f->shared->lf, H5FD_MEM_SUPER));
+ rel_eoa = H5FD_get_eoa(f->shared->lf, H5FD_MEM_SUPER);
+ H5F_addr_encode(f, &p, (rel_eoa + f->shared->base_addr));
/* Retrieve information for root group */
if(NULL == (root_oloc = H5G_oloc(f->shared->root_grp)))
@@ -957,10 +998,51 @@ H5F_super_write(H5F_t *f, hid_t dxpl_id)
/* Double check we didn't overrun the block (unlikely) */
HDassert(superblock_size <= sizeof(buf));
- /* Write superblock */
- if(H5FD_write(f->shared->lf, H5FD_MEM_SUPER, dxpl_id, f->shared->super_addr, superblock_size, buf) < 0)
+ /* Write superblock (always at relative offset 0) */
+ if(H5FD_write(f->shared->lf, dxpl_id, H5FD_MEM_SUPER, (haddr_t)0, superblock_size, buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write superblock")
+ /* Check for newer version of superblock format & superblock extension */
+ if(super_vers >= HDF5_SUPERBLOCK_VERSION_2 && H5F_addr_defined(f->shared->extension_addr)) {
+ /* Check for driver info message */
+ H5_ASSIGN_OVERFLOW(driver_size, H5FD_sb_size(f->shared->lf), hsize_t, size_t);
+ if(driver_size > 0) {
+ H5O_loc_t ext_loc; /* "Object location" for superblock extension */
+ H5O_drvinfo_t drvinfo; /* Driver info */
+ uint8_t dbuf[H5F_MAX_DRVINFOBLOCK_SIZE]; /* Driver info block encoding buffer */
+
+ /* Sanity check */
+ HDassert(driver_size <= H5F_MAX_DRVINFOBLOCK_SIZE);
+
+ /* Encode driver-specific data */
+ if(H5FD_sb_encode(f->shared->lf, drvinfo.name, dbuf) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to encode driver information")
+
+ /* Set up "fake" object location for superblock extension */
+ H5O_loc_reset(&ext_loc);
+ ext_loc.file = f;
+ ext_loc.addr = f->shared->extension_addr;
+
+ /* Open the superblock extension */
+ if(H5O_open(&ext_loc) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENFILE, FAIL, "unable to open superblock extension")
+
+ /* Write driver info information to the superblock extension */
+ drvinfo.len = driver_size;
+ drvinfo.buf = dbuf;
+ if(H5O_msg_write(&ext_loc, H5O_DRVINFO_ID, H5O_MSG_FLAG_DONTSHARE, H5O_UPDATE_TIME, &drvinfo, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to update driver info header message")
+
+ /* Close the extension. Twiddle the number of open objects to avoid
+ * closing the file (since this will be the only open object).
+ */
+ f->nopen_objs++;
+ if(H5O_close(&ext_loc) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENFILE, FAIL, "unable to close superblock extension")
+ f->nopen_objs--;
+ } /* end if */
+ } /* end if */
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F_super_write() */
diff --git a/src/H5Ftest.c b/src/H5Ftest.c
index 67ea5f7..1d7e514 100644
--- a/src/H5Ftest.c
+++ b/src/H5Ftest.c
@@ -102,7 +102,7 @@ H5F_get_sohm_mesg_count_test(hid_t file_id, unsigned type_id,
FUNC_ENTER_NOAPI_NOINIT(H5F_get_sohm_mesg_count_test)
/* Check arguments */
- if(NULL == (file = H5I_object_verify(file_id, H5I_FILE)))
+ if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
/* Retrieve count for message type */
diff --git a/src/H5G.c b/src/H5G.c
index bca0332..6a7e505 100644
--- a/src/H5G.c
+++ b/src/H5G.c
@@ -88,6 +88,7 @@
#include "H5Gpkg.h" /* Groups */
#include "H5Iprivate.h" /* IDs */
#include "H5Lprivate.h" /* Links */
+#include "H5MMprivate.h" /* Memory management */
#include "H5Pprivate.h" /* Property lists */
/* Local macros */
@@ -100,14 +101,43 @@ typedef struct {
H5G_loc_t *loc; /* Pointer to the location for insertion */
} H5G_trav_ins_t;
+/* User data for application-style iteration over links in a group */
+typedef struct {
+ hid_t gid; /* The group ID for the application callback */
+ H5G_link_iterate_t lnk_op; /* Application callback */
+ void *op_data; /* Application's op data */
+} H5G_iter_appcall_ud_t;
+
+/* User data for recursive traversal over links from a group */
+typedef struct {
+ hid_t gid; /* The group ID for the starting group */
+ H5G_loc_t *curr_loc; /* Location of starting group */
+ hid_t lapl_id; /* LAPL for walking across links */
+ hid_t dxpl_id; /* DXPL for operations */
+ H5_index_t idx_type; /* Index to use */
+ H5_iter_order_t order; /* Iteration order within index */
+ H5SL_t *visited; /* Skip list for tracking visited nodes */
+ char *path; /* Path name of the link */
+ size_t curr_path_len; /* Current length of the path in the buffer */
+ size_t path_buf_size; /* Size of path buffer */
+ H5L_iterate_t op; /* Application callback */
+ void *op_data; /* Application's op data */
+} H5G_iter_visit_ud_t;
+
+
/* Package variables */
+
/* Local variables */
/* Declare a free list to manage the H5G_t struct */
H5FL_DEFINE(H5G_t);
H5FL_DEFINE(H5G_shared_t);
+/* Declare the free list to manage H5_obj_t's */
+H5FL_DEFINE(H5_obj_t);
+
+
/* Private prototypes */
static herr_t H5G_open_oid(H5G_t *grp, hid_t dxpl_id);
@@ -179,7 +209,7 @@ H5Gcreate2(hid_t loc_id, const char *name, hid_t lcpl_id, hid_t gcpl_id,
/* Create the new group & get its ID */
if(NULL == (grp = H5G_create_named(&loc, name, lcpl_id, gcpl_id, gapl_id, H5AC_dxpl_id)))
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create group")
- if((ret_value = H5I_register(H5I_GROUP, grp)) < 0)
+ if((ret_value = H5I_register(H5I_GROUP, grp, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group")
done:
@@ -237,7 +267,7 @@ H5G_create_named(const H5G_loc_t *loc, const char *name, hid_t lcpl_id,
HDassert(ocrt_info.new_obj);
/* Set the return value */
- ret_value = ocrt_info.new_obj;
+ ret_value = (H5G_t *)ocrt_info.new_obj;
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -310,7 +340,7 @@ H5Gcreate_anon(hid_t loc_id, hid_t gcpl_id, hid_t gapl_id)
/* Create the new group & get its ID */
if(NULL == (grp = H5G_create(loc.oloc->file, gcpl_id, H5AC_dxpl_id)))
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create group")
- if((ret_value = H5I_register(H5I_GROUP, grp)) < 0)
+ if((ret_value = H5I_register(H5I_GROUP, grp, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group")
done:
@@ -366,8 +396,8 @@ H5Gopen2(hid_t loc_id, const char *name, hid_t gapl_id)
if((grp = H5G_open_name(&loc, name, gapl_id, H5AC_dxpl_id)) == NULL)
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group")
- /* Register an atom for the group */
- if((ret_value = H5I_register(H5I_GROUP, grp)) < 0)
+ /* Register an ID for the group */
+ if((ret_value = H5I_register(H5I_GROUP, grp, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group")
done:
@@ -399,8 +429,9 @@ done:
hid_t
H5Gget_create_plist(hid_t group_id)
{
- htri_t ginfo_exists = 0;
- htri_t linfo_exists = 0;
+ H5O_linfo_t linfo; /* Link info message */
+ htri_t ginfo_exists;
+ htri_t linfo_exists;
H5G_t *grp = NULL;
H5P_genplist_t *gcpl_plist;
H5P_genplist_t *new_plist;
@@ -411,15 +442,15 @@ H5Gget_create_plist(hid_t group_id)
H5TRACE1("i", "i", group_id);
/* Check args */
- if(NULL == (grp = H5I_object_verify(group_id, H5I_GROUP)))
+ if(NULL == (grp = (H5G_t *)H5I_object_verify(group_id, H5I_GROUP)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group")
/* Copy the default group creation property list */
- if(NULL == (gcpl_plist = H5I_object(H5P_LST_GROUP_CREATE_g)))
+ if(NULL == (gcpl_plist = (H5P_genplist_t *)H5I_object(H5P_LST_GROUP_CREATE_g)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get default group creation property list")
- if((new_gcpl_id = H5P_copy_plist(gcpl_plist)) < 0)
+ if((new_gcpl_id = H5P_copy_plist(gcpl_plist, TRUE)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to copy the creation property list")
- if(NULL == (new_plist = H5I_object(new_gcpl_id)))
+ if(NULL == (new_plist = (H5P_genplist_t *)H5I_object(new_gcpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list")
/* Retrieve any object creation properties */
@@ -442,15 +473,9 @@ H5Gget_create_plist(hid_t group_id)
} /* end if */
/* Check for the group having a link info message */
- if((linfo_exists = H5O_msg_exists(&(grp->oloc), H5O_LINFO_ID, H5AC_ind_dxpl_id)) < 0)
+ if((linfo_exists = H5G_obj_get_linfo(&(grp->oloc), &linfo, H5AC_ind_dxpl_id)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to read object header")
if(linfo_exists) {
- H5O_linfo_t linfo; /* Link info message */
-
- /* Read the link info */
- if(NULL == H5G_obj_get_linfo(&(grp->oloc), &linfo, H5AC_ind_dxpl_id))
- HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't get link info")
-
/* Set the link info for the property list */
if(H5P_set(new_plist, H5G_CRT_LINK_INFO_NAME, &linfo) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set link info")
@@ -462,7 +487,7 @@ H5Gget_create_plist(hid_t group_id)
done:
if(ret_value < 0) {
if(new_gcpl_id > 0)
- (void)H5I_dec_ref(new_gcpl_id);
+ (void)H5I_dec_ref(new_gcpl_id, TRUE);
} /* end if */
FUNC_LEAVE_API(ret_value)
@@ -672,7 +697,7 @@ H5Gclose(hid_t group_id)
* Decrement the counter on the group atom. It will be freed if the count
* reaches zero.
*/
- if(H5I_dec_ref(group_id) < 0)
+ if(H5I_dec_ref(group_id, TRUE) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "unable to close group")
done:
@@ -773,7 +798,7 @@ H5G_term_interface(void)
if(H5_interface_initialize_g) {
if((n = H5I_nmembers(H5I_GROUP)))
- H5I_clear_type(H5I_GROUP, FALSE);
+ H5I_clear_type(H5I_GROUP, FALSE, FALSE);
else {
/* Destroy the group object id group */
H5I_dec_type_ref(H5I_GROUP);
@@ -842,7 +867,7 @@ H5G_mkroot(H5F_t *f, hid_t dxpl_id, H5G_loc_t *loc)
/* Get the file creation property list */
/* (Which is a sub-class of the group creation property class) */
- if(NULL == (fc_plist = H5I_object(f->shared->fcpl_id)))
+ if(NULL == (fc_plist = (H5P_genplist_t *)H5I_object(f->shared->fcpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
/* Get the group info property */
@@ -884,7 +909,7 @@ H5G_mkroot(H5F_t *f, hid_t dxpl_id, H5G_loc_t *loc)
if(NULL == (f->shared->root_grp = H5FL_CALLOC(H5G_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
if(NULL == (f->shared->root_grp->shared = H5FL_CALLOC(H5G_shared_t))) {
- H5FL_FREE(H5G_t, f->shared->root_grp);
+ (void)H5FL_FREE(H5G_t, f->shared->root_grp);
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
} /* end if */
@@ -950,7 +975,7 @@ H5G_create(H5F_t *file, hid_t gcpl_id, hid_t dxpl_id)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Get the property list */
- if(NULL == (gc_plist = H5I_object(gcpl_id)))
+ if(NULL == (gc_plist = (H5P_genplist_t *)H5I_object(gcpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a property list")
/* Get the group info property */
@@ -974,7 +999,7 @@ H5G_create(H5F_t *file, hid_t gcpl_id, hid_t dxpl_id)
/* Set the count of times the object is opened */
grp->shared->fo_count = 1;
-
+
/* Set return value */
ret_value = grp;
@@ -989,8 +1014,8 @@ done:
} /* end if */
if(grp != NULL) {
if(grp->shared != NULL)
- H5FL_FREE(H5G_shared_t, grp->shared);
- H5FL_FREE(H5G_t,grp);
+ (void)H5FL_FREE(H5G_shared_t, grp->shared);
+ (void)H5FL_FREE(H5G_t,grp);
} /* end if */
} /* end if */
@@ -1019,8 +1044,8 @@ H5G_open_name(const H5G_loc_t *loc, const char *name, hid_t gapl_id,
H5G_loc_t grp_loc; /* Location used to open group */
H5G_name_t grp_path; /* Opened object group hier. path */
H5O_loc_t grp_oloc; /* Opened object object location */
- H5O_type_t obj_type; /* Type of object at location */
hbool_t loc_found = FALSE; /* Location at 'name' found */
+ H5O_type_t obj_type; /* Type of object at location */
H5G_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5G_open_name, NULL)
@@ -1100,7 +1125,7 @@ H5G_open(const H5G_loc_t *loc, hid_t dxpl_id)
HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "can't copy path")
/* Check if group was already open */
- if((shared_fo = H5FO_opened(grp->oloc.file, grp->oloc.addr)) == NULL) {
+ if((shared_fo = (H5G_shared_t *)H5FO_opened(grp->oloc.file, grp->oloc.addr)) == NULL) {
/* Clear any errors from H5FO_opened() */
H5E_clear_stack(NULL);
@@ -1111,7 +1136,7 @@ H5G_open(const H5G_loc_t *loc, hid_t dxpl_id)
/* Add group to list of open objects in file */
if(H5FO_insert(grp->oloc.file, grp->oloc.addr, grp->shared, FALSE) < 0) {
- H5FL_FREE(H5G_shared_t, grp->shared);
+ (void)H5FL_FREE(H5G_shared_t, grp->shared);
HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, NULL, "can't insert group into list of open objects")
} /* end if */
@@ -1145,10 +1170,10 @@ H5G_open(const H5G_loc_t *loc, hid_t dxpl_id)
ret_value = grp;
done:
- if (!ret_value && grp) {
+ if(!ret_value && grp) {
H5O_loc_free(&(grp->oloc));
H5G_name_free(&(grp->path));
- H5FL_FREE(H5G_t,grp);
+ (void)H5FL_FREE(H5G_t,grp);
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
@@ -1200,7 +1225,7 @@ done:
if(obj_opened)
H5O_close(&(grp->oloc));
if(grp->shared)
- H5FL_FREE(H5G_shared_t, grp->shared);
+ (void)H5FL_FREE(H5G_shared_t, grp->shared);
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
@@ -1242,7 +1267,7 @@ H5G_close(H5G_t *grp)
HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't remove group from list of open objects")
if(H5O_close(&(grp->oloc)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to close")
- H5FL_FREE(H5G_shared_t, grp->shared);
+ (void)H5FL_FREE(H5G_shared_t, grp->shared);
} else {
/* Decrement the ref. count for this object in the top file */
if(H5FO_top_decr(grp->oloc.file, grp->oloc.addr) < 0)
@@ -1264,11 +1289,11 @@ H5G_close(H5G_t *grp)
} /* end else */
if(H5G_name_free(&(grp->path)) < 0) {
- H5FL_FREE(H5G_t,grp);
+ (void)H5FL_FREE(H5G_t, grp);
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't free group entry name")
} /* end if */
- H5FL_FREE(H5G_t,grp);
+ (void)H5FL_FREE(H5G_t, grp);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1299,8 +1324,8 @@ H5G_free(H5G_t *grp)
HDassert(grp && grp->shared);
- H5FL_FREE(H5G_shared_t, grp->shared);
- H5FL_FREE(H5G_t, grp);
+ (void)H5FL_FREE(H5G_shared_t, grp->shared);
+ (void)H5FL_FREE(H5G_t, grp);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1330,8 +1355,8 @@ H5G_rootof(H5F_t *f)
{
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_rootof)
- while(f->mtab.parent)
- f = f->mtab.parent;
+ while(f->parent)
+ f = f->parent;
FUNC_LEAVE_NOAPI(f->shared->root_grp)
} /* end H5G_rootof() */
@@ -1496,6 +1521,30 @@ H5G_mount(H5G_t *grp)
/*-------------------------------------------------------------------------
+ * Function: H5G_mounted
+ *
+ * Purpose: Retrieves the 'mounted' flag for a group
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, July 15, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+hbool_t
+H5G_mounted(H5G_t *grp)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_mounted)
+
+ /* Check args */
+ HDassert(grp && grp->shared);
+
+ FUNC_LEAVE_NOAPI(grp->shared->mounted)
+} /* end H5G_mounted() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5G_unmount
*
* Purpose: Resets the 'mounted' flag for a group
@@ -1522,3 +1571,456 @@ H5G_unmount(H5G_t *grp)
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5G_unmount() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_iterate_cb
+ *
+ * Purpose: Callback function for iterating over links in a group
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Oct 3, 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5G_iterate_cb(const H5O_link_t *lnk, void *_udata)
+{
+ H5G_iter_appcall_ud_t *udata = (H5G_iter_appcall_ud_t *)_udata; /* User data for callback */
+ herr_t ret_value = H5_ITER_ERROR; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5G_iterate_cb)
+
+ /* Sanity check */
+ HDassert(lnk);
+ HDassert(udata);
+
+ switch(udata->lnk_op.op_type) {
+#ifndef H5_NO_DEPRECATED_SYMBOLS
+ case H5G_LINK_OP_OLD:
+ /* Make the old-type application callback */
+ ret_value = (udata->lnk_op.op_func.op_old)(udata->gid, lnk->name, udata->op_data);
+ break;
+#endif /* H5_NO_DEPRECATED_SYMBOLS */
+
+ case H5G_LINK_OP_NEW:
+ {
+ H5L_info_t info; /* Link info */
+
+ /* Retrieve the info for the link */
+ if(H5G_link_to_info(lnk, &info) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get info for link")
+
+ /* Make the application callback */
+ ret_value = (udata->lnk_op.op_func.op_new)(udata->gid, lnk->name, &info, udata->op_data);
+ }
+ break;
+
+ default:
+ HDassert(0 && "Unknown link op type?!?");
+ } /* end switch */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_iterate_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_iterate
+ *
+ * Purpose: Private function for iterating over links in a group
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Oct 3, 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_iterate(hid_t loc_id, const char *group_name,
+ H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk,
+ const H5G_link_iterate_t *lnk_op, void *op_data, hid_t lapl_id, hid_t dxpl_id)
+{
+ H5G_loc_t loc; /* Location of parent for group */
+ hid_t gid = -1; /* ID of group to iterate over */
+ H5G_t *grp = NULL; /* Pointer to group data structure to iterate over */
+ H5G_iter_appcall_ud_t udata; /* User data for callback */
+ herr_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5G_iterate, FAIL)
+
+ /* Sanity check */
+ HDassert(group_name);
+ HDassert(last_lnk);
+ HDassert(lnk_op && lnk_op->op_func.op_new);
+
+ /*
+ * Open the group on which to operate. We also create a group ID which
+ * we can pass to the application-defined operator.
+ */
+ if(H5G_loc(loc_id, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
+ if(NULL == (grp = H5G_open_name(&loc, group_name, lapl_id, dxpl_id)))
+ HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group")
+ if((gid = H5I_register(H5I_GROUP, grp, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group")
+
+ /* Set up user data for callback */
+ udata.gid = gid;
+ udata.lnk_op = *lnk_op;
+ udata.op_data = op_data;
+
+ /* Call the real group iteration routine */
+ if((ret_value = H5G_obj_iterate(&(grp->oloc), idx_type, order, skip, last_lnk, H5G_iterate_cb, &udata, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "error iterating over links")
+
+done:
+ /* Release the group opened */
+ if(gid > 0) {
+ if(H5I_dec_ref(gid, TRUE) < 0)
+ HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "unable to close group")
+ } /* end if */
+ else if(grp && H5G_close(grp) < 0)
+ HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "unable to release group")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_iterate() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_free_visit_visited
+ *
+ * Purpose: Free the key for an object visited during a group traversal
+ *
+ * Return: Non-negative on success, negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Nov 4, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5G_free_visit_visited(void *item, void UNUSED *key, void UNUSED *operator_data/*in,out*/)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_free_visit_visited)
+
+ (void)H5FL_FREE(H5_obj_t, item);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5G_free_visit_visited() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_visit_cb
+ *
+ * Purpose: Callback function for recursively visiting links from a group
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Nov 4, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5G_visit_cb(const H5O_link_t *lnk, void *_udata)
+{
+ H5G_iter_visit_ud_t *udata = (H5G_iter_visit_ud_t *)_udata; /* User data for callback */
+ H5L_info_t info; /* Link info */
+ H5G_loc_t obj_loc; /* Location of object */
+ H5G_name_t obj_path; /* Object's group hier. path */
+ H5O_loc_t obj_oloc; /* Object's object location */
+ hbool_t obj_found = FALSE; /* Object at 'name' found */
+ size_t old_path_len = udata->curr_path_len; /* Length of path before appending this link's name */
+ size_t link_name_len; /* Length of link's name */
+ size_t len_needed; /* Length of path string needed */
+ herr_t ret_value = H5_ITER_CONT; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5G_visit_cb)
+
+ /* Sanity check */
+ HDassert(lnk);
+ HDassert(udata);
+
+ /* Check if we will need more space to store this link's relative path */
+ /* ("+2" is for string terminator and possible '/' for group separator later) */
+ link_name_len = HDstrlen(lnk->name);
+ len_needed = udata->curr_path_len + link_name_len + 2;
+ if(len_needed > udata->path_buf_size) {
+ void *new_path; /* Pointer to new path buffer */
+
+ /* Attempt to allocate larger buffer for path */
+ if(NULL == (new_path = H5MM_realloc(udata->path, len_needed)))
+ HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, H5_ITER_ERROR, "can't allocate path string")
+ udata->path = (char *)new_path;
+ udata->path_buf_size = len_needed;
+ } /* end if */
+
+ /* Build the link's relative path name */
+ HDassert(udata->path[old_path_len] == '\0');
+ HDstrcpy(&(udata->path[old_path_len]), lnk->name);
+ udata->curr_path_len += link_name_len;
+
+ /* Construct the link info from the link message */
+ if(H5G_link_to_info(lnk, &info) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get info for link")
+
+ /* Make the application callback */
+ ret_value = (udata->op)(udata->gid, udata->path, &info, udata->op_data);
+
+ /* Check for doing more work */
+ if(ret_value == H5_ITER_CONT && lnk->type == H5L_TYPE_HARD) {
+ H5_obj_t obj_pos; /* Object "position" for this object */
+
+ /* Set up opened group location to fill in */
+ obj_loc.oloc = &obj_oloc;
+ obj_loc.path = &obj_path;
+ H5G_loc_reset(&obj_loc);
+
+ /* Find the object using the LAPL passed in */
+ /* (Correctly handles mounted files) */
+ if(H5G_loc_find(udata->curr_loc, lnk->name, &obj_loc/*out*/, udata->lapl_id, udata->dxpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5_ITER_ERROR, "object not found")
+ obj_found = TRUE;
+
+ /* Construct unique "position" for this object */
+ H5F_GET_FILENO(obj_oloc.file, obj_pos.fileno);
+ obj_pos.addr = obj_oloc.addr;
+
+ /* Check if we've seen the object the link references before */
+ if(NULL == H5SL_search(udata->visited, &obj_pos)) {
+ H5O_type_t otype; /* Basic object type (group, dataset, etc.) */
+ unsigned rc; /* Reference count of object */
+
+ /* Get the object's reference count and type */
+ if(H5O_get_rc_and_type(&obj_oloc, udata->dxpl_id, &rc, &otype) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get object info")
+
+ /* If its ref count is > 1, we add it to the list of visited objects */
+ /* (because it could come up again during traversal) */
+ if(rc > 1) {
+ H5_obj_t *new_node; /* New object node for visited list */
+
+ /* Allocate new object "position" node */
+ if((new_node = H5FL_MALLOC(H5_obj_t)) == NULL)
+ HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, H5_ITER_ERROR, "can't allocate object node")
+
+ /* Set node information */
+ *new_node = obj_pos;
+
+ /* Add to list of visited objects */
+ if(H5SL_insert(udata->visited, new_node, new_node) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, H5_ITER_ERROR, "can't insert object node into visited list")
+ } /* end if */
+
+ /* If it's a group, we recurse into it */
+ if(otype == H5O_TYPE_GROUP) {
+ H5G_loc_t *old_loc = udata->curr_loc; /* Pointer to previous group location info */
+ H5_index_t idx_type = udata->idx_type; /* Type of index to use */
+ H5O_linfo_t linfo; /* Link info message */
+ htri_t linfo_exists; /* Whether the link info message exists */
+
+ /* Add the path separator to the current path */
+ HDassert(udata->path[udata->curr_path_len] == '\0');
+ HDstrcpy(&(udata->path[udata->curr_path_len]), "/");
+ udata->curr_path_len++;
+
+ /* Attempt to get the link info for this group */
+ if((linfo_exists = H5G_obj_get_linfo(&obj_oloc, &linfo, udata->dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "can't check for link info message")
+ if(linfo_exists) {
+ /* Check for creation order tracking, if creation order index lookup requested */
+ if(idx_type == H5_INDEX_CRT_ORDER) {
+ /* Check if creation order is tracked */
+ if(!linfo.track_corder)
+ /* Switch to name order for this group */
+ idx_type = H5_INDEX_NAME;
+ } /* end if */
+ else
+ HDassert(idx_type == H5_INDEX_NAME);
+ } /* end if */
+ else {
+ /* Can only perform name lookups on groups with symbol tables */
+ if(idx_type != H5_INDEX_NAME)
+ /* Switch to name order for this group */
+ idx_type = H5_INDEX_NAME;
+ } /* end if */
+
+ /* Point to this group's location info */
+ udata->curr_loc = &obj_loc;
+
+ /* Iterate over links in group */
+ ret_value = H5G_obj_iterate(&obj_oloc, idx_type, udata->order, (hsize_t)0, NULL, H5G_visit_cb, udata, udata->dxpl_id);
+
+ /* Restore location */
+ udata->curr_loc = old_loc;
+ } /* end if */
+ } /* end if */
+ } /* end if */
+
+done:
+ /* Reset path back to incoming path */
+ udata->path[old_path_len] = '\0';
+ udata->curr_path_len = old_path_len;
+
+ /* Release resources */
+ if(obj_found && H5G_loc_free(&obj_loc) < 0)
+ HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, H5_ITER_ERROR, "can't free location")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_visit_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_visit
+ *
+ * Purpose: Recursively visit all the links in a group and all
+ * the groups that are linked to from that group. Links within
+ * each group are visited according to the order within the
+ * specified index (unless the specified index does not exist for
+ * a particular group, then the "name" index is used).
+ *
+ * NOTE: Each _link_ reachable from the initial group will only be
+ * visited once. However, because an object may be reached from
+ * more than one link, the visitation may call the application's
+ * callback with more than one link that points to a particular
+ * _object_.
+ *
+ * Return: Success: The return value of the first operator that
+ * returns non-zero, or zero if all members were
+ * processed with no operator returning non-zero.
+ *
+ * Failure: Negative if something goes wrong within the
+ * library, or the negative value returned by one
+ * of the operators.
+ *
+ *
+ *
+ * Programmer: Quincey Koziol
+ * November 4 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_visit(hid_t loc_id, const char *group_name, H5_index_t idx_type,
+ H5_iter_order_t order, H5L_iterate_t op, void *op_data, hid_t lapl_id,
+ hid_t dxpl_id)
+{
+ H5G_iter_visit_ud_t udata; /* User data for callback */
+ H5O_linfo_t linfo; /* Link info message */
+ htri_t linfo_exists; /* Whether the link info message exists */
+ hid_t gid = (-1); /* Group ID */
+ H5G_t *grp = NULL; /* Group opened */
+ H5G_loc_t loc; /* Location of group passed in */
+ H5G_loc_t start_loc; /* Location of starting group */
+ H5O_type_t otype; /* Basic object type (group, dataset, etc.) */
+ unsigned rc; /* Reference count of object */
+ herr_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5G_visit, FAIL)
+
+ /* Check args */
+ if(H5G_loc(loc_id, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
+
+ /* Open the group to begin visiting within */
+ if((grp = H5G_open_name(&loc, group_name, lapl_id, dxpl_id)) == NULL)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group")
+
+ /* Register an ID for the starting group */
+ if((gid = H5I_register(H5I_GROUP, grp, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group")
+
+ /* Get the location of the starting group */
+ if(H5G_loc(gid, &start_loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
+
+ /* Set up user data */
+ udata.gid = gid;
+ udata.curr_loc = &start_loc;
+ udata.lapl_id = lapl_id;
+ udata.dxpl_id = dxpl_id;
+ udata.idx_type = idx_type;
+ udata.order = order;
+ udata.op = op;
+ udata.op_data = op_data;
+
+ /* Allocate space for the path name */
+ if(NULL == (udata.path = H5MM_strdup("")))
+ HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate path name buffer")
+ udata.path_buf_size = 1;
+ udata.curr_path_len = 0;
+
+ /* Create skip list to store visited object information */
+ if((udata.visited = H5SL_create(H5SL_TYPE_OBJ, 0.5, (size_t)16)) == NULL)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTCREATE, FAIL, "can't create skip list for visited objects")
+
+ /* Get the group's reference count and type */
+ if(H5O_get_rc_and_type(&grp->oloc, dxpl_id, &rc, &otype) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get object info")
+
+ /* If its ref count is > 1, we add it to the list of visited objects */
+ /* (because it could come up again during traversal) */
+ if(rc > 1) {
+ H5_obj_t *obj_pos; /* New object node for visited list */
+
+ /* Allocate new object "position" node */
+ if((obj_pos = H5FL_MALLOC(H5_obj_t)) == NULL)
+ HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate object node")
+
+ /* Construct unique "position" for this object */
+ H5F_GET_FILENO(grp->oloc.file, obj_pos->fileno);
+ obj_pos->addr = grp->oloc.addr;
+
+ /* Add to list of visited objects */
+ if(H5SL_insert(udata.visited, obj_pos, obj_pos) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "can't insert object node into visited list")
+ } /* end if */
+
+ /* Attempt to get the link info for this group */
+ if((linfo_exists = H5G_obj_get_linfo(&(grp->oloc), &linfo, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message")
+ if(linfo_exists) {
+ /* Check for creation order tracking, if creation order index lookup requested */
+ if(idx_type == H5_INDEX_CRT_ORDER) {
+ /* Check if creation order is tracked */
+ if(!linfo.track_corder)
+ /* Switch to name order for this group */
+ idx_type = H5_INDEX_NAME;
+ } /* end if */
+ else
+ HDassert(idx_type == H5_INDEX_NAME);
+ } /* end if */
+ else {
+ /* Can only perform name lookups on groups with symbol tables */
+ if(idx_type != H5_INDEX_NAME)
+ /* Switch to name order for this group */
+ idx_type = H5_INDEX_NAME;
+ } /* end if */
+
+ /* Call the link iteration routine */
+ if((ret_value = H5G_obj_iterate(&(grp->oloc), idx_type, order, (hsize_t)0, NULL, H5G_visit_cb, &udata, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't visit links")
+
+done:
+ /* Release user data resources */
+ H5MM_xfree(udata.path);
+ if(udata.visited)
+ H5SL_destroy(udata.visited, H5G_free_visit_visited, NULL);
+
+ /* Release the group opened */
+ if(gid > 0) {
+ if(H5I_dec_ref(gid, TRUE) < 0)
+ HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "unable to close group")
+ } /* end if */
+ else if(grp && H5G_close(grp) < 0)
+ HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "unable to release group")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_visit() */
+
diff --git a/src/H5Gbtree2.c b/src/H5Gbtree2.c
index 2e2f215..d060a11 100644
--- a/src/H5Gbtree2.c
+++ b/src/H5Gbtree2.c
@@ -164,7 +164,7 @@ H5G_dense_fh_name_cmp(const void *obj, size_t UNUSED obj_len, void *_udata)
FUNC_ENTER_NOAPI_NOINIT(H5G_dense_fh_name_cmp)
/* Decode link information */
- if(NULL == (lnk = H5O_msg_decode(udata->f, udata->dxpl_id, H5O_LINK_ID, obj)))
+ if(NULL == (lnk = (H5O_link_t *)H5O_msg_decode(udata->f, udata->dxpl_id, H5O_LINK_ID, (const unsigned char *)obj)))
HGOTO_ERROR(H5E_SYM, H5E_CANTDECODE, FAIL, "can't decode link")
/* Compare the string values */
diff --git a/src/H5Gcache.c b/src/H5Gcache.c
new file mode 100644
index 0000000..0e2a699
--- /dev/null
+++ b/src/H5Gcache.c
@@ -0,0 +1,470 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5Gcache.c
+ * Feb 5 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: Implement group metadata cache methods.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5G_PACKAGE /*suppress error about including H5Gpkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Gpkg.h" /* Groups */
+#include "H5MFprivate.h" /* File memory management */
+#include "H5WBprivate.h" /* Wrapped Buffers */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+#define H5G_NODE_VERS 1 /* Symbol table node version number */
+#define H5G_NODE_BUF_SIZE 512 /* Size of stack buffer for serialized nodes */
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+/* Metadata cache (H5AC) callbacks */
+static H5G_node_t *H5G_node_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_udata1,
+ void *_udata2);
+static herr_t H5G_node_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
+ H5G_node_t *sym, unsigned UNUSED * flags_ptr);
+static herr_t H5G_node_dest(H5F_t *f, H5G_node_t *sym);
+static herr_t H5G_node_clear(H5F_t *f, H5G_node_t *sym, hbool_t destroy);
+static herr_t H5G_node_size(const H5F_t *f, const H5G_node_t *sym, size_t *size_ptr);
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* Symbol table nodes inherit cache-like properties from H5AC */
+const H5AC_class_t H5AC_SNODE[1] = {{
+ H5AC_SNODE_ID,
+ (H5AC_load_func_t)H5G_node_load,
+ (H5AC_flush_func_t)H5G_node_flush,
+ (H5AC_dest_func_t)H5G_node_dest,
+ (H5AC_clear_func_t)H5G_node_clear,
+ (H5AC_size_func_t)H5G_node_size,
+}};
+
+
+/* Declare extern the free list to manage the H5G_node_t struct */
+H5FL_EXTERN(H5G_node_t);
+
+/* Declare extern the free list to manage sequences of H5G_entry_t's */
+H5FL_SEQ_EXTERN(H5G_entry_t);
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_node_load
+ *
+ * Purpose: Loads a symbol table node from the file.
+ *
+ * Return: Success: Ptr to the new table.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Jun 23 1997
+ *
+ * Modifications:
+ * Robb Matzke, 1999-07-28
+ * The ADDR argument is passed by value.
+ *
+ * Quincey Koziol, 2002-7-180
+ * Added dxpl parameter to allow more control over I/O from metadata
+ * cache.
+ *-------------------------------------------------------------------------
+ */
+static H5G_node_t *
+H5G_node_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *_udata1,
+ void UNUSED * _udata2)
+{
+ H5G_node_t *sym = NULL;
+ size_t size;
+ H5WB_t *wb = NULL; /* Wrapped buffer for node data */
+ uint8_t node_buf[H5G_NODE_BUF_SIZE]; /* Buffer for node */
+ uint8_t *node; /* Pointer to node buffer */
+ const uint8_t *p;
+ H5G_node_t *ret_value; /*for error handling */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5G_node_load)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(!_udata1);
+ HDassert(NULL == _udata2);
+
+ /*
+ * Initialize variables.
+ */
+
+ /* Wrap the local buffer for serialized node info */
+ if(NULL == (wb = H5WB_wrap(node_buf, sizeof(node_buf))))
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "can't wrap buffer")
+
+ /* Compute the size of the serialized symbol table node on disk */
+ size = H5G_node_size_real(f);
+
+ /* Get a pointer to a buffer that's large enough for node */
+ if(NULL == (node = (uint8_t *)H5WB_actual(wb, size)))
+ HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, NULL, "can't get actual buffer")
+
+ /* Read the serialized symbol table node. */
+ if(H5F_block_read(f, H5FD_MEM_BTREE, addr, size, dxpl_id, node) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_READERROR, NULL, "unable to read symbol table node")
+
+ /* Get temporary pointer to serialized node */
+ p = node;
+
+ /* magic */
+ if(HDmemcmp(p, H5G_NODE_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, NULL, "bad symbol table node signature")
+ p += 4;
+
+ /* version */
+ if(H5G_NODE_VERS != *p++)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, NULL, "bad symbol table node version")
+
+ /* reserved */
+ p++;
+
+ /* Allocate symbol table data structures */
+ if(NULL == (sym = H5FL_CALLOC(H5G_node_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ if(NULL == (sym->entry = H5FL_SEQ_CALLOC(H5G_entry_t, (size_t)(2 * H5F_SYM_LEAF_K(f)))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+
+ /* number of symbols */
+ UINT16DECODE(p, sym->nsyms);
+
+ /* entries */
+ if(H5G_ent_decode_vec(f, &p, sym->entry, sym->nsyms) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, NULL, "unable to decode symbol table entries")
+
+ /* Set return value */
+ ret_value = sym;
+
+done:
+ /* Release resources */
+ if(wb && H5WB_unwrap(wb) < 0)
+ HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, NULL, "can't close wrapped buffer")
+ if(!ret_value)
+ if(sym && H5G_node_dest(f, sym) < 0)
+ HDONE_ERROR(H5E_SYM, H5E_CANTFREE, NULL, "unable to destroy symbol table node")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_node_load() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_node_flush
+ *
+ * Purpose: Flush a symbol table node to disk.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Jun 23 1997
+ *
+ * Modifications:
+ * rky, 1998-08-28
+ * Only p0 writes metadata to disk.
+ *
+ * Robb Matzke, 1999-07-28
+ * The ADDR argument is passed by value.
+ *
+ * Quincey Koziol, 2002-7-180
+ * Added dxpl parameter to allow more control over I/O from metadata
+ * cache.
+ *
+ * Pedro Vicente, <pvn@ncsa.uiuc.edu> 18 Sep 2002
+ * Added `id to name' support.
+ *
+ * JRM -- 8/21/06
+ * Added the flags_ptr parameter. This parameter exists to
+ * allow the flush routine to report to the cache if the
+ * entry is resized or renamed as a result of the flush.
+ * *flags_ptr is set to H5C_CALLBACK__NO_FLAGS_SET on entry.
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5G_node_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5G_node_t *sym, unsigned UNUSED * flags_ptr)
+{
+ H5WB_t *wb = NULL; /* Wrapped buffer for node data */
+ uint8_t node_buf[H5G_NODE_BUF_SIZE]; /* Buffer for node */
+ unsigned u;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5G_node_flush)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(sym);
+
+ /*
+ * Look for dirty entries and set the node dirty flag.
+ */
+ for(u = 0; u < sym->nsyms; u++)
+ if(sym->entry[u].dirty) {
+ /* Set the node's dirty flag */
+ sym->cache_info.is_dirty = TRUE;
+
+ /* Reset the entry's dirty flag */
+ sym->entry[u].dirty = FALSE;
+ } /* end if */
+
+ /*
+ * Write the symbol node to disk.
+ */
+ if(sym->cache_info.is_dirty) {
+ uint8_t *node; /* Pointer to node buffer */
+ uint8_t *p; /* Pointer into raw data buffer */
+ size_t size;
+
+ /* Wrap the local buffer for serialized node info */
+ if(NULL == (wb = H5WB_wrap(node_buf, sizeof(node_buf))))
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't wrap buffer")
+
+ /* Compute the size of the serialized symbol table node on disk */
+ size = H5G_node_size_real(f);
+
+ /* Get a pointer to a buffer that's large enough for node */
+ if(NULL == (node = (uint8_t *)H5WB_actual(wb, size)))
+ HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't get actual buffer")
+
+ /* Get temporary pointer to serialized symbol table node */
+ p = node;
+
+ /* magic number */
+ HDmemcpy(p, H5G_NODE_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ p += 4;
+
+ /* version number */
+ *p++ = H5G_NODE_VERS;
+
+ /* reserved */
+ *p++ = 0;
+
+ /* number of symbols */
+ UINT16ENCODE(p, sym->nsyms);
+
+ /* entries */
+ if(H5G_ent_encode_vec(f, &p, sym->entry, sym->nsyms) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTENCODE, FAIL, "can't serialize")
+ HDmemset(p, 0, size - (p - node));
+
+ /* Write the serialized symbol table node. */
+ if(H5F_block_write(f, H5FD_MEM_BTREE, addr, size, dxpl_id, node) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_WRITEERROR, FAIL, "unable to write symbol table node to the file")
+
+ /* Reset the node's dirty flag */
+ sym->cache_info.is_dirty = FALSE;
+ } /* end if */
+
+ /*
+ * Destroy the symbol node? This might happen if the node is being
+ * preempted from the cache.
+ */
+ if(destroy)
+ if(H5G_node_dest(f, sym) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to destroy symbol table node")
+
+done:
+ /* Release resources */
+ if(wb && H5WB_unwrap(wb) < 0)
+ HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close wrapped buffer")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_node_flush() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_node_dest
+ *
+ * Purpose: Destroy a symbol table node in memory.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Jan 15 2003
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_node_dest(H5F_t *f, H5G_node_t *sym)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5G_node_dest)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(sym);
+
+ /* Verify that node is clean */
+ HDassert(sym->cache_info.is_dirty == FALSE);
+
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!sym->cache_info.free_file_space_on_destroy || H5F_addr_defined(sym->cache_info.addr));
+
+ /* Check for freeing file space for symbol table node */
+ if(sym->cache_info.free_file_space_on_destroy) {
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_BTREE, H5AC_dxpl_id, sym->cache_info.addr, (hsize_t)H5G_node_size_real(f)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to free symbol table node")
+ } /* end if */
+
+ /* Release resources */
+ if(sym->entry)
+ sym->entry = (H5G_entry_t *)H5FL_SEQ_FREE(H5G_entry_t, sym->entry);
+ (void)H5FL_FREE(H5G_node_t, sym);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_node_dest() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_node_clear
+ *
+ * Purpose: Mark a symbol table node in memory as non-dirty.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Mar 20 2003
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5G_node_clear(H5F_t *f, H5G_node_t *sym, hbool_t destroy)
+{
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT(H5G_node_clear);
+
+ /*
+ * Check arguments.
+ */
+ assert(sym);
+
+ /* Look for dirty entries and reset their dirty flag. */
+ for(u = 0; u < sym->nsyms; u++)
+ sym->entry[u].dirty=FALSE;
+ sym->cache_info.is_dirty = FALSE;
+
+ /*
+ * Destroy the symbol node? This might happen if the node is being
+ * preempted from the cache.
+ */
+ if (destroy)
+ if (H5G_node_dest(f, sym) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to destroy symbol table node");
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5G_node_clear() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_node_size
+ *
+ * Purpose: Compute the size in bytes of the specified instance of
+ * H5G_node_t on disk, and return it in *size_ptr. On failure
+ * the value of size_ptr is undefined.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 5/13/04
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5G_node_size(const H5F_t *f, const H5G_node_t UNUSED *sym, size_t *size_ptr)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_node_size);
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(size_ptr);
+
+ *size_ptr = H5G_node_size_real(f);
+
+ FUNC_LEAVE_NOAPI(SUCCEED);
+} /* H5G_node_size() */
+
diff --git a/src/H5Gcompact.c b/src/H5Gcompact.c
index 042d29a..9ecd6c1 100644
--- a/src/H5Gcompact.c
+++ b/src/H5Gcompact.c
@@ -145,7 +145,7 @@ H5G_compact_build_table(const H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t
H5O_mesg_operator_t op; /* Message operator */
/* Allocate the link table */
- if((ltable->lnks = H5MM_malloc(sizeof(H5O_link_t) * ltable->nlinks)) == NULL)
+ if((ltable->lnks = (H5O_link_t *)H5MM_malloc(sizeof(H5O_link_t) * ltable->nlinks)) == NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Set up user data for iteration */
@@ -406,9 +406,9 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5G_compact_iterate(H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *linfo,
+H5G_compact_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *linfo,
H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk,
- hid_t gid, H5G_link_iterate_t *lnk_op, void *op_data)
+ H5G_lib_iterate_t op, void *op_data)
{
H5G_link_table_t ltable = {0, NULL}; /* Link table */
herr_t ret_value; /* Return value */
@@ -418,14 +418,14 @@ H5G_compact_iterate(H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *linfo,
/* Sanity check */
HDassert(oloc);
HDassert(linfo);
- HDassert(lnk_op && lnk_op->u.lib_op);
+ HDassert(op);
/* Build table of all link messages */
if(H5G_compact_build_table(oloc, dxpl_id, linfo, idx_type, order, &ltable) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create link message table")
/* Iterate over links in table */
- if((ret_value = H5G_link_iterate_table(&ltable, skip, last_lnk, gid, lnk_op, op_data)) < 0)
+ if((ret_value = H5G_link_iterate_table(&ltable, skip, last_lnk, op, op_data)) < 0)
HERROR(H5E_SYM, H5E_CANTNEXT, "iteration operator failed");
done:
@@ -489,7 +489,7 @@ done:
*
* Purpose: Look up an object relative to a group, using link messages.
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative (TRUE/FALSE) on success/Negative on failure
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
@@ -497,13 +497,13 @@ done:
*
*-------------------------------------------------------------------------
*/
-herr_t
+htri_t
H5G_compact_lookup(H5O_loc_t *oloc, const char *name, H5O_link_t *lnk,
hid_t dxpl_id)
{
H5G_iter_lkp_t udata; /* User data for iteration callback */
H5O_mesg_operator_t op; /* Message operator */
- herr_t ret_value = SUCCEED; /* Return value */
+ htri_t ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5G_compact_lookup, FAIL)
@@ -522,9 +522,8 @@ H5G_compact_lookup(H5O_loc_t *oloc, const char *name, H5O_link_t *lnk,
if(H5O_msg_iterate(oloc, H5O_LINK_ID, &op, &udata, dxpl_id) < 0)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "error iterating over link messages")
- /* Check if we found the link we were looking for */
- if(!udata.found)
- HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found")
+ /* Determine if we found the link we were looking for */
+ ret_value = udata.found;
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5Gdense.c b/src/H5Gdense.c
index 2b7493b..6c3a171 100644
--- a/src/H5Gdense.c
+++ b/src/H5Gdense.c
@@ -90,9 +90,8 @@ typedef struct {
hsize_t count; /* # of links examined */
/* downward (from application) */
- hid_t gid; /* Group ID for application callback */
hsize_t skip; /* Number of links to skip */
- const H5G_link_iterate_t *lnk_op; /* Callback for each link */
+ H5G_lib_iterate_t op; /* Callback for each link */
void *op_data; /* Callback data for each link */
/* upward */
@@ -404,7 +403,7 @@ HDfprintf(stderr, "%s: HDstrlen(lnk->name) = %Zu, link_size = %Zu\n", FUNC, HDst
HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't get actual buffer")
/* Create serialized form of link */
- if(H5O_msg_encode(f, H5O_LINK_ID, FALSE, link_ptr, lnk) < 0)
+ if(H5O_msg_encode(f, H5O_LINK_ID, FALSE, (unsigned char *)link_ptr, lnk) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTENCODE, FAIL, "can't encode link")
/* Open the fractal heap */
@@ -491,7 +490,7 @@ done:
*
* Purpose: Look up a link within a group that uses dense link storage
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative (TRUE/FALSE) on success/Negative on failure
*
* Programmer: Quincey Koziol
* koziol@hdfgroup.org
@@ -499,13 +498,13 @@ done:
*
*-------------------------------------------------------------------------
*/
-herr_t
+htri_t
H5G_dense_lookup(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo,
const char *name, H5O_link_t *lnk)
{
H5G_bt2_ud_common_t udata; /* User data for v2 B-tree link lookup */
H5HF_t *fheap = NULL; /* Fractal heap handle */
- herr_t ret_value = SUCCEED; /* Return value */
+ htri_t ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5G_dense_lookup, FAIL)
@@ -531,7 +530,7 @@ H5G_dense_lookup(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo,
udata.found_op_data = lnk;
/* Find & copy the named link in the 'name' index */
- if(H5B2_find(f, dxpl_id, H5G_BT2_NAME, linfo->name_bt2_addr, &udata, NULL, NULL) < 0)
+ if((ret_value = H5B2_find(f, dxpl_id, H5G_BT2_NAME, linfo->name_bt2_addr, &udata, NULL, NULL)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to locate link in name index")
done:
@@ -567,7 +566,7 @@ H5G_dense_lookup_by_idx_fh_cb(const void *obj, size_t UNUSED obj_len, void *_uda
FUNC_ENTER_NOAPI_NOINIT(H5G_dense_lookup_by_idx_fh_cb)
/* Decode link information & keep a copy */
- if(NULL == (tmp_lnk = H5O_msg_decode(udata->f, udata->dxpl_id, H5O_LINK_ID, obj)))
+ if(NULL == (tmp_lnk = (H5O_link_t *)H5O_msg_decode(udata->f, udata->dxpl_id, H5O_LINK_ID, (const unsigned char *)obj)))
HGOTO_ERROR(H5E_SYM, H5E_CANTDECODE, FAIL, "can't decode link")
/* Copy link information */
@@ -799,22 +798,17 @@ H5G_dense_build_table(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo,
/* Allocate space for the table entries */
if(ltable->nlinks > 0) {
H5G_dense_bt_ud_t udata; /* User data for iteration callback */
- H5G_link_iterate_t lnk_op; /* Link operator */
/* Allocate the table to store the links */
- if((ltable->lnks = H5MM_malloc(sizeof(H5O_link_t) * ltable->nlinks)) == NULL)
+ if((ltable->lnks = (H5O_link_t *)H5MM_malloc(sizeof(H5O_link_t) * ltable->nlinks)) == NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Set up user data for iteration */
udata.ltable = ltable;
udata.curr_lnk = 0;
- /* Build iterator operator */
- lnk_op.op_type = H5G_LINK_OP_LIB;
- lnk_op.u.lib_op = H5G_dense_build_table_cb;
-
/* Iterate over the links in the group, building a table of the link messages */
- if(H5G_dense_iterate(f, dxpl_id, linfo, H5_INDEX_NAME, H5_ITER_NATIVE, (hsize_t)0, NULL, (hid_t)0, &lnk_op, &udata) < 0)
+ if(H5G_dense_iterate(f, dxpl_id, linfo, H5_INDEX_NAME, H5_ITER_NATIVE, (hsize_t)0, NULL, H5G_dense_build_table_cb, &udata) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTNEXT, FAIL, "error iterating over links")
/* Sort link table in correct iteration order */
@@ -858,7 +852,7 @@ H5G_dense_iterate_fh_cb(const void *obj, size_t UNUSED obj_len, void *_udata)
* HDF5 routine, it could attempt to re-protect that direct block for the
* heap, causing the HDF5 routine called to fail - QAK)
*/
- if(NULL == (udata->lnk = H5O_msg_decode(udata->f, udata->dxpl_id, H5O_LINK_ID, obj)))
+ if(NULL == (udata->lnk = (H5O_link_t *)H5O_msg_decode(udata->f, udata->dxpl_id, H5O_LINK_ID, (const unsigned char *)obj)))
HGOTO_ERROR(H5E_SYM, H5E_CANTDECODE, FAIL, "can't decode link")
done:
@@ -904,32 +898,8 @@ H5G_dense_iterate_bt2_cb(const void *_record, void *_bt2_udata)
H5G_dense_iterate_fh_cb, &fh_udata) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTOPERATE, H5_ITER_ERROR, "heap op callback failed")
- /* Check which type of callback to make */
- switch(bt2_udata->lnk_op->op_type) {
-#ifndef H5_NO_DEPRECATED_SYMBOLS
- case H5G_LINK_OP_OLD:
- /* Make the old-type application callback */
- ret_value = (bt2_udata->lnk_op->u.old_op)(bt2_udata->gid, fh_udata.lnk->name, bt2_udata->op_data);
- break;
-#endif /* H5_NO_DEPRECATED_SYMBOLS */
-
- case H5G_LINK_OP_APP:
- {
- H5L_info_t info; /* Link info */
-
- /* Retrieve the info for the link */
- if(H5G_link_to_info(fh_udata.lnk, &info) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get info for link")
-
- /* Make the application callback */
- ret_value = (bt2_udata->lnk_op->u.app_op)(bt2_udata->gid, fh_udata.lnk->name, &info, bt2_udata->op_data);
- }
- break;
-
- case H5G_LINK_OP_LIB:
- /* Call the library's callback */
- ret_value = (bt2_udata->lnk_op->u.lib_op)(fh_udata.lnk, bt2_udata->op_data);
- } /* end switch */
+ /* Make the callback */
+ ret_value = (bt2_udata->op)(fh_udata.lnk, bt2_udata->op_data);
/* Release the space allocated for the link */
H5O_msg_free(H5O_LINK_ID, fh_udata.lnk);
@@ -964,7 +934,7 @@ done:
herr_t
H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo,
H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk,
- hid_t gid, const H5G_link_iterate_t *lnk_op, void *op_data)
+ H5G_lib_iterate_t op, void *op_data)
{
H5HF_t *fheap = NULL; /* Fractal heap handle */
H5G_link_table_t ltable = {0, NULL}; /* Table of links */
@@ -979,7 +949,7 @@ H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo,
*/
HDassert(f);
HDassert(linfo);
- HDassert(lnk_op && lnk_op->u.lib_op);
+ HDassert(op);
/* Determine the address of the index to use */
if(idx_type == H5_INDEX_NAME) {
@@ -1018,10 +988,9 @@ H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo,
udata.f = f;
udata.dxpl_id = dxpl_id;
udata.fheap = fheap;
- udata.gid = gid;
udata.skip = skip;
udata.count = 0;
- udata.lnk_op = lnk_op;
+ udata.op = op;
udata.op_data = op_data;
/* Iterate over the records in the v2 B-tree's "native" order */
@@ -1039,7 +1008,7 @@ H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo,
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "error building table of links")
/* Iterate over links in table */
- if((ret_value = H5G_link_iterate_table(&ltable, skip, last_lnk, gid, lnk_op, op_data)) < 0)
+ if((ret_value = H5G_link_iterate_table(&ltable, skip, last_lnk, op, op_data)) < 0)
HERROR(H5E_SYM, H5E_CANTNEXT, "iteration operator failed");
} /* end else */
@@ -1078,7 +1047,7 @@ H5G_dense_get_name_by_idx_fh_cb(const void *obj, size_t UNUSED obj_len, void *_u
FUNC_ENTER_NOAPI_NOINIT(H5G_dense_get_name_by_idx_fh_cb)
/* Decode link information */
- if(NULL == (lnk = H5O_msg_decode(udata->f, udata->dxpl_id, H5O_LINK_ID, obj)))
+ if(NULL == (lnk = (H5O_link_t *)H5O_msg_decode(udata->f, udata->dxpl_id, H5O_LINK_ID, (const unsigned char *)obj)))
HGOTO_ERROR(H5E_SYM, H5E_CANTDECODE, FAIL, "can't decode link")
/* Get the length of the name */
@@ -1276,7 +1245,7 @@ H5G_dense_remove_fh_cb(const void *obj, size_t UNUSED obj_len, void *_udata)
FUNC_ENTER_NOAPI_NOINIT(H5G_dense_remove_fh_cb)
/* Decode link information */
- if(NULL == (lnk = H5O_msg_decode(udata->f, udata->dxpl_id, H5O_LINK_ID, obj)))
+ if(NULL == (lnk = (H5O_link_t *)H5O_msg_decode(udata->f, udata->dxpl_id, H5O_LINK_ID, (const unsigned char *)obj)))
HGOTO_ERROR(H5E_SYM, H5E_CANTDECODE, FAIL, "can't decode link")
/* Check for removing the link from the creation order index */
@@ -1439,7 +1408,7 @@ H5G_dense_remove_by_idx_fh_cb(const void *obj, size_t UNUSED obj_len, void *_uda
FUNC_ENTER_NOAPI_NOINIT(H5G_dense_remove_by_idx_fh_cb)
/* Decode link information */
- if(NULL == (udata->lnk = H5O_msg_decode(udata->f, udata->dxpl_id, H5O_LINK_ID, obj)))
+ if(NULL == (udata->lnk = (H5O_link_t *)H5O_msg_decode(udata->f, udata->dxpl_id, H5O_LINK_ID, (const unsigned char *)obj)))
HGOTO_ERROR(H5E_SYM, H5E_CANTDECODE, H5_ITER_ERROR, "can't decode link")
/* Can't operate on link here because the fractal heap block is locked */
diff --git a/src/H5Gdeprec.c b/src/H5Gdeprec.c
index 52b607d..ddb5dfe 100644
--- a/src/H5Gdeprec.c
+++ b/src/H5Gdeprec.c
@@ -218,15 +218,15 @@ H5Gcreate1(hid_t loc_id, const char *name, size_t size_hint)
H5O_ginfo_t ginfo; /* Group info property */
/* Get the default property list */
- if(NULL == (gc_plist = H5I_object(H5P_GROUP_CREATE_DEFAULT)))
+ if(NULL == (gc_plist = (H5P_genplist_t *)H5I_object(H5P_GROUP_CREATE_DEFAULT)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
/* Make a copy of the default property list */
- if((tmp_gcpl = H5P_copy_plist(gc_plist)) < 0)
+ if((tmp_gcpl = H5P_copy_plist(gc_plist, FALSE)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to copy the creation property list")
/* Get pointer to the copied property list */
- if(NULL == (gc_plist = H5I_object(tmp_gcpl)))
+ if(NULL == (gc_plist = (H5P_genplist_t *)H5I_object(tmp_gcpl)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
/* Get the group info property */
@@ -245,12 +245,12 @@ H5Gcreate1(hid_t loc_id, const char *name, size_t size_hint)
if(NULL == (grp = H5G_create_named(&loc, name, H5P_LINK_CREATE_DEFAULT,
tmp_gcpl, H5P_GROUP_ACCESS_DEFAULT, H5AC_dxpl_id)))
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create group")
- if((ret_value = H5I_register(H5I_GROUP, grp)) < 0)
+ if((ret_value = H5I_register(H5I_GROUP, grp, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group")
done:
if(tmp_gcpl > 0 && tmp_gcpl != H5P_GROUP_CREATE_DEFAULT)
- if(H5I_dec_ref(tmp_gcpl) < 0)
+ if(H5I_dec_ref(tmp_gcpl, TRUE) < 0)
HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "unable to release property list")
if(ret_value < 0)
@@ -299,7 +299,7 @@ H5Gopen1(hid_t loc_id, const char *name)
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group")
/* Register an atom for the group */
- if((ret_value = H5I_register(H5I_GROUP, grp)) < 0)
+ if((ret_value = H5I_register(H5I_GROUP, grp, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group")
done:
@@ -770,10 +770,10 @@ H5Giterate(hid_t loc_id, const char *name, int *idx_p, H5G_iterate_t op,
/* Build link operator info */
lnk_op.op_type = H5G_LINK_OP_OLD;
- lnk_op.u.old_op = op;
+ lnk_op.op_func.op_old = op;
/* Call private function. */
- if((ret_value = H5G_obj_iterate(loc_id, name, H5_INDEX_NAME, H5_ITER_INC, idx, &last_obj, &lnk_op, op_data, H5P_DEFAULT, H5AC_ind_dxpl_id)) < 0)
+ if((ret_value = H5G_iterate(loc_id, name, H5_INDEX_NAME, H5_ITER_INC, idx, &last_obj, &lnk_op, op_data, H5P_DEFAULT, H5AC_ind_dxpl_id)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "group iteration failed")
/* Set the index we stopped at */
@@ -1104,13 +1104,13 @@ H5Gget_objtype_by_idx(hid_t loc_id, hsize_t idx)
if(H5G_loc(loc_id, &loc) < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "not a location ID")
if(H5O_obj_type(loc.oloc, &obj_type, H5AC_ind_dxpl_id) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get object type")
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5G_UNKNOWN, "can't get object type")
if(obj_type != H5O_TYPE_GROUP)
- HGOTO_ERROR(H5E_SYM, H5E_BADTYPE, FAIL, "not a group")
+ HGOTO_ERROR(H5E_SYM, H5E_BADTYPE, H5G_UNKNOWN, "not a group")
/* Call internal function*/
if((ret_value = H5G_obj_get_type_by_idx(loc.oloc, idx, H5AC_ind_dxpl_id)) == H5G_UNKNOWN)
- HGOTO_ERROR(H5E_SYM, H5E_BADTYPE, FAIL, "can't get object type")
+ HGOTO_ERROR(H5E_SYM, H5E_BADTYPE, H5G_UNKNOWN, "can't get object type")
done:
FUNC_LEAVE_API(ret_value)
@@ -1136,6 +1136,7 @@ static H5G_obj_t
H5G_obj_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx, hid_t dxpl_id)
{
H5O_linfo_t linfo; /* Link info message */
+ htri_t linfo_exists; /* Whether the link info message exists */
H5G_obj_t ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5G_obj_get_type_by_idx, H5G_UNKNOWN)
@@ -1144,7 +1145,9 @@ H5G_obj_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx, hid_t dxpl_id)
HDassert(oloc);
/* Attempt to get the link info for this group */
- if(H5G_obj_get_linfo(oloc, &linfo, dxpl_id)) {
+ if((linfo_exists = H5G_obj_get_linfo(oloc, &linfo, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5G_UNKNOWN, "can't check for link info message")
+ if(linfo_exists) {
if(H5F_addr_defined(linfo.fheap_addr)) {
/* Get the object's name from the dense link storage */
if((ret_value = H5G_dense_get_type_by_idx(oloc->file, dxpl_id, &linfo, idx)) < 0)
@@ -1157,9 +1160,6 @@ H5G_obj_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx, hid_t dxpl_id)
} /* end else */
} /* end if */
else {
- /* Clear error stack from not finding the link info message */
- H5E_clear_stack(NULL);
-
/* Get the object's type from the symbol table */
if((ret_value = H5G_stab_get_type_by_idx(oloc, idx, dxpl_id)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5G_UNKNOWN, "can't locate type")
diff --git a/src/H5Gent.c b/src/H5Gent.c
index e7be62f..7a9e9e5 100644
--- a/src/H5Gent.c
+++ b/src/H5Gent.c
@@ -494,7 +494,7 @@ H5G_ent_debug(H5F_t UNUSED *f, const H5G_entry_t *ent, FILE *stream,
"Link value offset:",
(unsigned long)(ent->cache.slink.lval_offset));
if(heap) {
- lval = H5HL_offset_into(ent->file, heap, ent->cache.slink.lval_offset);
+ lval = (const char *)H5HL_offset_into(ent->file, heap, ent->cache.slink.lval_offset);
HDfprintf(stream, "%*s%-*s %s\n", nested_indent, "", nested_fwidth,
"Link value:",
lval);
diff --git a/src/H5Glink.c b/src/H5Glink.c
index 7292245..9527521 100644
--- a/src/H5Glink.c
+++ b/src/H5Glink.c
@@ -240,7 +240,7 @@ H5G_ent_to_link(H5F_t *f, H5O_link_t *lnk, const H5HL_t *heap,
if(ent->type == H5G_CACHED_SLINK) {
const char *s; /* Pointer to link value */
- s = H5HL_offset_into(f, heap, ent->cache.slink.lval_offset);
+ s = (const char *)H5HL_offset_into(f, heap, ent->cache.slink.lval_offset);
HDassert(s);
/* Copy the link value */
@@ -295,7 +295,7 @@ H5G_ent_to_info(H5F_t *f, H5L_info_t *info, const H5HL_t *heap,
if(ent->type == H5G_CACHED_SLINK) {
const char *s; /* Pointer to link value */
- s = H5HL_offset_into(f, heap, ent->cache.slink.lval_offset);
+ s = (const char *)H5HL_offset_into(f, heap, ent->cache.slink.lval_offset);
HDassert(s);
/* Get the link value size */
@@ -319,7 +319,7 @@ H5G_ent_to_info(H5F_t *f, H5L_info_t *info, const H5HL_t *heap,
/*-------------------------------------------------------------------------
* Function: H5G_link_to_info
*
- * Purpose: Retrieve information from a link object
+ * Purpose: Retrieve information from a link object
*
* Return: Non-negative on success/Negative on failure
*
@@ -392,7 +392,7 @@ done:
/*-------------------------------------------------------------------------
* Function: H5G_link_to_loc
*
- * Purpose: Build group location from group and link object
+ * Purpose: Build group location from group and link object
*
* Return: Non-negative on success/Negative on failure
*
@@ -486,7 +486,7 @@ H5G_link_copy_file(H5F_t *dst_file, hid_t dxpl_id, const H5O_link_t *_src_lnk,
/* Check if the object pointed by the soft link exists in the source file */
if(H5G_loc_info(&grp_loc, tmp_src_lnk.u.soft.name, FALSE, &oinfo, H5P_DEFAULT, dxpl_id) >= 0) {
/* Convert soft link to hard link */
- tmp_src_lnk.u.soft.name = H5MM_xfree(tmp_src_lnk.u.soft.name);
+ tmp_src_lnk.u.soft.name = (char *)H5MM_xfree(tmp_src_lnk.u.soft.name);
tmp_src_lnk.type = H5L_TYPE_HARD;
tmp_src_lnk.u.hard.addr = oinfo.addr;
src_lnk = &tmp_src_lnk;
@@ -603,7 +603,7 @@ H5G_link_sort_table(H5G_link_table_t *ltable, H5_index_t idx_type,
*/
herr_t
H5G_link_iterate_table(const H5G_link_table_t *ltable, hsize_t skip,
- hsize_t *last_lnk, hid_t gid, const H5G_link_iterate_t *lnk_op, void *op_data)
+ hsize_t *last_lnk, const H5G_lib_iterate_t op, void *op_data)
{
size_t u; /* Local index variable */
herr_t ret_value = H5_ITER_CONT; /* Return value */
@@ -612,7 +612,7 @@ H5G_link_iterate_table(const H5G_link_table_t *ltable, hsize_t skip,
/* Sanity check */
HDassert(ltable);
- HDassert(lnk_op);
+ HDassert(op);
/* Skip over links, if requested */
if(last_lnk)
@@ -621,32 +621,8 @@ H5G_link_iterate_table(const H5G_link_table_t *ltable, hsize_t skip,
/* Iterate over link messages */
H5_ASSIGN_OVERFLOW(/* To: */ u, /* From: */ skip, /* From: */ hsize_t, /* To: */ size_t)
for(; u < ltable->nlinks && !ret_value; u++) {
- /* Check which kind of callback to make */
- switch(lnk_op->op_type) {
-#ifndef H5_NO_DEPRECATED_SYMBOLS
- case H5G_LINK_OP_OLD:
- /* Make the old-type application callback */
- ret_value = (lnk_op->u.old_op)(gid, ltable->lnks[u].name, op_data);
- break;
-#endif /* H5_NO_DEPRECATED_SYMBOLS */
-
- case H5G_LINK_OP_APP:
- {
- H5L_info_t info; /* Link info */
-
- /* Retrieve the info for the link */
- if(H5G_link_to_info(&(ltable->lnks[u]), &info) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get info for link")
-
- /* Make the application callback */
- ret_value = (lnk_op->u.app_op)(gid, ltable->lnks[u].name, &info, op_data);
- }
- break;
-
- case H5G_LINK_OP_LIB:
- /* Call the library's callback */
- ret_value = (lnk_op->u.lib_op)(&(ltable->lnks[u]), op_data);
- } /* end switch */
+ /* Make the callback */
+ ret_value = (op)(&(ltable->lnks[u]), op_data);
/* Increment the number of entries passed through */
if(last_lnk)
@@ -657,7 +633,6 @@ H5G_link_iterate_table(const H5G_link_table_t *ltable, hsize_t skip,
if(ret_value < 0)
HERROR(H5E_SYM, H5E_CANTNEXT, "iteration operator failed");
-done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5G_link_iterate_table() */
diff --git a/src/H5Gloc.c b/src/H5Gloc.c
index fc02539..908c9a3 100644
--- a/src/H5Gloc.c
+++ b/src/H5Gloc.c
@@ -161,7 +161,7 @@ H5G_loc(hid_t loc_id, H5G_loc_t *loc)
H5F_t *f;
/* Get the file struct */
- if(NULL == (f = H5I_object(loc_id)))
+ if(NULL == (f = (H5F_t *)H5I_object(loc_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file ID")
/* Construct a group location for root group of the file */
@@ -183,7 +183,7 @@ H5G_loc(hid_t loc_id, H5G_loc_t *loc)
{
H5G_t *group;
- if(NULL == (group = H5I_object(loc_id)))
+ if(NULL == (group = (H5G_t *)H5I_object(loc_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid group ID")
if(NULL == (loc->oloc = H5G_oloc(group)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location of group")
@@ -196,7 +196,7 @@ H5G_loc(hid_t loc_id, H5G_loc_t *loc)
{
H5T_t *dt;
- if(NULL == (dt = H5I_object(loc_id)))
+ if(NULL == (dt = (H5T_t *)H5I_object(loc_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid type ID")
if(NULL == (loc->oloc = H5T_oloc(dt)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location of datatype")
@@ -212,7 +212,7 @@ H5G_loc(hid_t loc_id, H5G_loc_t *loc)
{
H5D_t *dset;
- if(NULL == (dset = H5I_object(loc_id)))
+ if(NULL == (dset = (H5D_t *)H5I_object(loc_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid data ID")
if(NULL == (loc->oloc = H5D_oloc(dset)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location of dataset")
@@ -225,7 +225,7 @@ H5G_loc(hid_t loc_id, H5G_loc_t *loc)
{
H5A_t *attr;
- if(NULL == (attr = H5I_object(loc_id)))
+ if(NULL == (attr = (H5A_t *)H5I_object(loc_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid attribute ID")
if(NULL == (loc->oloc = H5A_oloc(attr)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location of attribute")
diff --git a/src/H5Gname.c b/src/H5Gname.c
index e341ee7..0634aef 100644
--- a/src/H5Gname.c
+++ b/src/H5Gname.c
@@ -50,21 +50,15 @@ typedef struct H5G_names_t {
} H5G_names_t;
/* Info to pass to the iteration function when building name */
-typedef struct H5G_ref_path_iter_t {
+typedef struct H5G_gnba_iter_t {
/* In */
- hid_t file; /* File id where it came from */
+ const H5O_loc_t *loc; /* The location of the object we're looking for */
hid_t lapl_id; /* LAPL for operations */
hid_t dxpl_id; /* DXPL for operations */
- hbool_t is_root_group; /* Flag to indicate that the root group is being looked at */
- const H5O_loc_t *loc; /* The location of the object we're looking for */
-
- /* In/Out */
- H5SL_t *ref_path_table; /* Skip list for tracking visited nodes */
- size_t max_container_len; /* Maximum size of container */
/* Out */
- char *container; /* full name of the container object */
-} H5G_ref_path_iter_t;
+ char *path; /* Name of the object */
+} H5G_gnba_iter_t;
/* Private macros */
@@ -73,9 +67,6 @@ typedef struct H5G_ref_path_iter_t {
/* Declare extern the PQ free list for the wrapped strings */
H5FL_BLK_EXTERN(str_buf);
-/* Declare the free list to manage haddr_t's */
-H5FL_DEFINE_STATIC(haddr_t);
-
/* PRIVATE PROTOTYPES */
static htri_t H5G_common_path(const H5RS_str_t *fullpath_r, const H5RS_str_t *prefix_r);
static H5RS_str_t *H5G_build_fullpath(const char *prefix, const char *name);
@@ -85,9 +76,6 @@ static H5RS_str_t *H5G_build_fullpath_refstr_refstr(const H5RS_str_t *prefix_r,
static herr_t H5G_name_move_path(H5RS_str_t **path_r_ptr,
const char *full_suffix, const char *src_path, const char *dst_path);
static int H5G_name_replace_cb(void *obj_ptr, hid_t obj_id, void *key);
-static herr_t H5G_refname_iterator(hid_t group, const char *name,
- const H5L_info_t *link_info, void *_udata);
-static herr_t H5G_free_ref_path_node(void *item, void *key, void *operator_data/*in,out*/);
/*-------------------------------------------------------------------------
@@ -464,17 +452,17 @@ H5G_get_name(hid_t id, char *name/*out*/, size_t size, hid_t lapl_id,
hid_t file;
/* Retrieve file ID for name search */
- if((file = H5I_get_file_id(id)) < 0)
+ if((file = H5I_get_file_id(id, FALSE)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve file ID")
/* Search for name of object */
- if((len = H5G_get_refobj_name(file, lapl_id, dxpl_id, loc.oloc, name, size)) < 0) {
- H5I_dec_ref(file);
+ if((len = H5G_get_name_by_addr(file, lapl_id, dxpl_id, loc.oloc, name, size)) < 0) {
+ H5I_dec_ref(file, FALSE);
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't determine name")
} /* end if */
-
+
/* Close file ID used for search */
- if(H5I_dec_ref(file) < 0)
+ if(H5I_dec_ref(file, FALSE) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTCLOSEFILE, FAIL, "can't determine name")
} /* end else */
@@ -482,7 +470,7 @@ H5G_get_name(hid_t id, char *name/*out*/, size_t size, hid_t lapl_id,
ret_value = len;
} /* end if */
-done:
+done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5G_get_name() */
@@ -712,19 +700,19 @@ H5G_name_replace_cb(void *obj_ptr, hid_t obj_id, void *key)
HGOTO_DONE(SUCCEED) /* No need to look at object, it's path is already invalid */
/* Find the top file in object's mount hier. */
- if(oloc->file->mtab.parent) {
+ if(oloc->file->parent) {
/* Check if object is in child file (for mount & unmount operations) */
if(names->dst_file && oloc->file->shared == names->dst_file->shared)
obj_in_child = TRUE;
/* Find the "top" file in the chain of mounted files */
- top_obj_file = oloc->file->mtab.parent;
- while(top_obj_file->mtab.parent != NULL) {
+ top_obj_file = oloc->file->parent;
+ while(top_obj_file->parent != NULL) {
/* Check if object is in child mount hier. (for mount & unmount operations) */
if(names->dst_file && top_obj_file->shared == names->dst_file->shared)
obj_in_child = TRUE;
- top_obj_file = top_obj_file->mtab.parent;
+ top_obj_file = top_obj_file->parent;
} /* end while */
} /* end if */
else
@@ -926,7 +914,7 @@ done:
*/
herr_t
H5G_name_replace(const H5O_link_t *lnk, H5G_names_op_t op, H5F_t *src_file,
- H5RS_str_t *src_full_path_r, H5F_t *dst_file, H5RS_str_t *dst_full_path_r,
+ H5RS_str_t *src_full_path_r, H5F_t *dst_file, H5RS_str_t *dst_full_path_r,
hid_t dxpl_id)
{
herr_t ret_value = SUCCEED;
@@ -1009,8 +997,8 @@ H5G_name_replace(const H5O_link_t *lnk, H5G_names_op_t op, H5F_t *src_file,
H5G_names_t names; /* Structure to hold operation information for callback */
/* Find top file in src location's mount hierarchy */
- while(src_file->mtab.parent)
- src_file = src_file->mtab.parent;
+ while(src_file->parent)
+ src_file = src_file->parent;
/* Set up common information for callback */
names.src_file = src_file;
@@ -1021,15 +1009,15 @@ H5G_name_replace(const H5O_link_t *lnk, H5G_names_op_t op, H5F_t *src_file,
/* Search through group IDs */
if(search_group)
- H5I_search(H5I_GROUP, H5G_name_replace_cb, &names);
+ H5I_search(H5I_GROUP, H5G_name_replace_cb, &names, FALSE);
/* Search through dataset IDs */
if(search_dataset)
- H5I_search(H5I_DATASET, H5G_name_replace_cb, &names);
+ H5I_search(H5I_DATASET, H5G_name_replace_cb, &names, FALSE);
/* Search through datatype IDs */
if(search_datatype)
- H5I_search(H5I_DATATYPE, H5G_name_replace_cb, &names);
+ H5I_search(H5I_DATATYPE, H5G_name_replace_cb, &names, FALSE);
} /* end if */
} /* end if */
@@ -1039,235 +1027,149 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5G_refname_iterator
- *
- * Purpose: The iterator which traverses all objects in a file looking for
- * one that matches the object that is being looked for.
+ * Function: H5G_get_name_by_addr_cb
*
- * Return: 1 on success, 0 to continue searching, negative on failure.
+ * Purpose: Callback for retrieving object's name by address
*
- * Programmer: Leon Arber, Nov 1, 2006.
+ * Return: Positive if path is for object desired
+ * 0 if not correct object
+ * negative on failure.
*
- * Modifications:
- * Quincey Koziol, Nov. 3, 2006
- * Cleaned up code.
+ * Programmer: Quincey Koziol
+ * November 4 2007
*
*-------------------------------------------------------------------------
*/
static herr_t
-H5G_refname_iterator(hid_t group, const char *name, const H5L_info_t *link_info,
+H5G_get_name_by_addr_cb(hid_t gid, const char *path, const H5L_info_t *linfo,
void *_udata)
{
- H5G_ref_path_iter_t *udata = (H5G_ref_path_iter_t*)_udata;
- herr_t ret_value = H5_ITER_CONT; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5G_refname_iterator)
-
- /* We only care about hard links */
- if(link_info->type == H5L_TYPE_HARD) {
- H5G_loc_t loc; /* Group location of parent */
-
- /* Look up group's location */
- if(H5G_loc(group, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5_ITER_ERROR, "not a location")
-
- /* Check for finding the object */
- /* (checks against the file in the location as well, to make certain that
- * the correct object is found in a mounted file hierarchy)
- */
- if(udata->loc->addr == link_info->u.address && udata->loc->file == loc.oloc->file) {
- size_t len_needed; /* Length of container string needed */
-
- /* Build the object's full name */
- len_needed = HDstrlen(udata->container) + HDstrlen(name) + 2;
- if(len_needed > udata->max_container_len) {
- void *new_container; /* Pointer to new container */
-
- if(NULL == (new_container = H5MM_realloc(udata->container, len_needed)))
- HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, H5_ITER_ERROR, "can't allocate path string")
- udata->container = new_container;
- udata->max_container_len = len_needed;
- } /* end if */
- HDstrcat(udata->container, name);
+ H5G_gnba_iter_t *udata = (H5G_gnba_iter_t *)_udata; /* User data for iteration */
+ H5G_loc_t obj_loc; /* Location of object */
+ H5G_name_t obj_path; /* Object's group hier. path */
+ H5O_loc_t obj_oloc; /* Object's object location */
+ hbool_t obj_found = FALSE; /* Object at 'path' found */
+ herr_t ret_value = H5_ITER_CONT; /* Return value */
- /* We found a match so we return immediately */
- HGOTO_DONE(H5_ITER_STOP)
- } /* end if */
- else {
- H5O_info_t oinfo; /* Object information */
- H5O_loc_t tmp_oloc; /* Temporary object location */
+ FUNC_ENTER_NOAPI_NOINIT(H5G_get_name_by_addr_cb)
- /* Check if we've seen this object before */
- if(H5SL_search(udata->ref_path_table, &link_info->u.address))
- HGOTO_DONE(H5_ITER_CONT)
+ /* Sanity check */
+ HDassert(path);
+ HDassert(linfo);
+ HDassert(udata->loc);
+ HDassert(udata->path == NULL);
- /* Go retrieve the object information */
- tmp_oloc.file = loc.oloc->file;
- tmp_oloc.addr = link_info->u.address;
- if(H5O_get_info(&tmp_oloc, udata->dxpl_id, FALSE, &oinfo) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, H5_ITER_ERROR, "unable to get object info")
+ /* Check for hard link with correct address */
+ if(linfo->type == H5L_TYPE_HARD && udata->loc->addr == linfo->u.address) {
+ H5G_loc_t grp_loc; /* Location of group */
- /* If its ref count is > 1, we add it to the list of visited objects */
- if(oinfo.rc > 1) {
- haddr_t *new_node; /* New path node for table */
+ /* Get group's location */
+ if(H5G_loc(gid, &grp_loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5_ITER_ERROR, "bad group location")
- /* Allocate new path node */
- if((new_node = H5FL_MALLOC(haddr_t)) == NULL)
- HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, H5_ITER_ERROR, "can't allocate path node")
+ /* Set up opened object location to fill in */
+ obj_loc.oloc = &obj_oloc;
+ obj_loc.path = &obj_path;
+ H5G_loc_reset(&obj_loc);
- /* Set node information */
- *new_node = link_info->u.address;
+ /* Find the object */
+ if(H5G_loc_find(&grp_loc, path, &obj_loc/*out*/, udata->lapl_id, udata->dxpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5_ITER_ERROR, "object not found")
+ obj_found = TRUE;
- /* Insert into skip list */
- if(H5SL_insert(udata->ref_path_table, new_node, new_node) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, H5_ITER_ERROR, "can't insert path node into table")
- } /* end if */
+ /* Check for object in same file (handles mounted files) */
+ /* (re-verify address, in case we traversed a file mount) */
+ if(udata->loc->addr == obj_loc.oloc->addr && udata->loc->file == obj_loc.oloc->file) {
+ udata->path = H5MM_strdup(path);
- /* If it's a group, we recurse into it */
- if(oinfo.type == H5O_TYPE_GROUP) {
- H5G_link_iterate_t lnk_op; /* Link operator */
- hsize_t last_obj;
- size_t len_needed; /* Length of container string needed */
- size_t len;
-
- /* Build full path name of group to recurse into */
- len = HDstrlen(udata->container);
- len_needed = len + HDstrlen(name) + 2;
- if(len_needed > udata->max_container_len) {
- void *new_container; /* Pointer to new container */
-
- if(NULL == (new_container = H5MM_realloc(udata->container, len_needed)))
- HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, H5_ITER_ERROR, "can't allocate path string")
- udata->container = new_container;
- udata->max_container_len = len_needed;
- } /* end if */
- if(!udata->is_root_group)
- HDstrcat(udata->container, name);
- else
- udata->is_root_group = FALSE;
- HDstrcat(udata->container, "/");
-
- /* Build iterator operator */
- lnk_op.op_type = H5G_LINK_OP_APP;
- lnk_op.u.app_op = H5G_refname_iterator;
-
- ret_value = H5G_obj_iterate(udata->file, udata->container, H5_INDEX_NAME, H5_ITER_NATIVE, (hsize_t)0, &last_obj, &lnk_op, udata, udata->lapl_id, udata->dxpl_id);
-
- /* If we didn't find the object, truncate the name to not include group name anymore */
- if(!ret_value)
- udata->container[len] = '\0';
- } /* end if */
- } /* end else */
+ /* We found a match so we return immediately */
+ HGOTO_DONE(H5_ITER_STOP)
+ } /* end if */
} /* end if */
done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5G_refname_iterator() */
+ if(obj_found && H5G_loc_free(&obj_loc) < 0)
+ HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, H5_ITER_ERROR, "can't free location")
-
-/*-------------------------------------------------------------------------
- * Function: H5G_free_ref_path_node
- *
- * Purpose: Free the key for a reference path table node
- *
- * Return: Non-negative on success, negative on failure
- *
- * Programmer: Quincey Koziol
- *
- * Modifications:
- * Leon Arber, Oct. 25, 2006. Moved into H5G from h5ls
- * tools lib for looking up path to reference.
- *
- * Quincey Koziol, Nov. 3, 2006
- * Cleaned up code.
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5G_free_ref_path_node(void *item, void UNUSED *key, void UNUSED *operator_data/*in,out*/)
-{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_free_ref_path_node)
-
- H5FL_FREE(haddr_t, item);
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5G_free_ref_path_node() */
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_get_name_by_addr_cb() */
/*-------------------------------------------------------------------------
- * Function: H5G_get_refobj_name
+ * Function: H5G_get_name_by_addr
*
- * Purpose: Tries to figure out the path to a reference.
+ * Purpose: Tries to figure out the path to an object from it's address
*
* Return: returns size of path name, and copies it into buffer
* pointed to by name if that buffer is big enough.
* 0 if it cannot find the path
* negative on failure.
*
- * Programmer: Leon Arber, Nov 1, 2006.
- *
- * Modifications:
- * Quincey Koziol, Nov. 3, 2006
- * Cleaned up code.
+ * Programmer: Quincey Koziol
+ * November 4 2007
*
*-------------------------------------------------------------------------
*/
ssize_t
-H5G_get_refobj_name(hid_t file, hid_t lapl_id, hid_t dxpl_id, const H5O_loc_t *loc,
+H5G_get_name_by_addr(hid_t file, hid_t lapl_id, hid_t dxpl_id, const H5O_loc_t *loc,
char *name, size_t size)
{
- H5G_ref_path_iter_t udata; /* User data for iteration */
- H5G_loc_t root_loc; /* Root location */
- H5L_info_t root_info; /* Link info for root group */
+ H5G_gnba_iter_t udata; /* User data for iteration */
+ H5G_loc_t root_loc; /* Root group's location */
+ hbool_t found_obj = FALSE; /* If we found the object */
herr_t status; /* Status from iteration */
ssize_t ret_value; /* Return value */
- FUNC_ENTER_NOAPI(H5G_get_refobj_name, FAIL)
+ FUNC_ENTER_NOAPI(H5G_get_name_by_addr, FAIL)
- /* Construct the link info for the root group */
+ /* Construct the link info for the file's root group */
if(H5G_loc(file, &root_loc) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get root group's location")
- HDmemset(&root_info, 0, sizeof(root_info));
- root_info.type = H5L_TYPE_HARD;
- root_info.u.address = root_loc.oloc->addr;
-
- /* Set up user data for iterator */
- udata.file = file;
- udata.lapl_id = lapl_id;
- udata.dxpl_id = dxpl_id;
- udata.is_root_group = TRUE;
- if(NULL == (udata.container = H5MM_strdup("")))
- HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate root group name")
- udata.max_container_len = 1;
- udata.loc = loc;
-
- /* Create skip list to store reference path information */
- if((udata.ref_path_table = H5SL_create(H5SL_TYPE_HADDR, 0.5, (size_t)16)) == NULL)
- HGOTO_ERROR(H5E_SYM, H5E_CANTCREATE, FAIL, "can't create skip list for path nodes")
-
- /* Iterate over all the objects in the file */
- if((status = H5G_refname_iterator(file, "/", &root_info, &udata)) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "group iteration failed while looking for object name")
- else if(status > 0) {
+
+ /* Check for root group being the object looked for */
+ if(root_loc.oloc->addr == loc->addr && root_loc.oloc->file == loc->file) {
+ udata.path = H5MM_strdup("");
+ found_obj = TRUE;
+ } /* end if */
+ else {
+ /* Set up user data for iterator */
+ udata.loc = loc;
+ udata.lapl_id = lapl_id;
+ udata.dxpl_id = dxpl_id;
+ udata.path = NULL;
+
+ /* Visit all the links in the file */
+ if((status = H5G_visit(file, "/", H5_INDEX_NAME, H5_ITER_NATIVE, H5G_get_name_by_addr_cb, &udata, lapl_id, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "group traversal failed while looking for object name")
+ else if(status > 0)
+ found_obj = TRUE;
+ } /* end else */
+
+ /* Check for finding the object */
+ if(found_obj) {
+ size_t full_path_len = HDstrlen(udata.path) + 1; /* Length of path + 1 (for "/") */
+
/* Set the length of the full path */
- ret_value = HDstrlen(udata.container);
+ ret_value = full_path_len;
/* If there's a buffer provided, copy into it, up to the limit of its size */
if(name) {
- HDstrncpy(name, udata.container, size);
+ /* Copy the initial path separator */
+ HDstrcpy(name, "/");
+
+ /* Append the rest of the path */
+ /* (less one character, for the initial path separator) */
+ HDstrncat(name, udata.path, (size - 2));
if((size_t)ret_value >= size)
name[size - 1] = '\0';
} /* end if */
} /* end if */
else
ret_value = 0;
-
-done:
+
+done:
/* Release resources */
- H5MM_xfree(udata.container);
- if(udata.ref_path_table)
- H5SL_destroy(udata.ref_path_table, H5G_free_ref_path_node, NULL);
+ H5MM_xfree(udata.path);
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5G_get_refobj_name() */
-
+} /* end H5G_get_name_by_addr() */
diff --git a/src/H5Gnode.c b/src/H5Gnode.c
index 6cff5a0..9468302 100644
--- a/src/H5Gnode.c
+++ b/src/H5Gnode.c
@@ -39,7 +39,6 @@
#include "H5HLprivate.h" /* Local Heaps */
#include "H5MFprivate.h" /* File memory management */
#include "H5MMprivate.h" /* Memory management */
-#include "H5WBprivate.h" /* Wrapped Buffers */
/* Private typedefs */
@@ -51,39 +50,11 @@ typedef struct H5G_node_key_t {
size_t offset; /*offset into heap for name */
} H5G_node_key_t;
-/*
- * A symbol table node is a collection of symbol table entries. It can
- * be thought of as the lowest level of the B-link tree that points to
- * a collection of symbol table entries that belong to a specific symbol
- * table or group.
- */
-typedef struct H5G_node_t {
- H5AC_info_t cache_info; /* Information for H5AC cache functions, _must_ be */
- /* first field in structure */
- unsigned nsyms; /*number of symbols */
- H5G_entry_t *entry; /*array of symbol table entries */
-} H5G_node_t;
-
/* Private macros */
-#define H5G_NODE_VERS 1 /*symbol table node version number */
-#define H5G_NODE_SIZEOF_HDR(F) (H5G_NODE_SIZEOF_MAGIC + 4)
-/* Size of stack buffer for serialized nodes */
-#define H5G_NODE_BUF_SIZE 512
+#define H5G_NODE_SIZEOF_HDR(F) (H5_SIZEOF_MAGIC + 4)
/* PRIVATE PROTOTYPES */
-static herr_t H5G_node_serialize(H5F_t *f, H5G_node_t *sym, size_t size, uint8_t *buf);
-static size_t H5G_node_size_real(const H5F_t *f);
-static herr_t H5G_node_shared_free(void *shared);
-
-/* Metadata cache callbacks */
-static H5G_node_t *H5G_node_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_udata1,
- void *_udata2);
-static herr_t H5G_node_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
- H5G_node_t *sym, unsigned UNUSED * flags_ptr);
-static herr_t H5G_node_dest(H5F_t *f, H5G_node_t *sym);
-static herr_t H5G_node_clear(H5F_t *f, H5G_node_t *sym, hbool_t destroy);
-static herr_t H5G_node_size(const H5F_t *f, const H5G_node_t *sym, size_t *size_ptr);
/* B-tree callbacks */
static H5RC_t *H5G_node_get_shared(const H5F_t *f, const void *_udata);
@@ -94,7 +65,7 @@ static int H5G_node_cmp2(H5F_t *f, hid_t dxpl_id, void *_lt_key, void *_udata,
void *_rt_key);
static int H5G_node_cmp3(H5F_t *f, hid_t dxpl_id, void *_lt_key, void *_udata,
void *_rt_key);
-static herr_t H5G_node_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_lt_key,
+static htri_t H5G_node_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_lt_key,
void *_udata);
static H5B_ins_t H5G_node_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key,
hbool_t *lt_key_changed, void *_md_key,
@@ -112,16 +83,6 @@ static herr_t H5G_node_debug_key(FILE *stream, H5F_t *f, hid_t dxpl_id,
int indent, int fwidth, const void *key,
const void *udata);
-/* H5G inherits cache-like properties from H5AC */
-const H5AC_class_t H5AC_SNODE[1] = {{
- H5AC_SNODE_ID,
- (H5AC_load_func_t)H5G_node_load,
- (H5AC_flush_func_t)H5G_node_flush,
- (H5AC_dest_func_t)H5G_node_dest,
- (H5AC_clear_func_t)H5G_node_clear,
- (H5AC_size_func_t)H5G_node_size,
-}};
-
/* H5G inherits B-tree like properties from H5B */
H5B_class_t H5B_SNODE[1] = {{
H5B_SNODE_ID, /*id */
@@ -141,16 +102,10 @@ H5B_class_t H5B_SNODE[1] = {{
}};
/* Declare a free list to manage the H5G_node_t struct */
-H5FL_DEFINE_STATIC(H5G_node_t);
+H5FL_DEFINE(H5G_node_t);
/* Declare a free list to manage sequences of H5G_entry_t's */
-H5FL_SEQ_DEFINE_STATIC(H5G_entry_t);
-
-/* Declare a free list to manage the native key offset sequence information */
-H5FL_SEQ_DEFINE_STATIC(size_t);
-
-/* Declare a free list to manage the raw page information */
-H5FL_BLK_DEFINE_STATIC(grp_page);
+H5FL_SEQ_DEFINE(H5G_entry_t);
/*-------------------------------------------------------------------------
@@ -283,7 +238,7 @@ H5G_node_debug_key(FILE *stream, H5F_t *f, hid_t UNUSED dxpl_id, int indent,
HDfprintf(stream, "%*s%-*s ", indent, "", fwidth, "Name:");
- s = H5HL_offset_into(f, udata->heap, key->offset);
+ s = (const char *)H5HL_offset_into(f, udata->heap, key->offset);
HDfprintf(stream, "%s\n", s);
} /* end if */
else
@@ -310,7 +265,7 @@ H5G_node_debug_key(FILE *stream, H5F_t *f, hid_t UNUSED dxpl_id, int indent,
*
*-------------------------------------------------------------------------
*/
-static size_t
+size_t
H5G_node_size_real(const H5F_t *f)
{
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_node_size_real);
@@ -321,389 +276,6 @@ H5G_node_size_real(const H5F_t *f)
/*-------------------------------------------------------------------------
- * Function: H5G_node_load
- *
- * Purpose: Loads a symbol table node from the file.
- *
- * Return: Success: Ptr to the new table.
- *
- * Failure: NULL
- *
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Jun 23 1997
- *
- * Modifications:
- * Robb Matzke, 1999-07-28
- * The ADDR argument is passed by value.
- *
- * Quincey Koziol, 2002-7-180
- * Added dxpl parameter to allow more control over I/O from metadata
- * cache.
- *-------------------------------------------------------------------------
- */
-static H5G_node_t *
-H5G_node_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *_udata1,
- void UNUSED * _udata2)
-{
- H5G_node_t *sym = NULL;
- size_t size;
- H5WB_t *wb = NULL; /* Wrapped buffer for node data */
- uint8_t node_buf[H5G_NODE_BUF_SIZE]; /* Buffer for node */
- uint8_t *node; /* Pointer to node buffer */
- const uint8_t *p;
- H5G_node_t *ret_value; /*for error handling */
-
- FUNC_ENTER_NOAPI_NOINIT(H5G_node_load)
-
- /*
- * Check arguments.
- */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
- HDassert(!_udata1);
- HDassert(NULL == _udata2);
-
- /*
- * Initialize variables.
- */
-
- /* Wrap the local buffer for serialized node info */
- if(NULL == (wb = H5WB_wrap(node_buf, sizeof(node_buf))))
- HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "can't wrap buffer")
-
- /* Compute the size of the serialized symbol table node on disk */
- size = H5G_node_size_real(f);
-
- /* Get a pointer to a buffer that's large enough for node */
- if(NULL == (node = H5WB_actual(wb, size)))
- HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, NULL, "can't get actual buffer")
-
- /* Read the serialized symbol table node. */
- if(H5F_block_read(f, H5FD_MEM_BTREE, addr, size, dxpl_id, node) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_READERROR, NULL, "unable to read symbol table node")
-
- /* Get temporary pointer to serialized node */
- p = node;
-
- /* magic */
- if(HDmemcmp(p, H5G_NODE_MAGIC, (size_t)H5G_NODE_SIZEOF_MAGIC))
- HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, NULL, "bad symbol table node signature")
- p += 4;
-
- /* version */
- if(H5G_NODE_VERS != *p++)
- HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, NULL, "bad symbol table node version")
-
- /* reserved */
- p++;
-
- /* Allocate symbol table data structures */
- if(NULL == (sym = H5FL_CALLOC(H5G_node_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- if(NULL == (sym->entry = H5FL_SEQ_CALLOC(H5G_entry_t, (size_t)(2 * H5F_SYM_LEAF_K(f)))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
-
- /* number of symbols */
- UINT16DECODE(p, sym->nsyms);
-
- /* entries */
- if(H5G_ent_decode_vec(f, &p, sym->entry, sym->nsyms) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, NULL, "unable to decode symbol table entries")
-
- /* Set return value */
- ret_value = sym;
-
-done:
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, NULL, "can't close wrapped buffer")
- if(!ret_value)
- if(sym && H5G_node_dest(f, sym) < 0)
- HDONE_ERROR(H5E_SYM, H5E_CANTFREE, NULL, "unable to destroy symbol table node")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5G_node_load() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5G_node_flush
- *
- * Purpose: Flush a symbol table node to disk.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Jun 23 1997
- *
- * Modifications:
- * rky, 1998-08-28
- * Only p0 writes metadata to disk.
- *
- * Robb Matzke, 1999-07-28
- * The ADDR argument is passed by value.
- *
- * Quincey Koziol, 2002-7-180
- * Added dxpl parameter to allow more control over I/O from metadata
- * cache.
- *
- * Pedro Vicente, <pvn@ncsa.uiuc.edu> 18 Sep 2002
- * Added `id to name' support.
- *
- * JRM -- 8/21/06
- * Added the flags_ptr parameter. This parameter exists to
- * allow the flush routine to report to the cache if the
- * entry is resized or renamed as a result of the flush.
- * *flags_ptr is set to H5C_CALLBACK__NO_FLAGS_SET on entry.
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5G_node_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5G_node_t *sym, unsigned UNUSED * flags_ptr)
-{
- H5WB_t *wb = NULL; /* Wrapped buffer for node data */
- uint8_t node_buf[H5G_NODE_BUF_SIZE]; /* Buffer for node */
- unsigned u;
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5G_node_flush)
-
- /*
- * Check arguments.
- */
- HDassert(f);
- HDassert(H5F_addr_defined(addr));
- HDassert(sym);
-
- /*
- * Look for dirty entries and set the node dirty flag.
- */
- for(u = 0; u < sym->nsyms; u++)
- if(sym->entry[u].dirty) {
- /* Set the node's dirty flag */
- sym->cache_info.is_dirty = TRUE;
-
- /* Reset the entry's dirty flag */
- sym->entry[u].dirty = FALSE;
- } /* end if */
-
- /*
- * Write the symbol node to disk.
- */
- if(sym->cache_info.is_dirty) {
- uint8_t *node; /* Pointer to node buffer */
- size_t size;
-
- /* Wrap the local buffer for serialized node info */
- if(NULL == (wb = H5WB_wrap(node_buf, sizeof(node_buf))))
- HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't wrap buffer")
-
- /* Compute the size of the serialized symbol table node on disk */
- size = H5G_node_size_real(f);
-
- /* Get a pointer to a buffer that's large enough for node */
- if(NULL == (node = H5WB_actual(wb, size)))
- HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't get actual buffer")
-
- /* Serialize symbol table node into buffer */
- if(H5G_node_serialize(f, sym, size, node) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTSERIALIZE, FAIL, "node serialization failed")
-
- /* Write the serialized symbol table node. */
- if(H5F_block_write(f, H5FD_MEM_BTREE, addr, size, dxpl_id, node) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_WRITEERROR, FAIL, "unable to write symbol table node to the file")
-
- /* Reset the node's dirty flag */
- sym->cache_info.is_dirty = FALSE;
- } /* end if */
-
- /*
- * Destroy the symbol node? This might happen if the node is being
- * preempted from the cache.
- */
- if(destroy)
- if(H5G_node_dest(f, sym) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to destroy symbol table node")
-
-done:
- /* Release resources */
- if(wb && H5WB_unwrap(wb) < 0)
- HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close wrapped buffer")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5G_node_flush() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5G_node_serialize
- *
- * Purpose: Serialize the symbol table node
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Bill Wendling
- * wendling@ncsa.uiuc.edu
- * Sept. 16, 2003
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5G_node_serialize(H5F_t *f, H5G_node_t *sym, size_t size, uint8_t *buf)
-{
- uint8_t *p;
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT(H5G_node_serialize);
-
- /* check args */
- assert(f);
- assert(sym);
- assert(buf);
-
- p = buf;
-
- /* magic number */
- HDmemcpy(p, H5G_NODE_MAGIC, (size_t)H5G_NODE_SIZEOF_MAGIC);
- p += 4;
-
- /* version number */
- *p++ = H5G_NODE_VERS;
-
- /* reserved */
- *p++ = 0;
-
- /* number of symbols */
- UINT16ENCODE(p, sym->nsyms);
-
- /* entries */
- if (H5G_ent_encode_vec(f, &p, sym->entry, sym->nsyms) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTENCODE, FAIL, "can't serialize")
- HDmemset(p, 0, size - (p - buf));
-
-done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5G_node_dest
- *
- * Purpose: Destroy a symbol table node in memory.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Jan 15 2003
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5G_node_dest(H5F_t UNUSED *f, H5G_node_t *sym)
-{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_node_dest);
-
- /*
- * Check arguments.
- */
- assert(sym);
-
- /* Verify that node is clean */
- assert (sym->cache_info.is_dirty==FALSE);
-
- if(sym->entry)
- sym->entry = H5FL_SEQ_FREE(H5G_entry_t,sym->entry);
- H5FL_FREE(H5G_node_t,sym);
-
- FUNC_LEAVE_NOAPI(SUCCEED);
-} /* end H5G_node_dest() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5G_node_clear
- *
- * Purpose: Mark a symbol table node in memory as non-dirty.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Mar 20 2003
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5G_node_clear(H5F_t *f, H5G_node_t *sym, hbool_t destroy)
-{
- unsigned u; /* Local index variable */
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT(H5G_node_clear);
-
- /*
- * Check arguments.
- */
- assert(sym);
-
- /* Look for dirty entries and reset their dirty flag. */
- for(u = 0; u < sym->nsyms; u++)
- sym->entry[u].dirty=FALSE;
- sym->cache_info.is_dirty = FALSE;
-
- /*
- * Destroy the symbol node? This might happen if the node is being
- * preempted from the cache.
- */
- if (destroy)
- if (H5G_node_dest(f, sym) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to destroy symbol table node");
-
-done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5G_node_clear() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5G_node_size
- *
- * Purpose: Compute the size in bytes of the specified instance of
- * H5G_node_t on disk, and return it in *size_ptr. On failure
- * the value of size_ptr is undefined.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: John Mainzer
- * 5/13/04
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5G_node_size(const H5F_t *f, const H5G_node_t UNUSED *sym, size_t *size_ptr)
-{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_node_size);
-
- /*
- * Check arguments.
- */
- HDassert(f);
- HDassert(size_ptr);
-
- *size_ptr = H5G_node_size_real(f);
-
- FUNC_LEAVE_NOAPI(SUCCEED);
-} /* H5G_node_size() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5G_node_create
*
* Purpose: Creates a new empty symbol table node. This function is
@@ -767,7 +339,7 @@ done:
if(sym != NULL) {
if(sym->entry != NULL)
H5FL_SEQ_FREE(H5G_entry_t, sym->entry);
- H5FL_FREE(H5G_node_t, sym);
+ (void)H5FL_FREE(H5G_node_t, sym);
} /* end if */
} /* end if */
@@ -817,7 +389,7 @@ H5G_node_cmp2(H5F_t *f, hid_t UNUSED dxpl_id, void *_lt_key, void *_udata,
HDassert(rt_key);
/* Get base address of heap */
- base = H5HL_offset_into(f, udata->heap, (size_t)0);
+ base = (const char *)H5HL_offset_into(f, udata->heap, (size_t)0);
HDassert(base);
/* Get pointers to string names */
@@ -877,7 +449,7 @@ H5G_node_cmp3(H5F_t *f, hid_t UNUSED dxpl_id, void *_lt_key, void *_udata,
HDassert(rt_key);
/* Get base address of heap */
- base = H5HL_offset_into(f, udata->heap, (size_t)0);
+ base = (const char *)H5HL_offset_into(f, udata->heap, (size_t)0);
HDassert(base);
/* left side */
@@ -910,8 +482,8 @@ H5G_node_cmp3(H5F_t *f, hid_t UNUSED dxpl_id, void *_lt_key, void *_udata,
* entry field. Otherwise the entry is copied from the
* UDATA entry field to the symbol table.
*
- * Return: Success: Non-negative if found and data returned through
- * the UDATA pointer.
+ * Return: Success: Non-negative (TRUE/FALSE) if found and data
+ * returned through the UDATA pointer.
*
* Failure: Negative if not found.
*
@@ -921,7 +493,7 @@ H5G_node_cmp3(H5F_t *f, hid_t UNUSED dxpl_id, void *_lt_key, void *_udata,
*
*-------------------------------------------------------------------------
*/
-static herr_t
+static htri_t
H5G_node_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *_lt_key,
void *_udata)
{
@@ -930,8 +502,8 @@ H5G_node_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *_lt_key
unsigned lt = 0, idx = 0, rt;
int cmp = 1;
const char *s;
- const char *base; /* Base of heap */
- herr_t ret_value = SUCCEED; /* Return value */
+ const char *base; /* Base of heap */
+ htri_t ret_value = TRUE; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5G_node_found)
@@ -945,11 +517,11 @@ H5G_node_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *_lt_key
/*
* Load the symbol table node for exclusive access.
*/
- if(NULL == (sn = H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, FAIL, "unable to protect symbol table node")
/* Get base address of heap */
- base = H5HL_offset_into(f, udata->common.heap, (size_t)0);
+ base = (const char *)H5HL_offset_into(f, udata->common.heap, (size_t)0);
HDassert(base);
/*
@@ -968,7 +540,7 @@ H5G_node_found(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *_lt_key
} /* end while */
if(cmp)
- HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "not found")
+ HGOTO_DONE(FALSE)
/* Call user's callback operator */
if((udata->op)(&sn->entry[idx], udata->op_data) < 0)
@@ -1051,11 +623,11 @@ H5G_node_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr,
/*
* Load the symbol node.
*/
- if(NULL == (sn = H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, NULL, NULL, H5AC_WRITE)))
+ if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, NULL, NULL, H5AC_WRITE)))
HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR, "unable to protect symbol table node")
/* Get base address of heap */
- base = H5HL_offset_into(f, udata->common.heap, (size_t)0);
+ base = (const char *)H5HL_offset_into(f, udata->common.heap, (size_t)0);
HDassert(base);
/*
@@ -1094,7 +666,7 @@ H5G_node_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr,
if(H5G_node_create(f, dxpl_id, H5B_INS_FIRST, NULL, NULL, NULL, new_node_p/*out*/) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, H5B_INS_ERROR, "unable to split symbol table node")
- if(NULL == (snrt = H5AC_protect(f, dxpl_id, H5AC_SNODE, *new_node_p, NULL, NULL, H5AC_WRITE)))
+ if(NULL == (snrt = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, *new_node_p, NULL, NULL, H5AC_WRITE)))
HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR, "unable to split symbol table node")
HDmemcpy(snrt->entry, sn->entry + H5F_SYM_LEAF_K(f),
@@ -1211,7 +783,7 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/,
HDassert(udata && udata->common.heap);
/* Load the symbol table */
- if(NULL == (sn = H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, NULL, NULL, H5AC_WRITE)))
+ if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, NULL, NULL, H5AC_WRITE)))
HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR, "unable to protect symbol table node")
/* "Normal" removal of a single entry from the symbol table node */
@@ -1221,7 +793,7 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/,
const char *base; /* Base of heap */
/* Get base address of heap */
- base = H5HL_offset_into(f, udata->common.heap, (size_t)0);
+ base = (const char *)H5HL_offset_into(f, udata->common.heap, (size_t)0);
/* Find the name with a binary search */
rt = sn->nsyms;
@@ -1241,7 +813,7 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/,
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5B_INS_ERROR, "name not found")
/* Get a pointer to the name of the link */
- if(NULL == (lnk.name = H5HL_offset_into(f, udata->common.heap, sn->entry[idx].name_off)))
+ if(NULL == (lnk.name = (char *)H5HL_offset_into(f, udata->common.heap, sn->entry[idx].name_off)))
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to get link name")
/* Set up rest of link structure */
@@ -1250,7 +822,7 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/,
lnk.cset = H5T_CSET_ASCII;
if(sn->entry[idx].type == H5G_CACHED_SLINK) {
lnk.type = H5L_TYPE_SOFT;
- lnk.u.soft.name = H5HL_offset_into(f, udata->common.heap, sn->entry[idx].cache.slink.lval_offset);
+ lnk.u.soft.name = (char *)H5HL_offset_into(f, udata->common.heap, sn->entry[idx].cache.slink.lval_offset);
} /* end if */
else {
lnk.type = H5L_TYPE_HARD;
@@ -1299,14 +871,8 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/,
*rt_key = *lt_key;
*rt_key_changed = TRUE;
sn->nsyms = 0;
- if(H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, addr, (hsize_t)H5G_node_size_real(f)) < 0
- || H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, H5AC__DIRTIED_FLAG | H5C__DELETED_FLAG) < 0) {
- sn = NULL;
- HGOTO_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to free symbol table node")
- } /* end if */
- sn = NULL;
+ sn_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
ret_value = H5B_INS_REMOVE;
-
} else if(0 == idx) {
/*
* We are about to remove the left-most entry from the symbol table
@@ -1318,7 +884,6 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/,
HDmemmove(sn->entry + idx, sn->entry + idx + 1,
(sn->nsyms-idx) * sizeof(H5G_entry_t));
ret_value = H5B_INS_NOOP;
-
} else if (idx + 1 == sn->nsyms) {
/*
* We are about to remove the right-most entry from the symbol table
@@ -1330,7 +895,6 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/,
rt_key->offset = sn->entry[sn->nsyms - 1].name_off;
*rt_key_changed = TRUE;
ret_value = H5B_INS_NOOP;
-
} else {
/*
* We are about to remove an entry from the middle of a symbol table
@@ -1371,12 +935,7 @@ H5G_node_remove(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key/*in,out*/,
*rt_key = *lt_key;
*rt_key_changed = TRUE;
sn->nsyms = 0;
- if(H5MF_xfree(f, H5FD_MEM_BTREE, dxpl_id, addr, (hsize_t)H5G_node_size_real(f)) < 0
- || H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, H5AC__DIRTIED_FLAG | H5C__DELETED_FLAG) < 0) {
- sn = NULL;
- HGOTO_ERROR(H5E_SYM, H5E_PROTECT, H5B_INS_ERROR, "unable to free symbol table node")
- } /* end if */
- sn = NULL;
+ sn_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
ret_value = H5B_INS_REMOVE;
} /* end else */
@@ -1421,7 +980,7 @@ H5G_node_iterate(H5F_t *f, hid_t dxpl_id, const void UNUSED *_lt_key, haddr_t ad
HDassert(udata && udata->heap);
/* Protect the symbol table node & local heap while we iterate over entries */
- if(NULL == (sn = H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5_ITER_ERROR, "unable to load symbol table node")
/*
@@ -1431,51 +990,23 @@ H5G_node_iterate(H5F_t *f, hid_t dxpl_id, const void UNUSED *_lt_key, haddr_t ad
if(udata->skip > 0)
--udata->skip;
else {
- const char *name; /* Pointer to link name in heap */
+ H5O_link_t lnk; /* Link for entry */
+ const char *name; /* Pointer to link name in heap */
/* Get the pointer to the name of the link in the heap */
- name = H5HL_offset_into(f, udata->heap, ents[u].name_off);
+ name = (const char *)H5HL_offset_into(f, udata->heap, ents[u].name_off);
HDassert(name);
- /* Check which type of callback to make */
- switch(udata->lnk_op->op_type) {
-#ifndef H5_NO_DEPRECATED_SYMBOLS
- case H5G_LINK_OP_OLD:
- /* Make the old-type application callback */
- ret_value = (udata->lnk_op->u.old_op)(udata->group_id, name, udata->op_data);
- break;
-#endif /* H5_NO_DEPRECATED_SYMBOLS */
-
- case H5G_LINK_OP_APP:
- {
- H5L_info_t info; /* Link info for entry */
-
- /* Make a link info for an entry */
- if(H5G_ent_to_info(f, &info, udata->heap, &ents[u]) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get info for symbol table entry")
-
- /* Make the application callback */
- ret_value = (udata->lnk_op->u.app_op)(udata->group_id, name, &info, udata->op_data);
- }
- break;
-
- case H5G_LINK_OP_LIB:
- /* Call the library's callback */
- {
- H5O_link_t lnk; /* Link for entry */
-
- /* Convert the entry to a link */
- if(H5G_ent_to_link(f, &lnk, udata->heap, &ents[u], name) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTCONVERT, H5_ITER_ERROR, "unable to convert symbol table entry to link")
-
- /* Call the library's callback */
- ret_value = (udata->lnk_op->u.lib_op)(&lnk, udata->op_data);
-
- /* Release memory for link object */
- if(H5O_msg_reset(H5O_LINK_ID, &lnk) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, H5_ITER_ERROR, "unable to release link message")
- }
- } /* end switch */
+ /* Convert the entry to a link */
+ if(H5G_ent_to_link(f, &lnk, udata->heap, &ents[u], name) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTCONVERT, H5_ITER_ERROR, "unable to convert symbol table entry to link")
+
+ /* Make the callback */
+ ret_value = (udata->op)(&lnk, udata->op_data);
+
+ /* Release memory for link object */
+ if(H5O_msg_reset(H5O_LINK_ID, &lnk) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, H5_ITER_ERROR, "unable to release link message")
} /* end else */
/* Increment the number of entries passed through */
@@ -1526,7 +1057,7 @@ H5G_node_sumup(H5F_t *f, hid_t dxpl_id, const void UNUSED *_lt_key, haddr_t addr
HDassert(num_objs);
/* Find the object node and add the number of symbol entries. */
- if(NULL == (sn = H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5_ITER_ERROR, "unable to load symbol table node")
*num_objs += sn->nsyms;
@@ -1571,7 +1102,7 @@ H5G_node_by_idx(H5F_t *f, hid_t dxpl_id, const void UNUSED *_lt_key, haddr_t add
HDassert(udata);
/* Get a pointer to the symbol table node */
- if(NULL == (sn = H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5_ITER_ERROR, "unable to load symbol table node");
/* Find the node, locate the object symbol table entry and retrieve the name */
@@ -1618,39 +1149,26 @@ herr_t
H5G_node_init(H5F_t *f)
{
H5B_shared_t *shared; /* Shared B-tree node info */
- size_t u; /* Local index variable */
+ size_t sizeof_rkey; /* Size of raw (disk) key */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5G_node_init, FAIL);
/* Check arguments. */
- assert(f);
+ HDassert(f);
+
+ /* Set the raw key size */
+ sizeof_rkey = H5F_SIZEOF_SIZE(f); /*name offset */
- /* Allocate space for the shared structure */
- if(NULL==(shared=H5FL_MALLOC(H5B_shared_t)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for shared B-tree info")
-
- /* Set up the "global" information for this file's groups */
- shared->type= H5B_SNODE;
- shared->two_k=2*H5F_KVALUE(f,H5B_SNODE);
- shared->sizeof_rkey = H5F_SIZEOF_SIZE(f); /*the name offset */
- assert(shared->sizeof_rkey);
- shared->sizeof_rnode = H5B_nodesize(f, shared, &shared->sizeof_keys);
- assert(shared->sizeof_rnode);
- if(NULL==(shared->page=H5FL_BLK_MALLOC(grp_page,shared->sizeof_rnode)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree page")
-#ifdef H5_CLEAR_MEMORY
-HDmemset(shared->page, 0, shared->sizeof_rnode);
-#endif /* H5_CLEAR_MEMORY */
- if(NULL==(shared->nkey=H5FL_SEQ_MALLOC(size_t,(size_t)(2*H5F_KVALUE(f,H5B_SNODE)+1))))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree page")
-
- /* Initialize the offsets into the native key buffer */
- for(u=0; u<(2*H5F_KVALUE(f,H5B_SNODE)+1); u++)
- shared->nkey[u]=u*H5B_SNODE->sizeof_nkey;
+ /* Allocate & initialize global info for the shared structure */
+ if(NULL == (shared = H5B_shared_new(f, H5B_SNODE, sizeof_rkey)))
+ HGOTO_ERROR(H5E_BTREE, H5E_NOSPACE, FAIL, "memory allocation failed for shared B-tree info")
+
+ /* Set up the "local" information for this file's groups */
+ /* <none> */
/* Make shared B-tree info reference counted */
- if(NULL==(f->shared->grp_btree_shared=H5RC_create(shared,H5G_node_shared_free)))
+ if(NULL == (f->shared->grp_btree_shared = H5RC_create(shared, H5B_shared_free)))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create ref-count wrapper for shared B-tree info")
done:
@@ -1690,40 +1208,6 @@ H5G_node_close(const H5F_t *f)
/*-------------------------------------------------------------------------
- * Function: H5G_node_shared_free
- *
- * Purpose: Free B-tree shared info
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Thursday, July 8, 2004
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5G_node_shared_free (void *_shared)
-{
- H5B_shared_t *shared = (H5B_shared_t *)_shared;
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_node_shared_free)
-
- /* Free the raw B-tree node buffer */
- H5FL_BLK_FREE(grp_page,shared->page);
-
- /* Free the B-tree native key offsets buffer */
- H5FL_SEQ_FREE(size_t,shared->nkey);
-
- /* Free the shared B-tree info */
- H5FL_FREE(H5B_shared_t,shared);
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5G_node_shared_free() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5G_node_copy
*
* Purpose: This function gets called during a group iterate operation
@@ -1756,7 +1240,7 @@ H5G_node_copy(H5F_t *f, hid_t dxpl_id, const void UNUSED *_lt_key, haddr_t addr,
HDassert(udata);
/* load the symbol table into memory from the source file */
- if(NULL == (sn = H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5_ITER_ERROR, "unable to load symbol table node")
/* get the base address of the heap */
@@ -1824,7 +1308,7 @@ H5G_node_copy(H5F_t *f, hid_t dxpl_id, const void UNUSED *_lt_key, haddr_t addr,
/* Construct link information for eventual insertion */
lnk.type = H5L_TYPE_SOFT;
- lnk.u.soft.name = H5HL_offset_into(f, heap, src_ent->cache.slink.lval_offset);
+ lnk.u.soft.name = (char *)H5HL_offset_into(f, heap, src_ent->cache.slink.lval_offset);
} /* else if */
else
HDassert(0 && "Unknown entry type");
@@ -1836,7 +1320,7 @@ H5G_node_copy(H5F_t *f, hid_t dxpl_id, const void UNUSED *_lt_key, haddr_t addr,
/* lnk.name = name; */ /* This will be set in callback */
/* Determine name of source object */
- name = H5HL_offset_into(f, heap, src_ent->name_off);
+ name = (const char *)H5HL_offset_into(f, heap, src_ent->name_off);
HDassert(name);
/* Insert the new object in the destination file's group */
@@ -1891,7 +1375,7 @@ H5G_node_build_table(H5F_t *f, hid_t dxpl_id, const void UNUSED *_lt_key, haddr_
* Save information about the symbol table node since we can't lock it
* because we're about to call an application function.
*/
- if(NULL == (sn = H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5_ITER_ERROR, "unable to load symbol table node")
/* Check if the link table needs to be extended */
@@ -1900,7 +1384,7 @@ H5G_node_build_table(H5F_t *f, hid_t dxpl_id, const void UNUSED *_lt_key, haddr_
H5O_link_t *x; /* Pointer to larger array of links */
/* Re-allocate the link table */
- if((x = H5MM_realloc(udata->ltable->lnks, sizeof(H5O_link_t) * na)) == NULL)
+ if(NULL == (x = (H5O_link_t *)H5MM_realloc(udata->ltable->lnks, sizeof(H5O_link_t) * na)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5_ITER_ERROR, "memory allocation failed")
udata->ltable->lnks = x;
} /* end if */
@@ -1911,7 +1395,7 @@ H5G_node_build_table(H5F_t *f, hid_t dxpl_id, const void UNUSED *_lt_key, haddr_
unsigned linkno; /* Link allocated */
/* Get pointer to link's name in the heap */
- name = H5HL_offset_into(f, udata->heap, sn->entry[u].name_off);
+ name = (const char *)H5HL_offset_into(f, udata->heap, sn->entry[u].name_off);
HDassert(name);
/* Determine the link to operate on in the table */
@@ -2005,7 +1489,7 @@ H5G_node_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent,
* If we couldn't load the symbol table node, then try loading the
* B-tree node.
*/
- if (NULL == (sn = H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, NULL, NULL, H5AC_READ))) {
+ if (NULL == (sn = (H5G_node_t *)H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, NULL, NULL, H5AC_READ))) {
H5G_bt_common_t udata; /*data to pass through B-tree */
H5E_clear_stack(NULL); /* discard that error */
@@ -2030,7 +1514,7 @@ H5G_node_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent,
fprintf(stream, "%*sSymbol %u:\n", indent - 3, "", u);
if(heap) {
- const char *s = H5HL_offset_into(f, heap, sn->entry[u].name_off);
+ const char *s = (const char *)H5HL_offset_into(f, heap, sn->entry[u].name_off);
if(s)
fprintf(stream, "%*s%-*s `%s'\n", indent, "", fwidth, "Name:", s);
diff --git a/src/H5Gobj.c b/src/H5Gobj.c
index 00bac73..e0d5434 100644
--- a/src/H5Gobj.c
+++ b/src/H5Gobj.c
@@ -141,6 +141,10 @@ H5G_obj_create(H5F_t *f, hid_t dxpl_id, const H5O_ginfo_t *ginfo,
HDassert(ginfo);
HDassert(oloc);
+ /* Check for invalid access request */
+ if(0 == (f->intent & H5F_ACC_RDWR))
+ HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "no write intent on file")
+
/* Check for using the latest version of the group format */
/* (add more checks for creating "new format" groups when needed) */
if(H5F_USE_LATEST_FORMAT(f) || linfo->track_corder)
@@ -182,7 +186,7 @@ H5G_obj_create(H5F_t *f, hid_t dxpl_id, const H5O_ginfo_t *ginfo,
ginfo_size +
(ginfo->est_num_entries * link_size);
} /* end if */
- else
+ else
hdr_size = 4 + 2 * H5F_SIZEOF_ADDR(f);
/*
@@ -322,36 +326,41 @@ H5G_obj_ent_encode(const H5F_t *f, uint8_t **pp, const H5O_loc_t *oloc)
*
*-------------------------------------------------------------------------
*/
-H5O_linfo_t *
+htri_t
H5G_obj_get_linfo(const H5O_loc_t *grp_oloc, H5O_linfo_t *linfo, hid_t dxpl_id)
{
- H5O_linfo_t *ret_value; /* Return value */
-
- FUNC_ENTER_NOAPI(H5G_obj_get_linfo, NULL)
+ htri_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5G_obj_get_linfo, FAIL)
/* check arguments */
HDassert(grp_oloc);
+ HDassert(linfo);
+
+ /* Check for the group having a link info message */
+ if((ret_value = H5O_msg_exists(grp_oloc, H5O_LINFO_ID, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to read object header")
+ if(ret_value) {
+ /* Retrieve the "link info" structure */
+ if(NULL == H5O_msg_read(grp_oloc, H5O_LINFO_ID, linfo, dxpl_id))
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "link info message not present")
- /* Retrieve the "link info" structure */
- if((ret_value = H5O_msg_read(grp_oloc, H5O_LINFO_ID, linfo, dxpl_id))) {
/* Check if we don't know how many links there are */
- if(ret_value->nlinks == HSIZET_MAX) {
+ if(linfo->nlinks == HSIZET_MAX) {
/* Check if we are using "dense" link storage */
- if(H5F_addr_defined(ret_value->fheap_addr)) {
+ if(H5F_addr_defined(linfo->fheap_addr)) {
/* Retrieve # of records in "name" B-tree */
/* (should be same # of records in all indices) */
- if(H5B2_get_nrec(grp_oloc->file, dxpl_id, H5G_BT2_NAME, ret_value->name_bt2_addr, &ret_value->nlinks) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTGET, NULL, "can't retrieve # of records in index")
+ if(H5B2_get_nrec(grp_oloc->file, dxpl_id, H5G_BT2_NAME, linfo->name_bt2_addr, &linfo->nlinks) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve # of records in index")
} /* end if */
else {
/* Retrieve # of links from object header */
- if(H5O_get_nlinks(grp_oloc, dxpl_id, &ret_value->nlinks) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTGET, NULL, "can't retrieve # of links for object")
+ if(H5O_get_nlinks(grp_oloc, dxpl_id, &linfo->nlinks) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve # of links for object")
} /* end if */
} /* end if */
} /* end if */
- else
- HGOTO_ERROR(H5E_SYM, H5E_CANTGET, NULL, "link info message not present")
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -452,6 +461,7 @@ H5G_obj_insert(const H5O_loc_t *grp_oloc, const char *name, H5O_link_t *obj_lnk,
hbool_t adj_link, hid_t dxpl_id)
{
H5O_linfo_t linfo; /* Link info message */
+ htri_t linfo_exists; /* Whether the link info message exists */
hbool_t use_old_format; /* Whether to use 'old format' (symbol table) for insertions or not */
hbool_t use_new_dense = FALSE; /* Whether to use "dense" form of 'new format' group */
herr_t ret_value = SUCCEED; /* Return value */
@@ -465,7 +475,9 @@ H5G_obj_insert(const H5O_loc_t *grp_oloc, const char *name, H5O_link_t *obj_lnk,
/* Check if we have information about the number of objects in this group */
/* (by attempting to get the link info message for this group) */
- if(H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) {
+ if((linfo_exists = H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message")
+ if(linfo_exists) {
H5O_ginfo_t ginfo; /* Group info message */
size_t link_msg_size; /* Size of new link message in the file */
@@ -525,15 +537,11 @@ H5G_obj_insert(const H5O_loc_t *grp_oloc, const char *name, H5O_link_t *obj_lnk,
} /* end else */
} /* end if */
else {
- /* Clear error stack from not finding the link info message */
- H5E_clear_stack(NULL);
-
/* Check for new-style link information */
if(obj_lnk->cset != H5T_CSET_ASCII || obj_lnk->type > H5L_TYPE_BUILTIN_MAX) {
H5O_linfo_t new_linfo = H5G_CRT_LINK_INFO_DEF; /* Link information */
H5O_ginfo_t new_ginfo = H5G_CRT_GROUP_INFO_DEF; /* Group information */
H5G_obj_stab_it_ud1_t udata; /* User data for iteration */
- H5G_link_iterate_t lnk_op; /* Link operator */
/* Convert group to "new format" group, in order to hold the information */
@@ -549,12 +557,8 @@ H5G_obj_insert(const H5O_loc_t *grp_oloc, const char *name, H5O_link_t *obj_lnk,
udata.grp_oloc = grp_oloc;
udata.dxpl_id = dxpl_id;
- /* Build iterator operator */
- lnk_op.op_type = H5G_LINK_OP_LIB;
- lnk_op.u.lib_op = H5G_obj_stab_to_new_cb;
-
/* Iterate through all links in "old format" group and insert them into new format */
- if(H5G_stab_iterate(grp_oloc, dxpl_id, H5_ITER_NATIVE, (hsize_t)0, NULL, (hid_t)0, &lnk_op, &udata) < 0)
+ if(H5G_stab_iterate(grp_oloc, dxpl_id, H5_ITER_NATIVE, (hsize_t)0, NULL, H5G_obj_stab_to_new_cb, &udata) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTNEXT, FAIL, "error iterating over old format links")
/* Remove the symbol table message from the group */
@@ -636,36 +640,24 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5G_obj_iterate(hid_t loc_id, const char *group_name,
+H5G_obj_iterate(const H5O_loc_t *grp_oloc,
H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk,
- H5G_link_iterate_t *lnk_op, void *op_data, hid_t lapl_id, hid_t dxpl_id)
+ H5G_lib_iterate_t op, void *op_data, hid_t dxpl_id)
{
- H5G_loc_t loc; /* Location of parent for group */
H5O_linfo_t linfo; /* Link info message */
- hid_t gid = -1; /* ID of group to iterate over */
- H5G_t *grp; /* Pointer to group data structure to iterate over */
+ htri_t linfo_exists; /* Whether the link info message exists */
herr_t ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5G_obj_iterate, FAIL)
/* Sanity check */
- HDassert(group_name);
- HDassert(last_lnk);
- HDassert(lnk_op && lnk_op->u.lib_op);
-
- /*
- * Open the group on which to operate. We also create a group ID which
- * we can pass to the application-defined operator.
- */
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
- if(NULL == (grp = H5G_open_name(&loc, group_name, lapl_id, dxpl_id)))
- HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group")
- if((gid = H5I_register(H5I_GROUP, grp)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group")
+ HDassert(grp_oloc);
+ HDassert(op);
/* Attempt to get the link info for this group */
- if(H5G_obj_get_linfo(&(grp->oloc), &linfo, dxpl_id)) {
+ if((linfo_exists = H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message")
+ if(linfo_exists) {
/* Check for going out of bounds */
if(skip > 0 && (size_t)skip >= linfo.nlinks)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "index out of bound")
@@ -679,32 +671,26 @@ H5G_obj_iterate(hid_t loc_id, const char *group_name,
if(H5F_addr_defined(linfo.fheap_addr)) {
/* Iterate over the links in the group, building a table of the link messages */
- if((ret_value = H5G_dense_iterate(grp->oloc.file, dxpl_id, &linfo, idx_type, order, skip, last_lnk, gid, lnk_op, op_data)) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTNEXT, FAIL, "error iterating over links")
+ if((ret_value = H5G_dense_iterate(grp_oloc->file, dxpl_id, &linfo, idx_type, order, skip, last_lnk, op, op_data)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over dense links")
} /* end if */
else {
/* Get the object's name from the link messages */
- if((ret_value = H5G_compact_iterate(&(grp->oloc), dxpl_id, &linfo, idx_type, order, skip, last_lnk, gid, lnk_op, op_data)) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over links")
+ if((ret_value = H5G_compact_iterate(grp_oloc, dxpl_id, &linfo, idx_type, order, skip, last_lnk, op, op_data)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over compact links")
} /* end else */
} /* end if */
else {
- /* Clear error stack from not finding the link info message */
- H5E_clear_stack(NULL);
-
/* Can only perform name lookups on groups with symbol tables */
if(idx_type != H5_INDEX_NAME)
HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "no creation order index to query")
/* Iterate over symbol table */
- if((ret_value = H5G_stab_iterate(&(grp->oloc), dxpl_id, order, skip, last_lnk, gid, lnk_op, op_data)) < 0)
+ if((ret_value = H5G_stab_iterate(grp_oloc, dxpl_id, order, skip, last_lnk, op, op_data)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over symbol table")
} /* end else */
done:
- if(gid > 0)
- H5I_dec_ref(gid); /*also closes 'grp'*/
-
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5G_obj_iterate() */
@@ -725,7 +711,12 @@ done:
herr_t
H5G_obj_info(H5O_loc_t *oloc, H5G_info_t *grp_info, hid_t dxpl_id)
{
+ H5G_t *grp = NULL; /* Group to query */
+ H5G_loc_t grp_loc; /* Entry of group to be queried */
+ H5G_name_t grp_path; /* Group hier. path */
+ H5O_loc_t grp_oloc; /* Group object location */
H5O_linfo_t linfo; /* Link info message */
+ htri_t linfo_exists; /* Whether the link info message exists */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5G_obj_info, FAIL)
@@ -734,8 +725,26 @@ H5G_obj_info(H5O_loc_t *oloc, H5G_info_t *grp_info, hid_t dxpl_id)
HDassert(oloc);
HDassert(grp_info);
+ /* Set up group location to fill in */
+ grp_loc.oloc = &grp_oloc;
+ grp_loc.path = &grp_path;
+ H5G_loc_reset(&grp_loc);
+
+ /* Deep copy (duplicate) of the group location object */
+ if(H5O_loc_copy(&grp_oloc, oloc, H5_COPY_DEEP) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, FAIL, "can't copy object location")
+
+ /* Open the group */
+ if(NULL == (grp = H5G_open(&grp_loc, dxpl_id)))
+ HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "mount point not found")
+
+ /* Get information from the group */
+ grp_info->mounted = H5G_MOUNTED(grp);
+
/* Attempt to get the link info for this group */
- if(H5G_obj_get_linfo(oloc, &linfo, dxpl_id)) {
+ if((linfo_exists = H5G_obj_get_linfo(oloc, &linfo, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message")
+ if(linfo_exists) {
/* Retrieve the information about the links */
grp_info->nlinks = linfo.nlinks;
grp_info->max_corder = linfo.max_corder;
@@ -747,9 +756,6 @@ H5G_obj_info(H5O_loc_t *oloc, H5G_info_t *grp_info, hid_t dxpl_id)
grp_info->storage_type = H5G_STORAGE_TYPE_COMPACT;
} /* end if */
else {
- /* Clear error stack from not finding the link info message */
- H5E_clear_stack(NULL);
-
/* Get the number of objects in this group by iterating over symbol table */
if(H5G_stab_count(oloc, &grp_info->nlinks, dxpl_id) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTCOUNT, FAIL, "can't count objects")
@@ -760,6 +766,10 @@ H5G_obj_info(H5O_loc_t *oloc, H5G_info_t *grp_info, hid_t dxpl_id)
} /* end else */
done:
+ /* Clean up resources */
+ if(grp && H5G_close(grp) < 0)
+ HDONE_ERROR(H5E_SYM, H5E_CANTCLOSEOBJ, FAIL, "unable to close queried group")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5G_obj_info() */
@@ -782,6 +792,7 @@ H5G_obj_get_name_by_idx(H5O_loc_t *oloc, H5_index_t idx_type,
H5_iter_order_t order, hsize_t n, char* name, size_t size, hid_t dxpl_id)
{
H5O_linfo_t linfo; /* Link info message */
+ htri_t linfo_exists; /* Whether the link info message exists */
ssize_t ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5G_obj_get_name_by_idx, FAIL)
@@ -790,7 +801,9 @@ H5G_obj_get_name_by_idx(H5O_loc_t *oloc, H5_index_t idx_type,
HDassert(oloc && oloc->file);
/* Attempt to get the link info for this group */
- if(H5G_obj_get_linfo(oloc, &linfo, dxpl_id)) {
+ if((linfo_exists = H5G_obj_get_linfo(oloc, &linfo, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message")
+ if(linfo_exists) {
/* Check for creation order tracking, if creation order index lookup requested */
if(idx_type == H5_INDEX_CRT_ORDER) {
/* Check if creation order is tracked */
@@ -811,9 +824,6 @@ H5G_obj_get_name_by_idx(H5O_loc_t *oloc, H5_index_t idx_type,
} /* end else */
} /* end if */
else {
- /* Clear error stack from not finding the link info message */
- H5E_clear_stack(NULL);
-
/* Can only perform name lookups on groups with symbol tables */
if(idx_type != H5_INDEX_NAME)
HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "no creation order index to query")
@@ -904,7 +914,7 @@ H5G_obj_remove_update_linfo(H5O_loc_t *oloc, H5O_linfo_t *linfo, hid_t dxpl_id)
if(can_convert) {
/* Insert link messages into group */
for(u = 0; u < linfo->nlinks; u++)
- if(H5O_msg_append(oloc->file, dxpl_id, oh, H5O_LINK_ID, 0, H5O_UPDATE_TIME, &(ltable.lnks[u])) < 0) {
+ if(H5O_msg_append_oh(oloc->file, dxpl_id, oh, H5O_LINK_ID, 0, H5O_UPDATE_TIME, &(ltable.lnks[u])) < 0) {
/* Release object header */
if(H5O_unprotect(oloc, oh) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to unprotect dataset object header")
@@ -954,6 +964,7 @@ herr_t
H5G_obj_remove(H5O_loc_t *oloc, H5RS_str_t *grp_full_path_r, const char *name, hid_t dxpl_id)
{
H5O_linfo_t linfo; /* Link info message */
+ htri_t linfo_exists; /* Whether the link info message exists */
hbool_t use_old_format; /* Whether to use 'old format' (symbol table) for deletion or not */
herr_t ret_value = SUCCEED; /* Return value */
@@ -964,7 +975,9 @@ H5G_obj_remove(H5O_loc_t *oloc, H5RS_str_t *grp_full_path_r, const char *name, h
HDassert(name && *name);
/* Attempt to get the link info for this group */
- if(H5G_obj_get_linfo(oloc, &linfo, dxpl_id)) {
+ if((linfo_exists = H5G_obj_get_linfo(oloc, &linfo, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message")
+ if(linfo_exists) {
/* Using the new format for groups */
use_old_format = FALSE;
@@ -981,9 +994,6 @@ H5G_obj_remove(H5O_loc_t *oloc, H5RS_str_t *grp_full_path_r, const char *name, h
} /* end else */
} /* end if */
else {
- /* Clear error stack from not finding the link info message */
- H5E_clear_stack(NULL);
-
/* Using the old format for groups */
use_old_format = TRUE;
@@ -1020,6 +1030,7 @@ H5G_obj_remove_by_idx(H5O_loc_t *grp_oloc, H5RS_str_t *grp_full_path_r,
H5_index_t idx_type, H5_iter_order_t order, hsize_t n, hid_t dxpl_id)
{
H5O_linfo_t linfo; /* Link info message */
+ htri_t linfo_exists; /* Whether the link info message exists */
hbool_t use_old_format; /* Whether to use 'old format' (symbol table) for deletion or not */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1029,7 +1040,9 @@ H5G_obj_remove_by_idx(H5O_loc_t *grp_oloc, H5RS_str_t *grp_full_path_r,
HDassert(grp_oloc && grp_oloc->file);
/* Attempt to get the link info for this group */
- if(H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) {
+ if((linfo_exists = H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message")
+ if(linfo_exists) {
/* Check for creation order tracking, if creation order index lookup requested */
if(idx_type == H5_INDEX_CRT_ORDER) {
/* Check if creation order is tracked */
@@ -1092,12 +1105,13 @@ done:
*
*-------------------------------------------------------------------------
*/
-herr_t
+htri_t
H5G_obj_lookup(H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk,
hid_t dxpl_id)
{
H5O_linfo_t linfo; /* Link info message */
- herr_t ret_value = SUCCEED; /* Return value */
+ htri_t linfo_exists; /* Whether the link info message exists */
+ htri_t ret_value = FALSE; /* Return value */
FUNC_ENTER_NOAPI(H5G_obj_lookup, FAIL)
@@ -1106,25 +1120,24 @@ H5G_obj_lookup(H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk,
HDassert(name && *name);
/* Attempt to get the link info message for this group */
- if(H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) {
+ if((linfo_exists = H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message")
+ if(linfo_exists) {
/* Check for dense link storage */
if(H5F_addr_defined(linfo.fheap_addr)) {
/* Get the object's info from the dense link storage */
- if(H5G_dense_lookup(grp_oloc->file, dxpl_id, &linfo, name, lnk) < 0)
+ if((ret_value = H5G_dense_lookup(grp_oloc->file, dxpl_id, &linfo, name, lnk)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't locate object")
} /* end if */
else {
/* Get the object's info from the link messages */
- if(H5G_compact_lookup(grp_oloc, name, lnk, dxpl_id) < 0)
+ if((ret_value = H5G_compact_lookup(grp_oloc, name, lnk, dxpl_id)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't locate object")
} /* end else */
} /* end if */
else {
- /* Clear error stack from not finding the link info message */
- H5E_clear_stack(NULL);
-
/* Get the object's info from the symbol table */
- if(H5G_stab_lookup(grp_oloc, name, lnk, dxpl_id) < 0)
+ if((ret_value = H5G_stab_lookup(grp_oloc, name, lnk, dxpl_id)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't locate object")
} /* end else */
@@ -1152,6 +1165,7 @@ H5G_obj_lookup_by_idx(H5O_loc_t *grp_oloc, H5_index_t idx_type,
H5_iter_order_t order, hsize_t n, H5O_link_t *lnk, hid_t dxpl_id)
{
H5O_linfo_t linfo; /* Link info message */
+ htri_t linfo_exists; /* Whether the link info message exists */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5G_obj_lookup_by_idx, FAIL)
@@ -1160,7 +1174,9 @@ H5G_obj_lookup_by_idx(H5O_loc_t *grp_oloc, H5_index_t idx_type,
HDassert(grp_oloc && grp_oloc->file);
/* Attempt to get the link info message for this group */
- if(H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) {
+ if((linfo_exists = H5G_obj_get_linfo(grp_oloc, &linfo, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message")
+ if(linfo_exists) {
/* Check for creation order tracking, if creation order index lookup requested */
if(idx_type == H5_INDEX_CRT_ORDER) {
/* Check if creation order is tracked */
@@ -1181,9 +1197,6 @@ H5G_obj_lookup_by_idx(H5O_loc_t *grp_oloc, H5_index_t idx_type,
} /* end else */
} /* end if */
else {
- /* Clear error stack from not finding the link info message */
- H5E_clear_stack(NULL);
-
/* Can only perform name lookups on groups with symbol tables */
if(idx_type != H5_INDEX_NAME)
HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "no creation order index to query")
diff --git a/src/H5Goh.c b/src/H5Goh.c
index 3ccdf16..497badb 100644
--- a/src/H5Goh.c
+++ b/src/H5Goh.c
@@ -46,7 +46,8 @@
/********************/
static htri_t H5O_group_isa(H5O_t *loc);
-static hid_t H5O_group_open(const H5G_loc_t *obj_loc, hid_t dxpl_id);
+static hid_t H5O_group_open(const H5G_loc_t *obj_loc, hid_t lapl_id,
+ hid_t dxpl_id, hbool_t app_ref);
static void *H5O_group_create(H5F_t *f, void *_crt_info, H5G_loc_t *obj_loc,
hid_t dxpl_id);
static H5O_loc_t *H5O_group_get_oloc(hid_t obj_id);
@@ -134,7 +135,7 @@ done:
*-------------------------------------------------------------------------
*/
static hid_t
-H5O_group_open(const H5G_loc_t *obj_loc, hid_t dxpl_id)
+H5O_group_open(const H5G_loc_t *obj_loc, hid_t UNUSED lapl_id, hid_t dxpl_id, hbool_t app_ref)
{
H5G_t *grp = NULL; /* Group opened */
hid_t ret_value; /* Return value */
@@ -148,7 +149,7 @@ H5O_group_open(const H5G_loc_t *obj_loc, hid_t dxpl_id)
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group")
/* Register an ID for the group */
- if((ret_value = H5I_register(H5I_GROUP, grp)) < 0)
+ if((ret_value = H5I_register(H5I_GROUP, grp, app_ref)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group")
done:
@@ -231,7 +232,7 @@ H5O_group_get_oloc(hid_t obj_id)
FUNC_ENTER_NOAPI_NOINIT(H5O_group_get_oloc)
/* Get the group */
- if(NULL == (grp = H5I_object(obj_id)))
+ if(NULL == (grp = (H5G_t *)H5I_object(obj_id)))
HGOTO_ERROR(H5E_OHDR, H5E_BADATOM, NULL, "couldn't get object from ID")
/* Get the group's object header location */
@@ -271,7 +272,7 @@ H5O_group_bh_info(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5_ih_info_t *bh_info)
HDassert(bh_info);
/* Check for "new style" group info */
- if(NULL == H5O_msg_read_real(f, dxpl_id, oh, H5O_LINFO_ID, &linfo)) {
+ if(NULL == H5O_msg_read_real(f, dxpl_id, oh, H5O_LINFO_ID, &linfo)) {
H5O_stab_t stab; /* Info about symbol table */
/* Must be "old style" group, clear error stack */
@@ -280,7 +281,7 @@ H5O_group_bh_info(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5_ih_info_t *bh_info)
/* Get symbol table message */
if(NULL == H5O_msg_read_real(f, dxpl_id, oh, H5O_STAB_ID, &stab))
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't find LINFO nor STAB messages")
-
+
/* Get symbol table size info */
if(H5G_stab_bh_size(f, dxpl_id, &stab, bh_info) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve symbol table size info")
diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h
index f5b2582..31e5713 100644
--- a/src/H5Gpkg.h
+++ b/src/H5Gpkg.h
@@ -110,6 +110,19 @@ typedef struct H5G_entry_t {
} H5G_entry_t;
/*
+ * A symbol table node is a collection of symbol table entries. It can
+ * be thought of as the lowest level of the B-link tree that points to
+ * a collection of symbol table entries that belong to a specific symbol
+ * table or group.
+ */
+typedef struct H5G_node_t {
+ H5AC_info_t cache_info; /* Information for H5AC cache functions, _must_ be */
+ /* first field in structure */
+ unsigned nsyms; /*number of symbols */
+ H5G_entry_t *entry; /*array of symbol table entries */
+} H5G_node_t;
+
+/*
* Shared information for all open group objects
*/
struct H5G_shared_t {
@@ -134,18 +147,16 @@ typedef herr_t (*H5G_lib_iterate_t)(const H5O_link_t *lnk, void *op_data);
typedef struct {
enum {
#ifndef H5_NO_DEPRECATED_SYMBOLS
- H5G_LINK_OP_OLD, /* Old application callback */
+ H5G_LINK_OP_OLD, /* "Old" application callback */
#endif /* H5_NO_DEPRECATED_SYMBOLS */
- H5G_LINK_OP_APP, /* Application callback */
- H5G_LINK_OP_LIB /* Library internal callback */
+ H5G_LINK_OP_NEW /* "New" application callback */
} op_type;
union {
#ifndef H5_NO_DEPRECATED_SYMBOLS
- H5G_iterate_t old_op; /* Old application callback for each link */
+ H5G_iterate_t op_old; /* "Old" application callback for each link */
#endif /* H5_NO_DEPRECATED_SYMBOLS */
- H5L_iterate_t app_op; /* Application callback for each link */
- H5G_lib_iterate_t lib_op; /* Library internal callback for each link */
- } u;
+ H5L_iterate_t op_new; /* "New" application callback for each link */
+ } op_func;
} H5G_link_iterate_t;
/* Data structure to hold table of links for a group */
@@ -210,10 +221,9 @@ typedef struct H5G_bt_lkp_t {
*/
typedef struct H5G_bt_it_it_t {
/* downward */
- hid_t group_id; /*group id to pass to iteration operator */
H5HL_t *heap; /*symbol table heap */
hsize_t skip; /*initial entries to skip */
- H5G_link_iterate_t *lnk_op; /*iteration operator */
+ H5G_lib_iterate_t op; /*iteration operator */
void *op_data; /*user-defined operator data */
/* upward */
@@ -342,6 +352,9 @@ H5_DLL H5G_t *H5G_create_named(const H5G_loc_t *loc, const char *name,
hid_t lcpl_id, hid_t gcpl_id, hid_t gapl_id, hid_t dxpl_id);
H5_DLL H5G_t *H5G_open_name(const H5G_loc_t *loc, const char *name,
hid_t gapl_id, hid_t dxpl_id);
+H5_DLL herr_t H5G_iterate(hid_t loc_id, const char *group_name,
+ H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk,
+ const H5G_link_iterate_t *lnk_op, void *op_data, hid_t lapl_id, hid_t dxpl_id);
/*
* Group hierarchy traversal routines
@@ -374,9 +387,8 @@ H5_DLL herr_t H5G_stab_insert(const H5O_loc_t *grp_oloc, const char *name,
H5_DLL herr_t H5G_stab_insert_real(H5F_t *f, H5O_stab_t *stab, const char *name,
H5O_link_t *obj_lnk, hid_t dxpl_id);
H5_DLL herr_t H5G_stab_delete(H5F_t *f, hid_t dxpl_id, const H5O_stab_t *stab);
-H5_DLL herr_t H5G_stab_iterate(const H5O_loc_t *oloc, hid_t dxpl_id,
- H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk, hid_t gid,
- H5G_link_iterate_t *lnk_op, void *op_data);
+H5_DLL herr_t H5G_stab_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, H5_iter_order_t order,
+ hsize_t skip, hsize_t *last_lnk, H5G_lib_iterate_t op, void *op_data);
H5_DLL herr_t H5G_stab_count(struct H5O_loc_t *oloc, hsize_t *num_objs, hid_t dxpl_id);
H5_DLL herr_t H5G_stab_bh_size(H5F_t *f, hid_t dxpl_id, const H5O_stab_t *stab,
H5_ih_info_t *bh_info);
@@ -413,6 +425,7 @@ H5_DLL herr_t H5G_ent_debug(H5F_t *f, const H5G_entry_t *ent,
/* Functions that understand symbol table nodes */
H5_DLL herr_t H5G_node_init(H5F_t *f);
+H5_DLL size_t H5G_node_size_real(const H5F_t *f);
H5_DLL int H5G_node_iterate(H5F_t *f, hid_t dxpl_id, const void *_lt_key, haddr_t addr,
const void *_rt_key, void *_udata);
H5_DLL int H5G_node_sumup(H5F_t *f, hid_t dxpl_id, const void *_lt_key, haddr_t addr,
@@ -444,8 +457,7 @@ H5_DLL herr_t H5G_link_copy_file(H5F_t *dst_file, hid_t dxpl_id,
H5_DLL herr_t H5G_link_sort_table(H5G_link_table_t *ltable, H5_index_t idx_type,
H5_iter_order_t order);
H5_DLL herr_t H5G_link_iterate_table(const H5G_link_table_t *ltable,
- hsize_t skip, hsize_t *last_lnk, hid_t gid, const H5G_link_iterate_t *lnk_op,
- void *op_data);
+ hsize_t skip, hsize_t *last_lnk, const H5G_lib_iterate_t op, void *op_data);
H5_DLL herr_t H5G_link_release_table(H5G_link_table_t *ltable);
H5_DLL herr_t H5G_link_name_replace(H5F_t *file, hid_t dxpl_id,
H5RS_str_t *grp_full_path_r, const H5O_link_t *lnk);
@@ -461,10 +473,10 @@ H5_DLL herr_t H5G_compact_remove(const H5O_loc_t *oloc, hid_t dxpl_id,
H5_DLL herr_t H5G_compact_remove_by_idx(const H5O_loc_t *oloc, hid_t dxpl_id,
const H5O_linfo_t *linfo, H5RS_str_t *grp_full_path_r, H5_index_t idx_type,
H5_iter_order_t order, hsize_t n);
-H5_DLL herr_t H5G_compact_iterate(H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *linfo,
- H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk,
- hid_t gid, H5G_link_iterate_t *lnk_op, void *op_data);
-H5_DLL herr_t H5G_compact_lookup(H5O_loc_t *grp_oloc, const char *name,
+H5_DLL herr_t H5G_compact_iterate(const H5O_loc_t *oloc, hid_t dxpl_id,
+ const H5O_linfo_t *linfo, H5_index_t idx_type, H5_iter_order_t order,
+ hsize_t skip, hsize_t *last_lnk, H5G_lib_iterate_t op, void *op_data);
+H5_DLL htri_t H5G_compact_lookup(H5O_loc_t *grp_oloc, const char *name,
H5O_link_t *lnk, hid_t dxpl_id);
H5_DLL herr_t H5G_compact_lookup_by_idx(H5O_loc_t *oloc, hid_t dxpl_id,
const H5O_linfo_t *linfo, H5_index_t idx_type, H5_iter_order_t order,
@@ -480,14 +492,14 @@ H5_DLL herr_t H5G_dense_build_table(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *
H5_DLL herr_t H5G_dense_create(H5F_t *f, hid_t dxpl_id, H5O_linfo_t *linfo);
H5_DLL herr_t H5G_dense_insert(H5F_t *f, hid_t dxpl_id,
const H5O_linfo_t *linfo, const H5O_link_t *lnk);
-H5_DLL herr_t H5G_dense_lookup(H5F_t *f, hid_t dxpl_id,
+H5_DLL htri_t H5G_dense_lookup(H5F_t *f, hid_t dxpl_id,
const H5O_linfo_t *linfo, const char *name, H5O_link_t *lnk);
H5_DLL herr_t H5G_dense_lookup_by_idx(H5F_t *f, hid_t dxpl_id,
const H5O_linfo_t *linfo, H5_index_t idx_type, H5_iter_order_t order,
hsize_t n, H5O_link_t *lnk);
H5_DLL herr_t H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo,
H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk,
- hid_t gid, const H5G_link_iterate_t *lnk_op, void *op_data);
+ H5G_lib_iterate_t op, void *op_data);
H5_DLL ssize_t H5G_dense_get_name_by_idx(H5F_t *f, hid_t dxpl_id,
H5O_linfo_t *linfo, H5_index_t idx_type, H5_iter_order_t order, hsize_t n,
char *name, size_t size);
@@ -506,13 +518,13 @@ H5_DLL H5G_obj_t H5G_dense_get_type_by_idx(H5F_t *f, hid_t dxpl_id,
/* Functions that understand group objects */
H5_DLL herr_t H5G_obj_create(H5F_t *f, hid_t dxpl_id, const H5O_ginfo_t *ginfo,
const H5O_linfo_t *linfo, hid_t gcpl_id, H5O_loc_t *oloc/*out*/);
-H5_DLL H5O_linfo_t * H5G_obj_get_linfo(const H5O_loc_t *grp_oloc,
- H5O_linfo_t *linfo, hid_t dxpl_id);
+H5_DLL htri_t H5G_obj_get_linfo(const H5O_loc_t *grp_oloc, H5O_linfo_t *linfo,
+ hid_t dxpl_id);
H5_DLL herr_t H5G_obj_insert(const H5O_loc_t *grp_oloc, const char *name,
H5O_link_t *obj_lnk, hbool_t adj_link, hid_t dxpl_id);
-H5_DLL herr_t H5G_obj_iterate(hid_t loc_id, const char *group_name,
- H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_obj,
- H5G_link_iterate_t *lnk_op, void *op_data, hid_t lapl_id, hid_t dxpl_id);
+H5_DLL herr_t H5G_obj_iterate(const H5O_loc_t *grp_oloc,
+ H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_lnk,
+ H5G_lib_iterate_t op, void *op_data, hid_t dxpl_id);
H5_DLL herr_t H5G_obj_info(H5O_loc_t *oloc, H5G_info_t *grp_info, hid_t dxpl_id);
H5_DLL ssize_t H5G_obj_get_name_by_idx(H5O_loc_t *oloc, H5_index_t idx_type,
H5_iter_order_t order, hsize_t n, char* name, size_t size, hid_t dxpl_id);
@@ -520,7 +532,7 @@ H5_DLL herr_t H5G_obj_remove(H5O_loc_t *oloc, H5RS_str_t *grp_full_path_r,
const char *name, hid_t dxpl_id);
H5_DLL herr_t H5G_obj_remove_by_idx(H5O_loc_t *grp_oloc, H5RS_str_t *grp_full_path_r,
H5_index_t idx_type, H5_iter_order_t order, hsize_t n, hid_t dxpl_id);
-H5_DLL herr_t H5G_obj_lookup(H5O_loc_t *grp_oloc, const char *name,
+H5_DLL htri_t H5G_obj_lookup(H5O_loc_t *grp_oloc, const char *name,
H5O_link_t *lnk, hid_t dxpl_id);
H5_DLL herr_t H5G_obj_lookup_by_idx(H5O_loc_t *grp_oloc, H5_index_t idx_type,
H5_iter_order_t order, hsize_t n, H5O_link_t *lnk, hid_t dxpl_id);
diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h
index 9717b77..591be6b 100644
--- a/src/H5Gprivate.h
+++ b/src/H5Gprivate.h
@@ -43,9 +43,6 @@
# undef H5G_DEBUG
#endif
-#define H5G_NODE_MAGIC "SNOD" /*symbol table node magic number */
-#define H5G_NODE_SIZEOF_MAGIC 4 /*sizeof symbol node magic number */
-
/*
* The disk size for a symbol table entry...
*/
@@ -101,6 +98,12 @@
H5G_CRT_GINFO_EST_NAME_LEN \
}
+/* If the module using this macro is allowed access to the private variables, access them directly */
+#ifdef H5G_PACKAGE
+#define H5G_MOUNTED(G) ((G)->shared->mounted)
+#else /* H5G_PACKAGE */
+#define H5G_MOUNTED(G) (H5G_mounted(G))
+#endif /* H5G_PACKAGE */
/* Type of operation being performed for call to H5G_name_replace() */
typedef enum {
@@ -158,10 +161,14 @@ H5_DLL herr_t H5G_close(H5G_t *grp);
H5_DLL herr_t H5G_free_grp_name(H5G_t *grp);
H5_DLL herr_t H5G_get_shared_count(H5G_t *grp);
H5_DLL herr_t H5G_mount(H5G_t *grp);
+H5_DLL hbool_t H5G_mounted(H5G_t *grp);
H5_DLL herr_t H5G_unmount(H5G_t *grp);
#ifndef H5_NO_DEPRECATED_SYMBOLS
H5_DLL H5G_obj_t H5G_map_obj_type(H5O_type_t obj_type);
#endif /* H5_NO_DEPRECATED_SYMBOLS */
+H5_DLL herr_t H5G_visit(hid_t loc_id, const char *group_name,
+ H5_index_t idx_type, H5_iter_order_t order, H5L_iterate_t op, void *op_data,
+ hid_t lapl_id, hid_t dxpl_id);
/*
* These functions operate on symbol table nodes.
@@ -189,7 +196,7 @@ H5_DLL herr_t H5G_name_copy(H5G_name_t *dst, const H5G_name_t *src, H5_copy_dept
H5_DLL herr_t H5G_name_free(H5G_name_t *name);
H5_DLL ssize_t H5G_get_name(hid_t id, char *name/*out*/, size_t size,
hid_t lapl_id, hid_t dxpl_id);
-H5_DLL ssize_t H5G_get_refobj_name(hid_t fid, hid_t lapl_id, hid_t dxpl_id,
+H5_DLL ssize_t H5G_get_name_by_addr(hid_t fid, hid_t lapl_id, hid_t dxpl_id,
const struct H5O_loc_t *loc, char* name, size_t size);
/*
diff --git a/src/H5Gpublic.h b/src/H5Gpublic.h
index e818e72..5b8b054 100644
--- a/src/H5Gpublic.h
+++ b/src/H5Gpublic.h
@@ -61,6 +61,7 @@ typedef struct H5G_info_t {
H5G_storage_type_t storage_type; /* Type of storage for links in group */
hsize_t nlinks; /* Number of links in group */
int64_t max_corder; /* Current max. creation order value for group */
+ hbool_t mounted; /* Whether group has a file mounted on it */
} H5G_info_t;
/********************/
@@ -85,7 +86,7 @@ H5_DLL herr_t H5Gget_info_by_idx(hid_t loc_id, const char *group_name,
H5_DLL herr_t H5Gclose(hid_t group_id);
/* Symbols defined for compatibility with previous versions of the HDF5 API.
- *
+ *
* Use of these symbols is deprecated.
*/
#ifndef H5_NO_DEPRECATED_SYMBOLS
diff --git a/src/H5Gstab.c b/src/H5Gstab.c
index 1887943..f79d78b 100644
--- a/src/H5Gstab.c
+++ b/src/H5Gstab.c
@@ -484,8 +484,7 @@ done:
*/
herr_t
H5G_stab_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, H5_iter_order_t order,
- hsize_t skip, hsize_t *last_lnk, hid_t gid,
- H5G_link_iterate_t *lnk_op, void *op_data)
+ hsize_t skip, hsize_t *last_lnk, H5G_lib_iterate_t op, void *op_data)
{
H5HL_t *heap = NULL; /* Local heap for group */
H5O_stab_t stab; /* Info about symbol table */
@@ -496,7 +495,7 @@ H5G_stab_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, H5_iter_order_t order,
/* Sanity check */
HDassert(oloc);
- HDassert(lnk_op && lnk_op->u.app_op);
+ HDassert(op);
/* Get the B-tree info */
if(NULL == H5O_msg_read(oloc, H5O_STAB_ID, &stab, dxpl_id))
@@ -512,15 +511,14 @@ H5G_stab_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, H5_iter_order_t order,
H5G_bt_it_it_t udata; /* User data to pass to B-tree callback */
/* Build udata to pass through H5B_iterate() to H5G_node_iterate() */
- udata.group_id = gid;
udata.heap = heap;
udata.skip = skip;
udata.final_ent = last_lnk;
- udata.lnk_op = lnk_op;
+ udata.op = op;
udata.op_data = op_data;
/* Iterate over the group members */
- if((ret_value = H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, H5G_node_iterate, stab.btree_addr, &udata)) < 0)
+ if((ret_value = H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, H5G_node_iterate, &udata)) < 0)
HERROR(H5E_SYM, H5E_CANTNEXT, "iteration operator failed");
/* Check for too high of a starting index (ex post facto :-) */
@@ -537,8 +535,7 @@ H5G_stab_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, H5_iter_order_t order,
udata.ltable = &ltable;
/* Iterate over the group members */
- if(H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, H5G_node_build_table,
- stab.btree_addr, &udata) < 0)
+ if(H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, H5G_node_build_table, &udata) < 0)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to build link table")
/* Check for skipping out of bounds */
@@ -550,7 +547,7 @@ H5G_stab_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, H5_iter_order_t order,
HGOTO_ERROR(H5E_SYM, H5E_CANTSORT, FAIL, "error sorting link messages")
/* Iterate over links in table */
- if((ret_value = H5G_link_iterate_table(&ltable, skip, last_lnk, gid, lnk_op, op_data)) < 0)
+ if((ret_value = H5G_link_iterate_table(&ltable, skip, last_lnk, op, op_data)) < 0)
HERROR(H5E_SYM, H5E_CANTNEXT, "iteration operator failed");
} /* end else */
@@ -597,7 +594,7 @@ H5G_stab_count(H5O_loc_t *oloc, hsize_t *num_objs, hid_t dxpl_id)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to determine local heap address")
/* Iterate over the group members */
- if(H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, H5G_node_sumup, stab.btree_addr, num_objs) < 0)
+ if(H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, H5G_node_sumup, num_objs) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "iteration operator failed")
done:
@@ -618,10 +615,12 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5G_stab_bh_size(H5F_t *f, hid_t dxpl_id, const H5O_stab_t *stab, H5_ih_info_t *bh_info)
+H5G_stab_bh_size(H5F_t *f, hid_t dxpl_id, const H5O_stab_t *stab,
+ H5_ih_info_t *bh_info)
{
- H5B_info_ud_t bh_udata; /* User-data for B-tree callbacks */
- herr_t ret_value = SUCCEED;
+ hsize_t snode_size; /* Symbol table node size */
+ H5B_info_t bt_info; /* B-tree node info */
+ herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(H5G_stab_bh_size, FAIL)
@@ -630,14 +629,16 @@ H5G_stab_bh_size(H5F_t *f, hid_t dxpl_id, const H5O_stab_t *stab, H5_ih_info_t *
HDassert(stab);
HDassert(bh_info);
- /* Set up user data for B-tree callback */
- bh_udata.udata = NULL;
- bh_udata.btree_size = &(bh_info->index_size);
+ /* Set up user data for B-tree iteration */
+ snode_size = 0;
/* Get the B-tree & symbol table node size info */
- if(H5B_iterate_size(f, dxpl_id, H5B_SNODE, H5G_node_iterate_size, stab->btree_addr, &bh_udata) < 0)
+ if(H5B_get_info(f, dxpl_id, H5B_SNODE, stab->btree_addr, &bt_info, H5G_node_iterate_size, &snode_size) < 0)
HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "iteration operator failed")
+ /* Add symbol table & B-tree node sizes to index info */
+ bh_info->index_size += snode_size + bt_info.size;
+
/* Get the size of the local heap for the group */
if(H5HL_heapsize(f, dxpl_id, stab->heap_addr, &(bh_info->heap_size)) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "iteration operator failed")
@@ -650,7 +651,7 @@ done:
/*-------------------------------------------------------------------------
* Function: H5G_stab_get_name_by_idx_cb
*
- * Purpose: Callback for B-tree iteration 'by index' info query to
+ * Purpose: Callback for B-tree iteration 'by index' info query to
* retrieve the name of a link
*
* Return: Success: Non-negative
@@ -676,7 +677,7 @@ H5G_stab_get_name_by_idx_cb(const H5G_entry_t *ent, void *_udata)
/* Get name offset in heap */
name_off = ent->name_off;
- name = H5HL_offset_into(udata->common.f, udata->heap, name_off);
+ name = (const char *)H5HL_offset_into(udata->common.f, udata->heap, name_off);
HDassert(name);
udata->name = H5MM_strdup(name);
HDassert(udata->name);
@@ -725,7 +726,7 @@ H5G_stab_get_name_by_idx(H5O_loc_t *oloc, H5_iter_order_t order, hsize_t n,
hsize_t nlinks = 0; /* Number of links in group */
/* Iterate over the symbol table nodes, to count the links */
- if(H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, H5G_node_sumup, stab.btree_addr, &nlinks) < 0)
+ if(H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, H5G_node_sumup, &nlinks) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "iteration operator failed")
/* Map decreasing iteration order index to increasing iteration order index */
@@ -741,7 +742,7 @@ H5G_stab_get_name_by_idx(H5O_loc_t *oloc, H5_iter_order_t order, hsize_t n,
udata.name = NULL;
/* Iterate over the group members */
- if(H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, H5G_node_by_idx, stab.btree_addr, &udata) < 0)
+ if(H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, H5G_node_by_idx, &udata) < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "iteration operator failed")
/* If we don't know the name now, we almost certainly went out of bounds */
@@ -809,7 +810,7 @@ done:
*
* Purpose: Look up an object relative to a group, using symbol table
*
- * Return: Non-negative on success/Negative on failure
+ * Return: Non-negative (TRUE/FALSE) on success/Negative on failure
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
@@ -817,7 +818,7 @@ done:
*
*-------------------------------------------------------------------------
*/
-herr_t
+htri_t
H5G_stab_lookup(H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk,
hid_t dxpl_id)
{
@@ -825,7 +826,7 @@ H5G_stab_lookup(H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk,
H5G_bt_lkp_t bt_udata; /* Data to pass through B-tree */
H5G_stab_fnd_ud_t udata; /* 'User data' to give to callback */
H5O_stab_t stab; /* Symbol table message */
- herr_t ret_value = SUCCEED; /* Return value */
+ htri_t ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5G_stab_lookup, FAIL)
@@ -855,7 +856,7 @@ H5G_stab_lookup(H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk,
bt_udata.op_data = &udata;
/* Search the B-tree */
- if(H5B_find(grp_oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, &bt_udata) < 0)
+ if((ret_value = H5B_find(grp_oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, &bt_udata)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "not found")
done:
@@ -870,7 +871,7 @@ done:
/*-------------------------------------------------------------------------
* Function: H5G_stab_lookup_by_idx_cb
*
- * Purpose: Callback for B-tree iteration 'by index' info query to
+ * Purpose: Callback for B-tree iteration 'by index' info query to
* retrieve the link
*
* Return: Success: Non-negative
@@ -895,7 +896,7 @@ H5G_stab_lookup_by_idx_cb(const H5G_entry_t *ent, void *_udata)
HDassert(udata && udata->heap);
/* Get a pointer to the link name */
- name = H5HL_offset_into(udata->common.f, udata->heap, ent->name_off);
+ name = (const char *)H5HL_offset_into(udata->common.f, udata->heap, ent->name_off);
HDassert(name);
/* Convert the entry to a link */
@@ -949,7 +950,7 @@ H5G_stab_lookup_by_idx(H5O_loc_t *grp_oloc, H5_iter_order_t order, hsize_t n,
hsize_t nlinks = 0; /* Number of links in group */
/* Iterate over the symbol table nodes, to count the links */
- if(H5B_iterate(grp_oloc->file, dxpl_id, H5B_SNODE, H5G_node_sumup, stab.btree_addr, &nlinks) < 0)
+ if(H5B_iterate(grp_oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, H5G_node_sumup, &nlinks) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "iteration operator failed")
/* Map decreasing iteration order index to increasing iteration order index */
@@ -966,7 +967,7 @@ H5G_stab_lookup_by_idx(H5O_loc_t *grp_oloc, H5_iter_order_t order, hsize_t n,
udata.found = FALSE;
/* Iterate over the group members */
- if(H5B_iterate(grp_oloc->file, dxpl_id, H5B_SNODE, H5G_node_by_idx, stab.btree_addr, &udata) < 0)
+ if(H5B_iterate(grp_oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, H5G_node_by_idx, &udata) < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "iteration operator failed")
/* If we didn't find the link, we almost certainly went out of bounds */
@@ -986,7 +987,7 @@ done:
/*-------------------------------------------------------------------------
* Function: H5G_stab_get_type_by_idx_cb
*
- * Purpose: Callback for B-tree iteration 'by index' info query to
+ * Purpose: Callback for B-tree iteration 'by index' info query to
* retrieve the type of an object
*
* Return: Success: Non-negative
@@ -1078,7 +1079,7 @@ H5G_stab_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx, hid_t dxpl_id)
udata.type = H5G_UNKNOWN;
/* Iterate over the group members */
- if(H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, H5G_node_by_idx, stab.btree_addr, &udata) < 0)
+ if(H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, H5G_node_by_idx, &udata) < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "iteration operator failed")
/* If we don't know the type now, we almost certainly went out of bounds */
diff --git a/src/H5Gtest.c b/src/H5Gtest.c
index 2921bf0..d7f102f 100644
--- a/src/H5Gtest.c
+++ b/src/H5Gtest.c
@@ -102,7 +102,7 @@ H5G_is_empty_test(hid_t gid)
FUNC_ENTER_NOAPI(H5G_is_empty_test, FAIL)
/* Get group structure */
- if(NULL == (grp = H5I_object_verify(gid, H5I_GROUP)))
+ if(NULL == (grp = (H5G_t *)H5I_object_verify(gid, H5I_GROUP)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group")
/* "New format" checks */
@@ -133,7 +133,7 @@ H5G_is_empty_test(hid_t gid)
HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "both symbol table and link info messages found")
/* Get the link info */
- if(NULL == H5G_obj_get_linfo(&(grp->oloc), &linfo, H5AC_dxpl_id))
+ if(H5G_obj_get_linfo(&(grp->oloc), &linfo, H5AC_dxpl_id) < 0)
HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't get link info")
/* Check for 'dense' link storage file addresses being defined */
@@ -213,7 +213,7 @@ H5G_has_links_test(hid_t gid, unsigned *nmsgs)
FUNC_ENTER_NOAPI(H5G_has_links_test, FAIL)
/* Get group structure */
- if(NULL == (grp = H5I_object_verify(gid, H5I_GROUP)))
+ if(NULL == (grp = (H5G_t *)H5I_object_verify(gid, H5I_GROUP)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group")
/* Check if the group has any link messages */
@@ -271,7 +271,7 @@ H5G_has_stab_test(hid_t gid)
FUNC_ENTER_NOAPI(H5G_has_stab_test, FAIL)
/* Get group structure */
- if(NULL == (grp = H5I_object_verify(gid, H5I_GROUP)))
+ if(NULL == (grp = (H5G_t *)H5I_object_verify(gid, H5I_GROUP)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group")
/* Check if the group has a symbol table message */
@@ -321,7 +321,7 @@ H5G_is_new_dense_test(hid_t gid)
FUNC_ENTER_NOAPI(H5G_is_new_dense_test, FAIL)
/* Get group structure */
- if(NULL == (grp = H5I_object_verify(gid, H5I_GROUP)))
+ if(NULL == (grp = (H5G_t *)H5I_object_verify(gid, H5I_GROUP)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group")
/* Check if the group has a symbol table message */
@@ -343,7 +343,7 @@ H5G_is_new_dense_test(hid_t gid)
H5O_linfo_t linfo; /* Link info message */
/* Get the link info */
- if(NULL == H5G_obj_get_linfo(&(grp->oloc), &linfo, H5AC_dxpl_id))
+ if(H5G_obj_get_linfo(&(grp->oloc), &linfo, H5AC_dxpl_id) < 0)
HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't get link info")
/* Check for 'dense' link storage file addresses being defined */
@@ -389,11 +389,11 @@ H5G_new_dense_info_test(hid_t gid, hsize_t *name_count, hsize_t *corder_count)
FUNC_ENTER_NOAPI(H5G_new_dense_info_test, FAIL)
/* Get group structure */
- if(NULL == (grp = H5I_object_verify(gid, H5I_GROUP)))
+ if(NULL == (grp = (H5G_t *)H5I_object_verify(gid, H5I_GROUP)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group")
/* Get the link info */
- if(NULL == H5G_obj_get_linfo(&(grp->oloc), &linfo, H5AC_dxpl_id))
+ if(H5G_obj_get_linfo(&(grp->oloc), &linfo, H5AC_dxpl_id) < 0)
HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't get link info")
/* Check for 'dense' link storage file addresses being defined */
@@ -449,7 +449,7 @@ H5G_lheap_size_test(hid_t gid, size_t *lheap_size)
FUNC_ENTER_NOAPI(H5G_lheap_size_test, FAIL)
/* Get group structure */
- if(NULL == (grp = H5I_object_verify(gid, H5I_GROUP)))
+ if(NULL == (grp = (H5G_t *)H5I_object_verify(gid, H5I_GROUP)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group")
/* Make certain the group has a symbol table message */
diff --git a/src/H5Gtraverse.c b/src/H5Gtraverse.c
index 4fc345c..87ebc74 100644
--- a/src/H5Gtraverse.c
+++ b/src/H5Gtraverse.c
@@ -89,7 +89,7 @@ H5G_traverse_term_interface(void)
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_traverse_term_interface)
/* Free the global component buffer */
- H5G_comp_g = H5MM_xfree(H5G_comp_g);
+ H5G_comp_g = (char *)H5MM_xfree(H5G_comp_g);
H5G_comp_alloc_g = 0;
FUNC_LEAVE_NOAPI(SUCCEED)
@@ -194,27 +194,27 @@ H5G_traverse_ud(const H5G_loc_t *grp_loc/*in,out*/, const H5O_link_t *lnk,
/* Create a group to pass to the user-defined callback */
if((grp = H5G_open(&grp_loc_copy, dxpl_id)) == NULL)
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group")
- if((cur_grp = H5I_register(H5I_GROUP, grp)) < 0)
+ if((cur_grp = H5I_register(H5I_GROUP, grp, FALSE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group")
/* Check for generic default property list and use link access default if so */
if(_lapl_id == H5P_DEFAULT) {
HDassert(H5P_LINK_ACCESS_DEFAULT != -1);
- if(NULL == (lapl = H5I_object(H5P_LINK_ACCESS_DEFAULT)))
+ if(NULL == (lapl = (H5P_genplist_t *)H5I_object(H5P_LINK_ACCESS_DEFAULT)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "unable to get default property list")
} /* end if */
else {
/* Get the underlying property list passed in */
- if(NULL == (lapl = H5I_object(_lapl_id)))
+ if(NULL == (lapl = (H5P_genplist_t *)H5I_object(_lapl_id)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "unable to get property list from ID")
} /* end else */
/* Copy the property list passed in */
- if((lapl_id = H5P_copy_plist(lapl)) < 0)
+ if((lapl_id = H5P_copy_plist(lapl, FALSE)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "unable to copy property list")
/* Get the underlying property list copy */
- if(NULL == (lapl = H5I_object(lapl_id)))
+ if(NULL == (lapl = (H5P_genplist_t *)H5I_object(lapl_id)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "unable to get property list from ID")
/* Record number of soft links left to traverse in the property list. */
@@ -228,22 +228,22 @@ H5G_traverse_ud(const H5G_loc_t *grp_loc/*in,out*/, const H5O_link_t *lnk,
/* Get the oloc from the ID the user callback returned */
switch(H5I_get_type(cb_return)) {
case H5I_GROUP:
- if((new_oloc = H5G_oloc(H5I_object(cb_return))) == NULL)
+ if((new_oloc = H5G_oloc((H5G_t *)H5I_object(cb_return))) == NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location from group ID")
break;
case H5I_DATASET:
- if((new_oloc = H5D_oloc(H5I_object(cb_return))) ==NULL)
+ if((new_oloc = H5D_oloc((H5D_t *)H5I_object(cb_return))) ==NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location from dataset ID")
break;
case H5I_DATATYPE:
- if((new_oloc = H5T_oloc(H5I_object(cb_return))) ==NULL)
+ if((new_oloc = H5T_oloc((H5T_t *)H5I_object(cb_return))) ==NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location from datatype ID")
break;
case H5I_FILE:
- if((temp_file = H5I_object(cb_return)) == NULL)
+ if((temp_file = (H5F_t *)H5I_object(cb_return)) == NULL)
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "couldn't get file from ID")
if((new_oloc = H5G_oloc(temp_file->shared->root_grp)) ==NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get root group location from file ID")
@@ -266,22 +266,22 @@ H5G_traverse_ud(const H5G_loc_t *grp_loc/*in,out*/, const H5O_link_t *lnk,
/* We have a copy of the location and we're holding the file open.
* Close the open ID the user passed back.
*/
- if(H5I_dec_ref(cb_return) < 0)
+ if(H5I_dec_ref(cb_return, FALSE) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTRELEASE, FAIL, "unable to close atom from UD callback")
cb_return = (-1);
done:
/* Close location given to callback. */
if(cur_grp > 0)
- if(H5I_dec_ref(cur_grp) < 0)
+ if(H5I_dec_ref(cur_grp, FALSE) < 0)
HDONE_ERROR(H5E_ATOM, H5E_CANTRELEASE, FAIL, "unable to close atom for current location")
if(ret_value < 0 && cb_return > 0)
- if(H5I_dec_ref(cb_return) < 0)
+ if(H5I_dec_ref(cb_return, FALSE) < 0)
HDONE_ERROR(H5E_ATOM, H5E_CANTRELEASE, FAIL, "unable to close atom from UD callback")
/* Close the LAPL, if we copied one */
- if(lapl_id > 0 && H5I_dec_ref(lapl_id) < 0)
+ if(lapl_id > 0 && H5I_dec_ref(lapl_id, FALSE) < 0)
HDONE_ERROR(H5E_ATOM, H5E_CANTRELEASE, FAIL, "unable to close copied link access property list")
FUNC_LEAVE_NOAPI(ret_value)
@@ -384,7 +384,8 @@ done:
static herr_t
H5G_traverse_mount(H5G_loc_t *obj_loc/*in,out*/)
{
- H5F_t *parent = obj_loc->oloc->file; /* File of object */
+ H5F_t *parent = obj_loc->oloc->file, /* File of object */
+ *child = NULL; /* Child file */
unsigned lt, rt, md = 0; /* Binary search indices */
int cmp;
H5O_loc_t *oloc = NULL; /* Object location for mount points */
@@ -405,11 +406,11 @@ H5G_traverse_mount(H5G_loc_t *obj_loc/*in,out*/)
* table for the parent
*/
lt = 0;
- rt = parent->mtab.nmounts;
+ rt = parent->shared->mtab.nmounts;
cmp = -1;
while(lt < rt && cmp) {
md = (lt + rt) / 2;
- oloc = H5G_oloc(parent->mtab.child[md].group);
+ oloc = H5G_oloc(parent->shared->mtab.child[md].group);
cmp = H5F_addr_cmp(obj_loc->oloc->addr, oloc->addr);
if(cmp < 0)
rt = md;
@@ -418,17 +419,28 @@ H5G_traverse_mount(H5G_loc_t *obj_loc/*in,out*/)
} /* end while */
/* Copy root info over to ENT */
- if(0 == cmp) {
- /* Get the location for the root group in the child's file */
- oloc = H5G_oloc(parent->mtab.child[md].file->shared->root_grp);
+ if(0 == cmp) {
+ /* Get the child file */
+ child = parent->shared->mtab.child[md].file;
- /* Copy the entry for the root group */
- if(H5O_loc_copy(obj_loc->oloc, oloc, H5_COPY_DEEP) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, FAIL, "unable to copy object location")
+ /* Get the location for the root group in the child's file */
+ oloc = H5G_oloc(child->shared->root_grp);
- /* Switch to child's file */
- parent = oloc->file;
- } /* end if */
+ /* Release the mount point */
+ if(H5O_loc_free(obj_loc->oloc) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "unable to free object location")
+
+ /* Copy the entry for the root group */
+ if(H5O_loc_copy(obj_loc->oloc, oloc, H5_COPY_DEEP) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, FAIL, "unable to copy object location")
+
+ /* In case the shared root group info points to a different file handle
+ * than the child, modify obj_loc */
+ obj_loc->oloc->file = child;
+
+ /* Switch to child's file */
+ parent = child;
+ } /* end if */
} while(!cmp);
done:
@@ -612,7 +624,7 @@ H5G_traverse_real(const H5G_loc_t *_loc, const char *name, unsigned target,
size_t new_alloc; /* New component buffer size */
new_alloc = MAX3(1024, (2 * H5G_comp_alloc_g), (HDstrlen(name) + 1));
- if(NULL == (new_comp = H5MM_realloc(H5G_comp_g, new_alloc)))
+ if(NULL == (new_comp = (char *)H5MM_realloc(H5G_comp_g, new_alloc)))
HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "unable to allocate component buffer")
H5G_comp_g = new_comp;
H5G_comp_alloc_g = new_alloc;
@@ -621,7 +633,7 @@ H5G_traverse_real(const H5G_loc_t *_loc, const char *name, unsigned target,
/* Traverse the path */
while((name = H5G_component(name, &nchars)) && *name) {
const char *s; /* Temporary string pointer */
- herr_t lookup_status; /* Status from object lookup */
+ htri_t lookup_status; /* Status from object lookup */
/*
* Copy the component name into a null-terminated buffer so
@@ -649,11 +661,11 @@ H5G_traverse_real(const H5G_loc_t *_loc, const char *name, unsigned target,
} /* end if */
/* Get information for object in current group */
- /* (Defer issuing error for bad lookup until later) */
- lookup_status = H5G_obj_lookup(grp_loc.oloc, H5G_comp_g, &lnk/*out*/, dxpl_id);
+ if((lookup_status = H5G_obj_lookup(grp_loc.oloc, H5G_comp_g, &lnk/*out*/, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't look up component")
/* If the lookup was OK, build object location and traverse special links, etc. */
- if(lookup_status >= 0) {
+ if(lookup_status) {
/* Sanity check link and indicate it's valid */
HDassert(lnk.type >= H5L_TYPE_HARD);
HDassert(!HDstrcmp(H5G_comp_g, lnk.name));
@@ -676,14 +688,14 @@ H5G_traverse_real(const H5G_loc_t *_loc, const char *name, unsigned target,
H5G_loc_t *cb_loc; /* Pointer to object location for callback */
/* Set callback parameters appropriately, based on link being found */
- if(lookup_status < 0) {
+ if(lookup_status) {
+ cb_lnk = &lnk;
+ cb_loc = &obj_loc;
+ } /* end if */
+ else {
HDassert(!obj_loc_valid);
cb_lnk = NULL;
cb_loc = NULL;
- } /* end if */
- else {
- cb_lnk = &lnk;
- cb_loc = &obj_loc;
} /* end else */
/* Call 'operator' routine */
@@ -694,7 +706,7 @@ H5G_traverse_real(const H5G_loc_t *_loc, const char *name, unsigned target,
} /* end if */
/* Handle lookup failures now */
- if(lookup_status < 0) {
+ if(!lookup_status) {
/* If an intermediate group doesn't exist & flag is set, create the group */
if(target & H5G_CRT_INTMD_GROUP) {
const H5O_ginfo_t def_ginfo = H5G_CRT_GROUP_INFO_DEF; /* Default group info settings */
@@ -702,39 +714,43 @@ H5G_traverse_real(const H5G_loc_t *_loc, const char *name, unsigned target,
H5O_ginfo_t par_ginfo; /* Group info settings for parent group */
H5O_linfo_t par_linfo; /* Link info settings for parent group */
H5O_linfo_t tmp_linfo; /* Temporary link info settings */
+ htri_t exists; /* Whether a group or link info message exists */
const H5O_ginfo_t *ginfo; /* Group info settings for new group */
const H5O_linfo_t *linfo; /* Link info settings for new group */
- /* Get the group info for parent group */
+ /* Check for the parent group having a group info message */
/* (OK if not found) */
- if(NULL == H5O_msg_read(grp_loc.oloc, H5O_GINFO_ID, &par_ginfo, dxpl_id)) {
- /* Clear error stack from not finding the group info message */
- H5E_clear_stack(NULL);
-
- /* Use default group info settings */
- ginfo = &def_ginfo;
+ if((exists = H5O_msg_exists(grp_loc.oloc, H5O_GINFO_ID, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to read object header")
+ if(exists) {
+ /* Get the group info for parent group */
+ if(NULL == H5O_msg_read(grp_loc.oloc, H5O_GINFO_ID, &par_ginfo, dxpl_id))
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "group info message not present")
+
+ /* Use parent group info settings */
+ ginfo = &par_ginfo;
} /* end if */
else
- ginfo = &par_ginfo;
+ /* Use default group info settings */
+ ginfo = &def_ginfo;
- /* Get the link info for parent group */
+ /* Check for the parent group having a link info message */
/* (OK if not found) */
- if(NULL == H5G_obj_get_linfo(grp_loc.oloc, &par_linfo, dxpl_id)) {
- /* Clear error stack from not finding the link info message */
- H5E_clear_stack(NULL);
-
- /* Use default link info settings */
- linfo = &def_linfo;
- } /* end if */
- else {
- /* Only keep the creation order information from the parent
+ /* Get the link info for parent group */
+ if((exists = H5G_obj_get_linfo(grp_loc.oloc, &par_linfo, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to read object header")
+ if(exists) {
+ /* Only keep the creation order information from the parent
* group's link info
*/
HDmemcpy(&tmp_linfo, &def_linfo, sizeof(H5O_linfo_t));
tmp_linfo.track_corder = par_linfo.track_corder;
tmp_linfo.index_corder = par_linfo.index_corder;
linfo = &tmp_linfo;
- } /* end else */
+ } /* end if */
+ else
+ /* Use default link info settings */
+ linfo = &def_linfo;
/* Create the intermediate group */
/* XXX: Should we allow user to control the group creation params here? -QAK */
@@ -802,7 +818,7 @@ done:
H5G_loc_free(&obj_loc);
if(group_copy && !(own_loc & H5G_OWN_GRP_LOC))
H5G_loc_free(&grp_loc);
-
+
/* If there's valid information in the link, reset it */
if(link_valid)
H5O_msg_reset(H5O_LINK_ID, &lnk);
@@ -850,7 +866,7 @@ H5G_traverse(const H5G_loc_t *loc, const char *name, unsigned target, H5G_traver
if(lapl_id == H5P_DEFAULT)
nlinks = H5L_NUM_LINKS;
else {
- if(NULL == (lapl = H5I_object(lapl_id)))
+ if(NULL == (lapl = (H5P_genplist_t *)H5I_object(lapl_id)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
if(H5P_get(lapl, H5L_ACS_NLINKS_NAME, &nlinks) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get number of links")
diff --git a/src/H5HF.c b/src/H5HF.c
index 768b7e7..79032d3 100644
--- a/src/H5HF.c
+++ b/src/H5HF.c
@@ -175,7 +175,7 @@ HDfprintf(stderr, "%s: Called\n", FUNC);
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fractal heap info")
/* Lock the heap header into memory */
- if(NULL == (hdr = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, fh_addr, NULL, NULL, H5AC_WRITE)))
+ if(NULL == (hdr = (H5HF_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, fh_addr, NULL, NULL, H5AC_WRITE)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to load fractal heap header")
/* Point fractal heap wrapper at header and bump it's ref count */
@@ -238,7 +238,7 @@ H5HF_open(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr)
#ifdef QAK
HDfprintf(stderr, "%s: fh_addr = %a\n", FUNC, fh_addr);
#endif /* QAK */
- if(NULL == (hdr = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, fh_addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (hdr = (H5HF_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, fh_addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unable to load fractal heap header")
#ifdef QAK
HDfprintf(stderr, "%s: hdr->rc = %u, hdr->fspace = %p\n", FUNC, hdr->rc, hdr->fspace);
@@ -635,7 +635,7 @@ done:
*
* Purpose: Perform an operation directly on a heap object
*
- * Note: The library routines currently assume that the 'op' callback
+ * Note: The library routines currently assume that the 'op' callback
* won't modify the object. This can easily be changed later for
* "managed" heap objects, and, with some difficulty, for 'huge'
* and 'tiny' heap objects.
@@ -847,6 +847,9 @@ HDfprintf(stderr, "%s; After iterator reset fh->hdr->rc = %Zu\n", FUNC, fh->hdr-
} /* end if */
/* Decrement the reference count on the heap header */
+ /* (don't put in H5HF_hdr_fuse_decr() as the heap header may be evicted
+ * immediately -QAK)
+ */
if(H5HF_hdr_decr(fh->hdr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared heap header")
@@ -855,7 +858,7 @@ HDfprintf(stderr, "%s; After iterator reset fh->hdr->rc = %Zu\n", FUNC, fh->hdr-
H5HF_hdr_t *hdr; /* Another pointer to fractal heap header */
/* Lock the heap header into memory */
- if(NULL == (hdr = H5AC_protect(fh->f, dxpl_id, H5AC_FHEAP_HDR, heap_addr, NULL, NULL, H5AC_WRITE)))
+ if(NULL == (hdr = (H5HF_hdr_t *)H5AC_protect(fh->f, dxpl_id, H5AC_FHEAP_HDR, heap_addr, NULL, NULL, H5AC_WRITE)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap header")
/* Set the shared heap header's file context for this operation */
@@ -867,7 +870,7 @@ HDfprintf(stderr, "%s; After iterator reset fh->hdr->rc = %Zu\n", FUNC, fh->hdr-
} /* end if */
/* Release the fractal heap wrapper */
- H5FL_FREE(H5HF_t, fh);
+ (void)H5FL_FREE(H5HF_t, fh);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -905,13 +908,16 @@ H5HF_delete(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr)
#ifdef QAK
HDfprintf(stderr, "%s: fh_addr = %a\n", FUNC, fh_addr);
#endif /* QAK */
- if(NULL == (hdr = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, fh_addr, NULL, NULL, H5AC_WRITE)))
+ if(NULL == (hdr = (H5HF_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, fh_addr, NULL, NULL, H5AC_WRITE)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap header")
/* Check for files using shared heap header */
if(hdr->file_rc)
hdr->pending_delete = TRUE;
else {
+ /* Set the shared heap header's file context for this operation */
+ hdr->f = f;
+
/* Delete heap now, starting with header (unprotects header) */
if(H5HF_hdr_delete(hdr, dxpl_id) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDELETE, FAIL, "unable to delete fractal heap")
diff --git a/src/H5HFcache.c b/src/H5HFcache.c
index 23bc28e..847c54e 100644
--- a/src/H5HFcache.c
+++ b/src/H5HFcache.c
@@ -30,6 +30,7 @@
#define H5HF_PACKAGE /*suppress error about including H5HFpkg */
+
/***********/
/* Headers */
/***********/
@@ -41,6 +42,7 @@
#include "H5Vprivate.h" /* Vectors and arrays */
#include "H5WBprivate.h" /* Wrapped Buffers */
+
/****************/
/* Local Macros */
/****************/
@@ -89,6 +91,7 @@ static herr_t H5HF_cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy,
static herr_t H5HF_cache_dblock_clear(H5F_t *f, H5HF_direct_t *dblock, hbool_t destroy);
static herr_t H5HF_cache_dblock_size(const H5F_t *f, const H5HF_direct_t *dblock, size_t *size_ptr);
+
/*********************/
/* Package Variables */
/*********************/
@@ -291,7 +294,7 @@ HDfprintf(stderr, "%s: Load heap header, addr = %a\n", FUNC, addr);
size = H5HF_HEADER_SIZE(hdr);
/* Get a pointer to a buffer that's large enough for serialized header */
- if(NULL == (buf = H5WB_actual(wb, size)))
+ if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, NULL, "can't get actual buffer")
/* Read header from disk */
@@ -302,9 +305,9 @@ HDfprintf(stderr, "%s: Load heap header, addr = %a\n", FUNC, addr);
p = buf;
/* Magic number */
- if(HDmemcmp(p, H5HF_HDR_MAGIC, (size_t)H5HF_SIZEOF_MAGIC))
+ if(HDmemcmp(p, H5HF_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC))
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong fractal heap header signature")
- p += H5HF_SIZEOF_MAGIC;
+ p += H5_SIZEOF_MAGIC;
/* Version */
if(*p++ != H5HF_HDR_VERSION)
@@ -366,7 +369,7 @@ HDfprintf(stderr, "%s: Load heap header, addr = %a\n", FUNC, addr);
hdr->heap_size = size + filter_info_size;
/* Re-size current buffer */
- if(NULL == (buf = H5WB_actual(wb, hdr->heap_size)))
+ if(NULL == (buf = (uint8_t *)H5WB_actual(wb, hdr->heap_size)))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, NULL, "can't get actual buffer")
/* Read in I/O filter information */
@@ -395,7 +398,7 @@ HDfprintf(stderr, "%s: Load heap header, addr = %a\n", FUNC, addr);
/* Release the space allocated for the I/O pipeline filters */
H5O_msg_free(H5O_PLINE_ID, pline);
} /* end if */
- else
+ else
/* Set the heap header's size */
hdr->heap_size = size;
@@ -490,15 +493,15 @@ HDfprintf(stderr, "%s: Flushing heap header, addr = %a, destroy = %u\n", FUNC, a
size = hdr->heap_size;
/* Get a pointer to a buffer that's large enough for serialized header */
- if(NULL == (buf = H5WB_actual(wb, size)))
+ if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "can't get actual buffer")
/* Get temporary pointer to serialized header */
p = buf;
/* Magic number */
- HDmemcpy(p, H5HF_HDR_MAGIC, (size_t)H5HF_SIZEOF_MAGIC);
- p += H5HF_SIZEOF_MAGIC;
+ HDmemcpy(p, H5HF_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ p += H5_SIZEOF_MAGIC;
/* Version # */
*p++ = H5HF_HDR_VERSION;
@@ -593,11 +596,12 @@ done:
*
*-------------------------------------------------------------------------
*/
-/* ARGSUSED */
herr_t
-H5HF_cache_hdr_dest(H5F_t UNUSED *f, H5HF_hdr_t *hdr)
+H5HF_cache_hdr_dest(H5F_t *f, H5HF_hdr_t *hdr)
{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_cache_hdr_dest)
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_cache_hdr_dest)
/*
* Check arguments.
@@ -605,6 +609,17 @@ H5HF_cache_hdr_dest(H5F_t UNUSED *f, H5HF_hdr_t *hdr)
HDassert(hdr);
HDassert(hdr->rc == 0);
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!hdr->cache_info.free_file_space_on_destroy || H5F_addr_defined(hdr->cache_info.addr));
+
+ /* Check for freeing file space for heap header */
+ if(hdr->cache_info.free_file_space_on_destroy) {
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_FHEAP_HDR, H5AC_dxpl_id, hdr->cache_info.addr, (hsize_t)hdr->heap_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap header")
+ } /* end if */
+
/* Free the block size lookup table for the doubling table */
H5HF_dtable_dest(&hdr->man_dtable);
@@ -613,9 +628,10 @@ H5HF_cache_hdr_dest(H5F_t UNUSED *f, H5HF_hdr_t *hdr)
H5O_msg_reset(H5O_PLINE_ID, &(hdr->pline));
/* Free the shared info itself */
- H5FL_FREE(H5HF_hdr_t, hdr);
+ (void)H5FL_FREE(H5HF_hdr_t, hdr);
- FUNC_LEAVE_NOAPI(SUCCEED)
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_cache_hdr_dest() */
@@ -733,7 +749,6 @@ HDfprintf(stderr, "%s: Load indirect block, addr = %a\n", FUNC, addr);
/* Allocate space for the fractal heap indirect block */
if(NULL == (iblock = H5FL_CALLOC(H5HF_indirect_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- HDmemset(&iblock->cache_info, 0, sizeof(H5AC_info_t));
/* Get the pointer to the shared heap header */
hdr = par_info->hdr;
@@ -760,7 +775,7 @@ HDfprintf(stderr, "%s: Load indirect block, addr = %a\n", FUNC, addr);
iblock->size = H5HF_MAN_INDIRECT_SIZE(hdr, iblock);
/* Get a pointer to a buffer that's large enough for serialized indirect block */
- if(NULL == (buf = H5WB_actual(wb, iblock->size)))
+ if(NULL == (buf = (uint8_t *)H5WB_actual(wb, iblock->size)))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, NULL, "can't get actual buffer")
/* Read indirect block from disk */
@@ -771,9 +786,9 @@ HDfprintf(stderr, "%s: Load indirect block, addr = %a\n", FUNC, addr);
p = buf;
/* Magic number */
- if(HDmemcmp(p, H5HF_IBLOCK_MAGIC, (size_t)H5HF_SIZEOF_MAGIC))
+ if(HDmemcmp(p, H5HF_IBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC))
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong fractal heap indirect block signature")
- p += H5HF_SIZEOF_MAGIC;
+ p += H5_SIZEOF_MAGIC;
/* Version */
if(*p++ != H5HF_IBLOCK_VERSION)
@@ -963,15 +978,15 @@ HDfprintf(stderr, "%s: hdr->man_dtable.cparam.width = %u\n", FUNC, hdr->man_dtab
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't wrap buffer")
/* Get a pointer to a buffer that's large enough for serialized indirect block */
- if(NULL == (buf = H5WB_actual(wb, iblock->size)))
+ if(NULL == (buf = (uint8_t *)H5WB_actual(wb, iblock->size)))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "can't get actual buffer")
/* Get temporary pointer to buffer for serialized indirect block */
p = buf;
/* Magic number */
- HDmemcpy(p, H5HF_IBLOCK_MAGIC, (size_t)H5HF_SIZEOF_MAGIC);
- p += H5HF_SIZEOF_MAGIC;
+ HDmemcpy(p, H5HF_IBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ p += H5_SIZEOF_MAGIC;
/* Version # */
*p++ = H5HF_IBLOCK_VERSION;
@@ -1072,9 +1087,8 @@ done:
*
*-------------------------------------------------------------------------
*/
-/* ARGSUSED */
herr_t
-H5HF_cache_iblock_dest(H5F_t UNUSED *f, H5HF_indirect_t *iblock)
+H5HF_cache_iblock_dest(H5F_t *f, H5HF_indirect_t *iblock)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -1085,15 +1099,26 @@ H5HF_cache_iblock_dest(H5F_t UNUSED *f, H5HF_indirect_t *iblock)
*/
HDassert(iblock);
HDassert(iblock->rc == 0);
+ HDassert(iblock->hdr);
#ifdef QAK
HDfprintf(stderr, "%s: Destroying indirect block\n", FUNC);
#endif /* QAK */
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!iblock->cache_info.free_file_space_on_destroy || H5F_addr_defined(iblock->cache_info.addr));
+
+ /* Check for freeing file space for indirect block */
+ if(iblock->cache_info.free_file_space_on_destroy) {
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_FHEAP_IBLOCK, H5AC_dxpl_id, iblock->cache_info.addr, (hsize_t)iblock->size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap indirect block")
+ } /* end if */
+
/* Set the shared heap header's file context for this operation */
iblock->hdr->f = f;
/* Decrement reference count on shared info */
- HDassert(iblock->hdr);
if(H5HF_hdr_decr(iblock->hdr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared heap header")
if(iblock->parent)
@@ -1109,7 +1134,7 @@ HDfprintf(stderr, "%s: Destroying indirect block\n", FUNC);
H5FL_SEQ_FREE(H5HF_indirect_ptr_t, iblock->child_iblocks);
/* Free fractal heap indirect block info */
- H5FL_FREE(H5HF_indirect_t, iblock);
+ (void)H5FL_FREE(H5HF_indirect_t, iblock);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1235,7 +1260,7 @@ H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_size,
/* Set block's internal information */
dblock->size = *size;
- dblock->blk_off_size = H5HF_SIZEOF_OFFSET_LEN(dblock->size);
+ dblock->file_size = 0;
/* Allocate block buffer */
/* XXX: Change to using free-list factories */
@@ -1316,9 +1341,9 @@ HDfprintf(stderr, "%s: nbytes = %Zu, read_size = %Zu, read_buf = %p\n", FUNC, nb
p = dblock->blk;
/* Magic number */
- if(HDmemcmp(p, H5HF_DBLOCK_MAGIC, (size_t)H5HF_SIZEOF_MAGIC))
+ if(HDmemcmp(p, H5HF_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC))
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong fractal heap direct block signature")
- p += H5HF_SIZEOF_MAGIC;
+ p += H5_SIZEOF_MAGIC;
/* Version */
if(*p++ != H5HF_DBLOCK_VERSION)
@@ -1422,8 +1447,8 @@ H5HF_cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
p = dblock->blk;
/* Magic number */
- HDmemcpy(p, H5HF_DBLOCK_MAGIC, (size_t)H5HF_SIZEOF_MAGIC);
- p += H5HF_SIZEOF_MAGIC;
+ HDmemcpy(p, H5HF_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ p += H5_SIZEOF_MAGIC;
/* Version # */
*p++ = H5HF_DBLOCK_VERSION;
@@ -1623,9 +1648,8 @@ done:
*
*-------------------------------------------------------------------------
*/
-/* ARGSUSED */
herr_t
-H5HF_cache_dblock_dest(H5F_t UNUSED *f, H5HF_direct_t *dblock)
+H5HF_cache_dblock_dest(H5F_t *f, H5HF_direct_t *dblock)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -1639,6 +1663,20 @@ H5HF_cache_dblock_dest(H5F_t UNUSED *f, H5HF_direct_t *dblock)
HDfprintf(stderr, "%s: Destroying direct block, dblock = %p\n", FUNC, dblock);
#endif /* QAK */
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!dblock->cache_info.free_file_space_on_destroy || H5F_addr_defined(dblock->cache_info.addr));
+
+ /* Check for freeing file space for direct block */
+ if(dblock->cache_info.free_file_space_on_destroy) {
+ /* Sanity check */
+ HDassert(dblock->file_size > 0);
+
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_FHEAP_DBLOCK, H5AC_dxpl_id, dblock->cache_info.addr, dblock->file_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block")
+ } /* end if */
+
/* Set the shared heap header's file context for this operation */
dblock->hdr->f = f;
@@ -1654,7 +1692,7 @@ HDfprintf(stderr, "%s: Destroying direct block, dblock = %p\n", FUNC, dblock);
dblock->blk = H5FL_BLK_FREE(direct_block, dblock->blk);
/* Free fractal heap direct block info */
- H5FL_FREE(H5HF_direct_t, dblock);
+ (void)H5FL_FREE(H5HF_direct_t, dblock);
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5HFdbg.c b/src/H5HFdbg.c
index 3a7288f..3931eb0 100644
--- a/src/H5HFdbg.c
+++ b/src/H5HFdbg.c
@@ -204,7 +204,7 @@ H5HF_hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent,
/*
* Load the fractal heap header.
*/
- if(NULL == (hdr = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (hdr = (H5HF_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap header")
/* Print opening message */
@@ -394,7 +394,6 @@ H5HF_dblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream,
{
H5HF_hdr_t *hdr = NULL; /* Fractal heap header info */
H5HF_direct_t *dblock = NULL; /* Fractal heap direct block info */
- H5HF_debug_iter_ud1_t udata; /* User data for callbacks */
size_t blk_prefix_size; /* Size of prefix for block */
size_t amount_free; /* Amount of free space in block */
uint8_t *marker = NULL; /* Track free space for block */
@@ -416,7 +415,7 @@ H5HF_dblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream,
/*
* Load the fractal heap header.
*/
- if(NULL == (hdr = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, hdr_addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (hdr = (H5HF_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, hdr_addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap header")
/*
@@ -441,45 +440,49 @@ H5HF_dblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream,
HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth,
"Size of block header:",
blk_prefix_size);
- HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth,
- "Size of block offsets:",
- dblock->blk_off_size);
/* Allocate space for the free space markers */
- if(NULL == (marker = H5MM_calloc(dblock->size)))
+ if(NULL == (marker = (uint8_t *)H5MM_calloc(dblock->size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Initialize the free space information for the heap */
- if(H5HF_space_start(hdr, dxpl_id) < 0)
+ if(H5HF_space_start(hdr, dxpl_id, FALSE) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize heap free space")
- /* Prepare user data for section iteration callback */
- udata.stream = stream;
- udata.indent = indent;
- udata.fwidth = fwidth;
- udata.dblock_addr = dblock->block_off;
- udata.dblock_size = block_size;
- udata.marker = marker;
- udata.sect_count = 0;
- udata.amount_free = 0;
-
- /* Print header */
- HDfprintf(stream, "%*sFree Blocks (offset, size):\n", indent, "");
-
- /* Iterate over the free space sections, to detect overlaps with this block */
- if(H5FS_sect_iterate(f, dxpl_id, hdr->fspace, H5HF_dblock_debug_cb, &udata) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_BADITER, FAIL, "can't iterate over heap's free space")
-
- /* Close the free space information */
- if(H5HF_space_close(hdr, dxpl_id) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release free space info")
-
- /* Keep the amount of space free */
- amount_free = udata.amount_free;
-
- /* Check for no free space */
- if(amount_free == 0)
- HDfprintf(stream, "%*s<none>\n", indent + 3, "");
+ /* If there is a free space manager for the heap, check for sections that overlap this block */
+ if(hdr->fspace) {
+ H5HF_debug_iter_ud1_t udata; /* User data for callbacks */
+
+ /* Prepare user data for section iteration callback */
+ udata.stream = stream;
+ udata.indent = indent;
+ udata.fwidth = fwidth;
+ udata.dblock_addr = dblock->block_off;
+ udata.dblock_size = block_size;
+ udata.marker = marker;
+ udata.sect_count = 0;
+ udata.amount_free = 0;
+
+ /* Print header */
+ HDfprintf(stream, "%*sFree Blocks (offset, size):\n", indent, "");
+
+ /* Iterate over the free space sections, to detect overlaps with this block */
+ if(H5FS_sect_iterate(f, dxpl_id, hdr->fspace, H5HF_dblock_debug_cb, &udata) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_BADITER, FAIL, "can't iterate over heap's free space")
+
+ /* Close the free space information */
+ if(H5HF_space_close(hdr, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release free space info")
+
+ /* Keep the amount of space free */
+ amount_free = udata.amount_free;
+
+ /* Check for no free space */
+ if(amount_free == 0)
+ HDfprintf(stream, "%*s<none>\n", indent + 3, "");
+ } /* end if */
+ else
+ amount_free = 0;
HDfprintf(stream, "%*s%-*s %.2f%%\n", indent, "", fwidth,
"Percent of available space for data used:",
@@ -541,7 +544,7 @@ H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream,
/*
* Load the fractal heap header.
*/
- if(NULL == (hdr = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, hdr_addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (hdr = (H5HF_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, hdr_addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap header")
/*
@@ -709,7 +712,6 @@ H5HF_sects_debug(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr,
FILE *stream, int indent, int fwidth)
{
H5HF_hdr_t *hdr = NULL; /* Fractal heap header info */
- H5HF_debug_iter_ud2_t udata; /* User data for callbacks */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5HF_sects_debug, FAIL)
@@ -726,26 +728,31 @@ H5HF_sects_debug(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr,
/*
* Load the fractal heap header.
*/
- if(NULL == (hdr = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, fh_addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (hdr = (H5HF_hdr_t *)H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, fh_addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap header")
/* Initialize the free space information for the heap */
- if(H5HF_space_start(hdr, dxpl_id) < 0)
+ if(H5HF_space_start(hdr, dxpl_id, FALSE) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize heap free space")
- /* Prepare user data for section iteration callback */
- udata.fspace = hdr->fspace;
- udata.stream = stream;
- udata.indent = indent;
- udata.fwidth = fwidth;
+ /* If there is a free space manager for the heap, iterate over them */
+ if(hdr->fspace) {
+ H5HF_debug_iter_ud2_t udata; /* User data for callbacks */
- /* Iterate over all the free space sections */
- if(H5FS_sect_iterate(f, dxpl_id, hdr->fspace, H5HF_sects_debug_cb, &udata) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_BADITER, FAIL, "can't iterate over heap's free space")
+ /* Prepare user data for section iteration callback */
+ udata.fspace = hdr->fspace;
+ udata.stream = stream;
+ udata.indent = indent;
+ udata.fwidth = fwidth;
- /* Close the free space information */
- if(H5HF_space_close(hdr, dxpl_id) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release free space info")
+ /* Iterate over all the free space sections */
+ if(H5FS_sect_iterate(f, dxpl_id, hdr->fspace, H5HF_sects_debug_cb, &udata) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_BADITER, FAIL, "can't iterate over heap's free space")
+
+ /* Close the free space information */
+ if(H5HF_space_close(hdr, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release free space info")
+ } /* end if */
done:
if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, fh_addr, hdr, H5AC__NO_FLAGS_SET) < 0)
diff --git a/src/H5HFdblock.c b/src/H5HFdblock.c
index 9de7bb8..c14249c 100644
--- a/src/H5HFdblock.c
+++ b/src/H5HFdblock.c
@@ -137,7 +137,7 @@ H5HF_man_dblock_create(hid_t dxpl_id, H5HF_hdr_t *hdr, H5HF_indirect_t *par_iblo
dblock->block_off = 0;
dblock->size = hdr->man_dtable.cparam.start_block_size;
} /* end else */
- dblock->blk_off_size = H5HF_SIZEOF_OFFSET_LEN(dblock->size);
+ dblock->file_size = 0;
free_space = dblock->size - H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr);
/* Allocate buffer for block */
@@ -220,6 +220,7 @@ H5HF_man_dblock_destroy(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_direct_t *dblock,
haddr_t dblock_addr)
{
hsize_t dblock_size; /* Size of direct block on disk */
+ unsigned cache_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting indirect block */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_man_dblock_destroy)
@@ -325,16 +326,15 @@ HDfprintf(stderr, "%s: Reversing iterator\n", FUNC);
HDfprintf(stderr, "%s: Before releasing direct block's space, dblock_addr = %a, dblock_size = %Hu\n", FUNC, dblock_addr, dblock_size);
#endif /* QAK */
- /* Release direct block's disk space */
- if(H5MF_xfree(hdr->f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, dblock_addr, dblock_size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block")
-
- /* Remove direct block from metadata cache */
- if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block")
- dblock = NULL;
+ /* Indicate that the indirect block should be deleted & file space freed */
+ dblock->file_size = dblock_size;
+ cache_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
done:
+ /* Unprotect the indirect block, with appropriate flags */
+ if(dblock && H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, cache_flags) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_man_dblock_destroy() */
@@ -507,7 +507,7 @@ HDfprintf(stderr, "%s: dblock_addr = %a, dblock_size = %Zu\n", FUNC, dblock_addr
par_info.entry = par_entry;
/* Protect the direct block */
- if(NULL == (dblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, &dblock_size, &par_info, rw)))
+ if(NULL == (dblock = (H5HF_direct_t *)H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, &dblock_size, &par_info, rw)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap direct block")
/* Set the return value */
@@ -688,7 +688,7 @@ HDfprintf(stderr, "%s: dblock_addr = %a, dblock_size = %Hu\n", FUNC, dblock_addr
HDfprintf(stderr, "%s: Expunging direct block from cache\n", FUNC);
#endif /* QAK */
/* Evict the direct block from the metadata cache */
- if(H5AC_expunge_entry(f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr) < 0)
+ if(H5AC_expunge_entry(f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "unable to remove direct block from cache")
#ifdef QAK
HDfprintf(stderr, "%s: Done expunging direct block from cache\n", FUNC);
@@ -696,6 +696,19 @@ HDfprintf(stderr, "%s: Done expunging direct block from cache\n", FUNC);
} /* end if */
/* Release direct block's disk space */
+ /* (XXX: Under the best of circumstances, this block's space in the file
+ * would be freed in the H5AC_expunge_entry() call above (and the
+ * H5AC__FREE_FILE_SPACE_FLAG used there), but since the direct
+ * block structure might have a different size on disk than in
+ * the heap's 'abstract' address space, we would need to set the
+ * "file_size" field for the direct block structure. In order to
+ * do that, we'd have to protect/unprotect the direct block and
+ * that would add a bunch of unnecessary overhead to the process,
+ * so we just release the file space here, directly. When the
+ * revised metadata cache is operating, it will "know" the file
+ * size of each entry in the cache and we can the the
+ * H5AC_expunge_entry() method. -QAK)
+ */
if(H5MF_xfree(f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, dblock_addr, dblock_size) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block")
diff --git a/src/H5HFdtable.c b/src/H5HFdtable.c
index b5be676..29af47f 100644
--- a/src/H5HFdtable.c
+++ b/src/H5HFdtable.c
@@ -113,13 +113,13 @@ H5HF_dtable_init(H5HF_dtable_t *dtable)
dtable->max_dir_blk_off_size = H5HF_SIZEOF_OFFSET_LEN(dtable->cparam.max_direct_size);
/* Build table of block sizes for each row */
- if(NULL == (dtable->row_block_size = H5MM_malloc(dtable->max_root_rows * sizeof(hsize_t))))
+ if(NULL == (dtable->row_block_size = (hsize_t *)H5MM_malloc(dtable->max_root_rows * sizeof(hsize_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create doubling table block size table")
- if(NULL == (dtable->row_block_off = H5MM_malloc(dtable->max_root_rows * sizeof(hsize_t))))
+ if(NULL == (dtable->row_block_off = (hsize_t *)H5MM_malloc(dtable->max_root_rows * sizeof(hsize_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create doubling table block offset table")
- if(NULL == (dtable->row_tot_dblock_free = H5MM_malloc(dtable->max_root_rows * sizeof(hsize_t))))
+ if(NULL == (dtable->row_tot_dblock_free = (hsize_t *)H5MM_malloc(dtable->max_root_rows * sizeof(hsize_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create doubling table total direct block free space table")
- if(NULL == (dtable->row_max_dblock_free = H5MM_malloc(dtable->max_root_rows * sizeof(size_t))))
+ if(NULL == (dtable->row_max_dblock_free = (size_t *)H5MM_malloc(dtable->max_root_rows * sizeof(size_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create doubling table max. direct block free space table")
tmp_block_size = dtable->cparam.start_block_size;
acc_block_off = dtable->cparam.start_block_size * dtable->cparam.width;
diff --git a/src/H5HFhdr.c b/src/H5HFhdr.c
index c1b856b..4fd527d 100644
--- a/src/H5HFhdr.c
+++ b/src/H5HFhdr.c
@@ -225,7 +225,7 @@ H5HF_hdr_finish_init_phase1(H5HF_hdr_t *hdr)
/* Set the size of heap IDs */
hdr->heap_len_size = MIN(hdr->man_dtable.max_dir_blk_off_size,
- ((H5V_log2_gen((uint64_t)hdr->max_man_size) + 7) / 8));
+ H5V_limit_enc_size((uint64_t)hdr->max_man_size));
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -415,7 +415,7 @@ H5HF_hdr_create(H5F_t *f, hid_t dxpl_id, const H5HF_create_t *cparam)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, HADDR_UNDEF, "can't finish phase #1 of header final initialization")
/* Copy any I/O filter pipeline */
- /* (This code is not in the "finish init phase" routines because those
+ /* (This code is not in the "finish init phase" routines because those
* routines are also called from the cache 'load' callback, and the filter
* length is already set in that case (its stored in the header on disk))
*/
@@ -448,7 +448,7 @@ HDfprintf(stderr, "%s: hdr->filter_len = %u\n", FUNC, hdr->filter_len);
hdr->heap_size = H5HF_HEADER_SIZE(hdr);
/* Set the length of IDs in the heap */
- /* (This code is not in the "finish init phase" routines because those
+ /* (This code is not in the "finish init phase" routines because those
* routines are also called from the cache 'load' callback, and the ID
* length is already set in that case (its stored in the header on disk))
*/
@@ -1313,7 +1313,7 @@ HDfprintf(stderr, "%s: curr_entry = %u\n", FUNC, curr_entry);
HDfprintf(stderr, "%s: tmp_entry = %d\n", FUNC, tmp_entry);
#endif /* QAK */
while(tmp_entry >= 0 &&
- (H5F_addr_eq(iblock->ents[tmp_entry].addr, dblock_addr) ||
+ (H5F_addr_eq(iblock->ents[tmp_entry].addr, dblock_addr) ||
!H5F_addr_defined(iblock->ents[tmp_entry].addr)))
tmp_entry--;
#ifdef QAK
@@ -1505,6 +1505,7 @@ done:
herr_t
H5HF_hdr_delete(H5HF_hdr_t *hdr, hid_t dxpl_id)
{
+ unsigned cache_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting heap header */
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(H5HF_hdr_delete, FAIL)
@@ -1585,18 +1586,12 @@ HDfprintf(stderr, "%s: hdr->huge_bt2_addr = %a\n", FUNC, hdr->huge_bt2_addr);
HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to release fractal heap 'huge' objects and tracker")
} /* end if */
- /* Release header's disk space */
- if(H5MF_xfree(hdr->f, H5FD_MEM_FHEAP_HDR, dxpl_id, hdr->heap_addr, (hsize_t)hdr->heap_size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to release fractal heap header")
-
- /* Finished deleting header */
- if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_HDR, hdr->heap_addr, hdr, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap header")
- hdr = NULL;
+ /* Indicate that the heap header should be deleted & file space freed */
+ cache_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
done:
- /* Unprotect the header, if an error occurred */
- if(hdr && H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_HDR, hdr->heap_addr, hdr, H5AC__NO_FLAGS_SET) < 0)
+ /* Unprotect the header with appropriate flags */
+ if(hdr && H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_HDR, hdr->heap_addr, hdr, cache_flags) < 0)
HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap header")
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5HFhuge.c b/src/H5HFhuge.c
index 198ef62..db9f7a1 100644
--- a/src/H5HFhuge.c
+++ b/src/H5HFhuge.c
@@ -545,7 +545,7 @@ H5HF_huge_get_obj_len(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id,
/* Look up object in v2 B-tree */
if(H5B2_find(hdr->f, dxpl_id, H5HF_BT2_FILT_INDIR, hdr->huge_bt2_addr,
- &search_rec, H5HF_huge_bt2_filt_indir_found, &found_rec) < 0)
+ &search_rec, H5HF_huge_bt2_filt_indir_found, &found_rec) != TRUE)
HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in B-tree")
/* Retrieve the object's length */
@@ -560,7 +560,7 @@ H5HF_huge_get_obj_len(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id,
/* Look up object in v2 B-tree */
if(H5B2_find(hdr->f, dxpl_id, H5HF_BT2_INDIR, hdr->huge_bt2_addr,
- &search_rec, H5HF_huge_bt2_indir_found, &found_rec) < 0)
+ &search_rec, H5HF_huge_bt2_indir_found, &found_rec) != TRUE)
HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in B-tree")
/* Retrieve the object's length */
@@ -628,7 +628,7 @@ H5HF_huge_op_real(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id,
/* Look up object in v2 B-tree */
if(H5B2_find(hdr->f, dxpl_id, H5HF_BT2_FILT_INDIR, hdr->huge_bt2_addr,
- &search_rec, H5HF_huge_bt2_filt_indir_found, &found_rec) < 0)
+ &search_rec, H5HF_huge_bt2_filt_indir_found, &found_rec) != TRUE)
HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in B-tree")
/* Retrieve the object's address & length */
@@ -645,7 +645,7 @@ H5HF_huge_op_real(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id,
/* Look up object in v2 B-tree */
if(H5B2_find(hdr->f, dxpl_id, H5HF_BT2_INDIR, hdr->huge_bt2_addr,
- &search_rec, H5HF_huge_bt2_indir_found, &found_rec) < 0)
+ &search_rec, H5HF_huge_bt2_indir_found, &found_rec) != TRUE)
HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in B-tree")
/* Retrieve the object's address & length */
@@ -764,7 +764,7 @@ H5HF_huge_write(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id,
/* Look up object in v2 B-tree */
if(H5B2_find(hdr->f, dxpl_id, H5HF_BT2_INDIR, hdr->huge_bt2_addr,
- &search_rec, H5HF_huge_bt2_indir_found, &found_rec) < 0)
+ &search_rec, H5HF_huge_bt2_indir_found, &found_rec) != TRUE)
HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in B-tree")
/* Retrieve the object's address & length */
diff --git a/src/H5HFiblock.c b/src/H5HFiblock.c
index 70133aa..8f9eb24 100644
--- a/src/H5HFiblock.c
+++ b/src/H5HFiblock.c
@@ -125,7 +125,7 @@ H5HF_iblock_pin(H5HF_indirect_t *iblock)
/* Sanity check */
HDassert(par_iblock->child_iblocks);
- HDassert(iblock->par_entry >= (iblock->hdr->man_dtable.max_direct_rows
+ HDassert(iblock->par_entry >= (iblock->hdr->man_dtable.max_direct_rows
* iblock->hdr->man_dtable.cparam.width));
/* Compute index in parent's child iblock pointer array */
@@ -179,7 +179,7 @@ H5HF_iblock_unpin(H5HF_indirect_t *iblock)
/* Sanity check */
HDassert(par_iblock->child_iblocks);
- HDassert(iblock->par_entry >= (iblock->hdr->man_dtable.max_direct_rows
+ HDassert(iblock->par_entry >= (iblock->hdr->man_dtable.max_direct_rows
* iblock->hdr->man_dtable.cparam.width));
/* Compute index in parent's child iblock pointer array */
@@ -310,12 +310,8 @@ HDfprintf(stderr, "%s: Removing indirect block from cache, iblock->addr = %a\n",
iblock->par_entry = 0;
} /* end if */
- /* Release space for indirect block on disk */
- if(H5MF_xfree(iblock->hdr->f, H5FD_MEM_FHEAP_IBLOCK, H5AC_dxpl_id, iblock->addr, (hsize_t)iblock->size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap indirect block disk space")
-
/* Evict the indirect block from the metadata cache */
- if(H5AC_expunge_entry(iblock->hdr->f, H5AC_dxpl_id, H5AC_FHEAP_IBLOCK, iblock->addr) < 0)
+ if(H5AC_expunge_entry(iblock->hdr->f, H5AC_dxpl_id, H5AC_FHEAP_IBLOCK, iblock->addr, H5AC__FREE_FILE_SPACE_FLAG) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "unable to remove indirect block from cache")
} /* end if */
} /* end if */
@@ -805,7 +801,7 @@ HDfprintf(stderr, "%s: new_addr = %a\n", FUNC, new_addr);
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "memory allocation failed for filtered direct entries")
} /* end if */
else
- iblock->child_iblocks = H5FL_SEQ_FREE(H5HF_indirect_ptr_t, iblock->child_iblocks);
+ iblock->child_iblocks = (H5HF_indirect_ptr_t *)H5FL_SEQ_FREE(H5HF_indirect_ptr_t, iblock->child_iblocks);
} /* end if */
/* Mark indirect block as dirty */
@@ -1157,7 +1153,7 @@ HDfprintf(stderr, "%s: iblock_addr = %a, iblock_nrows = %u\n", FUNC, iblock_addr
HDassert(iblock_nrows > 0);
HDassert(did_protect);
- /* Check if we are allow to use existing pinned iblock pointer */
+ /* Check if we are allowed to use existing pinned iblock pointer */
if(!must_protect) {
/* Check for this block already being pinned */
if(par_iblock) {
@@ -1165,7 +1161,7 @@ HDfprintf(stderr, "%s: iblock_addr = %a, iblock_nrows = %u\n", FUNC, iblock_addr
/* Sanity check */
HDassert(par_iblock->child_iblocks);
- HDassert(par_entry >= (hdr->man_dtable.max_direct_rows
+ HDassert(par_entry >= (hdr->man_dtable.max_direct_rows
* hdr->man_dtable.cparam.width));
/* Compute index in parent's child iblock pointer array */
@@ -1200,7 +1196,7 @@ HDfprintf(stderr, "%s: iblock_addr = %a, iblock_nrows = %u\n", FUNC, iblock_addr
par_info.entry = par_entry;
/* Protect the indirect block */
- if(NULL == (iblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, &iblock_nrows, &par_info, rw)))
+ if(NULL == (iblock = (H5HF_indirect_t *)H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, &iblock_nrows, &par_info, rw)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap indirect block")
*did_protect = TRUE;
} /* end if */
@@ -1489,6 +1485,7 @@ H5HF_man_iblock_delete(H5HF_hdr_t *hdr, hid_t dxpl_id, haddr_t iblock_addr,
H5HF_indirect_t *iblock; /* Pointer to indirect block */
unsigned row, col; /* Current row & column in indirect block */
unsigned entry; /* Current entry in row */
+ unsigned cache_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting indirect block */
hbool_t did_protect; /* Whether we protected the indirect block or not */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1525,7 +1522,7 @@ HDfprintf(stderr, "%s: iblock_addr = %a, iblock_nrows = %u\n", FUNC, iblock_addr
/* Are we in a direct or indirect block row */
if(row < hdr->man_dtable.max_direct_rows) {
hsize_t dblock_size; /* Size of direct block on disk */
-
+
/* Check for I/O filters on this heap */
if(hdr->filter_len > 0)
dblock_size = iblock->filt_ents[entry].size;
@@ -1550,10 +1547,6 @@ HDfprintf(stderr, "%s: iblock_addr = %a, iblock_nrows = %u\n", FUNC, iblock_addr
} /* end for */
} /* end row */
- /* Release indirect block's disk space */
- if(H5MF_xfree(hdr->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, iblock_addr, (hsize_t)iblock->size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap indirect block")
-
#ifndef NDEBUG
{
unsigned iblock_status = 0; /* Indirect block's status in the metadata cache */
@@ -1567,12 +1560,14 @@ HDfprintf(stderr, "%s: iblock_addr = %a, iblock_nrows = %u\n", FUNC, iblock_addr
}
#endif /* NDEBUG */
- /* Finished deleting indirect block in metadata cache */
- if(H5HF_man_iblock_unprotect(iblock, dxpl_id, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG, did_protect) < 0)
- HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
- iblock = NULL;
+ /* Indicate that the indirect block should be deleted & file space freed */
+ cache_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
done:
+ /* Unprotect the indirect block, with appropriate flags */
+ if(iblock && H5HF_man_iblock_unprotect(iblock, dxpl_id, cache_flags, did_protect) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_man_iblock_delete() */
@@ -1591,7 +1586,7 @@ done:
*/
herr_t
H5HF_man_iblock_size(H5F_t *f, hid_t dxpl_id, H5HF_hdr_t *hdr, haddr_t iblock_addr,
- unsigned nrows, hsize_t *heap_size)
+ unsigned nrows, H5HF_indirect_t *par_iblock, unsigned par_entry, hsize_t *heap_size)
{
H5HF_indirect_t *iblock = NULL; /* Pointer to indirect block */
hbool_t did_protect; /* Whether we protected the indirect block or not */
@@ -1608,7 +1603,7 @@ H5HF_man_iblock_size(H5F_t *f, hid_t dxpl_id, H5HF_hdr_t *hdr, haddr_t iblock_ad
HDassert(heap_size);
/* Protect the indirect block */
- if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, nrows, NULL, 0, FALSE, H5AC_READ, &did_protect)))
+ if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, nrows, par_iblock, par_entry, FALSE, H5AC_READ, &did_protect)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap indirect block")
/* Accumulate size of this indirect block */
@@ -1624,13 +1619,14 @@ H5HF_man_iblock_size(H5F_t *f, hid_t dxpl_id, H5HF_hdr_t *hdr, haddr_t iblock_ad
entry = hdr->man_dtable.max_direct_rows * hdr->man_dtable.cparam.width;
first_row_bits = H5V_log2_of2((uint32_t)hdr->man_dtable.cparam.start_block_size) +
H5V_log2_of2(hdr->man_dtable.cparam.width);
- num_indirect_rows = (H5V_log2_gen(hdr->man_dtable.row_block_size[u]) - first_row_bits) + 1;
+ num_indirect_rows =
+ (H5V_log2_gen(hdr->man_dtable.row_block_size[hdr->man_dtable.max_direct_rows]) - first_row_bits) + 1;
for(u = hdr->man_dtable.max_direct_rows; u < iblock->nrows; u++, num_indirect_rows++) {
size_t v; /* Local index variable */
for(v = 0; v < hdr->man_dtable.cparam.width; v++, entry++)
if(H5F_addr_defined(iblock->ents[entry].addr))
- if(H5HF_man_iblock_size(f, dxpl_id, hdr, iblock->ents[entry].addr, num_indirect_rows, heap_size) < 0)
+ if(H5HF_man_iblock_size(f, dxpl_id, hdr, iblock->ents[entry].addr, num_indirect_rows, iblock, entry, heap_size) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to get fractal heap storage info for indirect block")
} /* end for */
} /* end if */
@@ -1639,6 +1635,7 @@ done:
/* Release the indirect block */
if(iblock && H5HF_man_iblock_unprotect(iblock, dxpl_id, H5AC__NO_FLAGS_SET, did_protect) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
+ iblock = NULL;
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_man_iblock_size() */
diff --git a/src/H5HFiter.c b/src/H5HFiter.c
index 81ae03d..9e95c4e 100644
--- a/src/H5HFiter.c
+++ b/src/H5HFiter.c
@@ -407,7 +407,7 @@ H5HF_man_iter_reset(H5HF_block_iter_t *biter)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block")
/* Free the current location context */
- H5FL_FREE(H5HF_block_loc_t, curr_loc);
+ (void)H5FL_FREE(H5HF_block_loc_t, curr_loc);
/* Advance to next location */
curr_loc = next_loc;
@@ -504,7 +504,7 @@ H5HF_man_iter_up(H5HF_block_iter_t *biter)
up_loc = biter->curr->up;
/* Release this location */
- H5FL_FREE(H5HF_block_loc_t, biter->curr);
+ (void)H5FL_FREE(H5HF_block_loc_t, biter->curr);
/* Point location to next location up */
biter->curr = up_loc;
diff --git a/src/H5HFman.c b/src/H5HFman.c
index cf3f939..e069e82 100644
--- a/src/H5HFman.c
+++ b/src/H5HFman.c
@@ -246,7 +246,7 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5HF_man_op_real(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id,
+H5HF_man_op_real(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id,
H5HF_operator_t op, void *op_data, unsigned op_flags)
{
H5HF_direct_t *dblock = NULL; /* Pointer to direct block to query */
diff --git a/src/H5HFpkg.h b/src/H5HFpkg.h
index 461cba7..2997b3a 100644
--- a/src/H5HFpkg.h
+++ b/src/H5HFpkg.h
@@ -35,27 +35,19 @@
#include "H5ACprivate.h" /* Metadata cache */
#include "H5B2private.h" /* v2 B-trees */
#include "H5FLprivate.h" /* Free Lists */
-#include "H5FSprivate.h" /* File free space */
+#include "H5FSprivate.h" /* Free space manager */
#include "H5SLprivate.h" /* Skip lists */
/**************************/
/* Package Private Macros */
/**************************/
-/* Size of signature information (on disk) */
-#define H5HF_SIZEOF_MAGIC 4
-
-/* Fractal heap signatures */
-#define H5HF_HDR_MAGIC "FRHP" /* Header */
-#define H5HF_IBLOCK_MAGIC "FHIB" /* Indirect block */
-#define H5HF_DBLOCK_MAGIC "FHDB" /* Direct block */
-
/* Size of checksum information (on disk) */
#define H5HF_SIZEOF_CHKSUM 4
/* "Standard" size of prefix information for fractal heap metadata */
#define H5HF_METADATA_PREFIX_SIZE(c) ( \
- H5HF_SIZEOF_MAGIC /* Signature */ \
+ H5_SIZEOF_MAGIC /* Signature */ \
+ 1 /* Version */ \
+ ((c) ? H5HF_SIZEOF_CHKSUM : 0) /* Metadata checksum */ \
)
@@ -411,7 +403,7 @@ typedef struct H5HF_direct_t {
H5HF_indirect_t *parent; /* Shared parent indirect block info */
unsigned par_entry; /* Entry in parent's table */
size_t size; /* Size of direct block */
- unsigned blk_off_size; /* Size of offsets in the block */
+ hsize_t file_size; /* Size of direct block in file (only valid when block's space is being freed) */
uint8_t *blk; /* Pointer to buffer containing block data */
/* Stored values */
@@ -601,7 +593,7 @@ H5_DLL herr_t H5HF_man_iblock_delete(H5HF_hdr_t *hdr, hid_t dxpl_id,
haddr_t iblock_addr, unsigned iblock_nrows, H5HF_indirect_t *par_iblock,
unsigned par_entry);
H5_DLL herr_t H5HF_man_iblock_size(H5F_t *f, hid_t dxpl_id, H5HF_hdr_t *hdr,
- haddr_t iblock_addr, unsigned nrows, hsize_t *heap_size/*out*/);
+ haddr_t iblock_addr, unsigned nrows, H5HF_indirect_t *par_iblock, unsigned par_entry, hsize_t *heap_size/*out*/);
/* Direct block routines */
H5_DLL herr_t H5HF_man_dblock_new(H5HF_hdr_t *fh, hid_t dxpl_id, size_t request,
@@ -692,7 +684,7 @@ H5_DLL herr_t H5HF_man_iter_offset(H5HF_hdr_t *hdr, H5HF_block_iter_t *biter,
H5_DLL hbool_t H5HF_man_iter_ready(H5HF_block_iter_t *biter);
/* Free space manipulation routines */
-H5_DLL herr_t H5HF_space_start(H5HF_hdr_t *hdr, hid_t dxpl_id);
+H5_DLL herr_t H5HF_space_start(H5HF_hdr_t *hdr, hid_t dxpl_id, hbool_t may_create);
H5_DLL herr_t H5HF_space_add(H5HF_hdr_t *hdr, hid_t dxpl_id,
H5HF_free_section_t *node, unsigned flags);
H5_DLL htri_t H5HF_space_find(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t request,
diff --git a/src/H5HFsection.c b/src/H5HFsection.c
index 62af976..81b353f 100644
--- a/src/H5HFsection.c
+++ b/src/H5HFsection.c
@@ -206,6 +206,7 @@ H5FS_section_class_t H5HF_FSPACE_SECT_CLS_SINGLE[1] = {{
H5HF_sect_single_shrink, /* Shrink container w/section */
H5HF_sect_single_free, /* Free section */
H5HF_sect_single_valid, /* Check validity of section */
+ NULL, /* Split section node for alignment */
NULL, /* Dump debugging for section */
}};
@@ -234,6 +235,7 @@ H5FS_section_class_t H5HF_FSPACE_SECT_CLS_FIRST_ROW[1] = {{
H5HF_sect_row_shrink, /* Shrink container w/section */
H5HF_sect_row_free, /* Free section */
H5HF_sect_row_valid, /* Check validity of section */
+ NULL, /* Split section node for alignment */
H5HF_sect_row_debug, /* Dump debugging for section */
}};
@@ -259,6 +261,7 @@ H5FS_section_class_t H5HF_FSPACE_SECT_CLS_NORMAL_ROW[1] = {{
NULL, /* Shrink container w/section */
H5HF_sect_row_free, /* Free section */
H5HF_sect_row_valid, /* Check validity of section */
+ NULL, /* Split section node for alignment */
H5HF_sect_row_debug, /* Dump debugging for section */
}};
@@ -287,6 +290,7 @@ H5FS_section_class_t H5HF_FSPACE_SECT_CLS_INDIRECT[1] = {{
NULL, /* Shrink container w/section */
NULL, /* Free section */
NULL, /* Check validity of section */
+ NULL, /* Split section node for alignment */
NULL, /* Dump debugging for section */
}};
@@ -333,7 +337,7 @@ H5HF_sect_init_cls(H5FS_section_class_t *cls, H5HF_hdr_t *hdr)
/* Allocate & initialize the class-private (i.e. private shared) information
* for this type of section
*/
- if(NULL == (cls_prvt = H5MM_malloc(sizeof(H5HF_sect_private_t))))
+ if(NULL == (cls_prvt = (H5HF_sect_private_t *)H5MM_malloc(sizeof(H5HF_sect_private_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
cls_prvt->hdr = hdr;
cls->cls_private = cls_prvt;
@@ -372,7 +376,7 @@ H5HF_sect_term_cls(H5FS_section_class_t *cls)
HDassert(cls);
/* Get pointer to class private info */
- cls_prvt = cls->cls_private;
+ cls_prvt = (H5HF_sect_private_t *)cls->cls_private;
/* Decrement reference count on heap header */
if(H5HF_hdr_decr(cls_prvt->hdr) < 0)
@@ -461,7 +465,7 @@ H5HF_sect_node_free(H5HF_free_section_t *sect, H5HF_indirect_t *iblock)
HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on section's indirect block")
/* Release the section */
- H5FL_FREE(H5HF_free_section_t, sect);
+ (void)H5FL_FREE(H5HF_free_section_t, sect);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -522,7 +526,7 @@ done:
} /* end if */
/* Release the section */
- H5FL_FREE(H5HF_free_section_t, sect);
+ (void)H5FL_FREE(H5HF_free_section_t, sect);
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
@@ -1185,7 +1189,7 @@ HDfprintf(stderr, "%s: (*sect).sect_info = {%a, %Hu, %u}\n", FUNC, (*sect)->sect
#ifdef QAK
HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr);
#endif /* QAK */
- if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr,
+ if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr,
dblock_size, (*sect)->u.single.parent, (*sect)->u.single.par_entry, H5AC_WRITE)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load fractal heap direct block")
HDassert(H5F_addr_eq(dblock->block_off + dblock_size, (*sect)->sect_info.addr + (*sect)->sect_info.size));
@@ -2159,7 +2163,7 @@ H5HF_sect_row_valid(const H5FS_section_class_t *cls, const H5FS_section_info_t *
HDassert(sect);
/* Retrieve class private information */
- cls_prvt = cls->cls_private;
+ cls_prvt = (H5HF_sect_private_t *)cls->cls_private;
hdr = cls_prvt->hdr;
#ifdef QAK
@@ -2430,7 +2434,7 @@ H5HF_sect_indirect_new(H5HF_hdr_t *hdr, haddr_t sect_off, hsize_t sect_size,
/* Set the 'indirect' specific fields */
if(iblock) {
sect->u.indirect.u.iblock = iblock;
- sect->u.indirect.iblock_entries = hdr->man_dtable.cparam.width *
+ sect->u.indirect.iblock_entries = hdr->man_dtable.cparam.width *
sect->u.indirect.u.iblock->max_rows;
if(H5HF_iblock_incr(sect->u.indirect.u.iblock) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared indirect block")
@@ -2464,7 +2468,7 @@ done:
HDONE_ERROR(H5E_HEAP, H5E_CANTDEC, NULL, "can't decrement reference count on shared indirect block")
/* Release the section */
- H5FL_FREE(H5HF_free_section_t, sect);
+ (void)H5FL_FREE(H5HF_free_section_t, sect);
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
@@ -2485,7 +2489,7 @@ done:
*-------------------------------------------------------------------------
*/
static H5HF_free_section_t *
-H5HF_sect_indirect_for_row(H5HF_hdr_t *hdr, H5HF_indirect_t *iblock,
+H5HF_sect_indirect_for_row(H5HF_hdr_t *hdr, H5HF_indirect_t *iblock,
H5HF_free_section_t *row_sect)
{
H5HF_free_section_t *sect = NULL; /* 'Indirect' free space section to add */
@@ -2505,7 +2509,7 @@ HDfprintf(stderr, "%s: Entering\n", FUNC);
#endif /* QAK */
/* Create free space section node */
- if(NULL == (sect = H5HF_sect_indirect_new(hdr, row_sect->sect_info.addr,
+ if(NULL == (sect = H5HF_sect_indirect_new(hdr, row_sect->sect_info.addr,
row_sect->sect_info.size, iblock, iblock->block_off,
row_sect->u.row.row, row_sect->u.row.col, row_sect->u.row.num_entries)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't create indirect section")
@@ -2514,7 +2518,7 @@ HDfprintf(stderr, "%s: Entering\n", FUNC);
sect->u.indirect.dir_nrows = 1;
/* Allocate space for the derived row sections */
- if(NULL == (sect->u.indirect.dir_rows = H5MM_malloc(sizeof(H5HF_free_section_t *))))
+ if(NULL == (sect->u.indirect.dir_rows = (H5HF_free_section_t **)H5MM_malloc(sizeof(H5HF_free_section_t *))))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, NULL, "allocation failed for row section pointer array")
/* Atatch the new row section to indirect section */
@@ -2605,7 +2609,7 @@ HDfprintf(stderr, "%s: end_row = %u, end_col = %u\n", FUNC, end_row, end_col);
sect->u.indirect.dir_nrows = 0;
/* Allocate space for the derived row sections */
- if(NULL == (sect->u.indirect.dir_rows = H5MM_malloc(sizeof(H5HF_free_section_t *) * dir_nrows)))
+ if(NULL == (sect->u.indirect.dir_rows = (H5HF_free_section_t **)H5MM_malloc(sizeof(H5HF_free_section_t *) * dir_nrows)))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for row section pointer array")
} /* end if */
else {
@@ -2635,14 +2639,13 @@ HDfprintf(stderr, "%s: end_row = %u, end_col = %u\n", FUNC, end_row, end_col);
+ indirect_start_col;
/* Compute ending indirect entry */
- indirect_end_entry = (end_row * hdr->man_dtable.cparam.width) +
- end_col;
+ indirect_end_entry = (end_row * hdr->man_dtable.cparam.width) + end_col;
/* Compute # of indirect entries covered */
sect->u.indirect.indir_nents = (indirect_end_entry - indirect_start_entry) + 1;
/* Allocate space for the child indirect sections */
- if(NULL == (sect->u.indirect.indir_ents = H5MM_malloc(sizeof(H5HF_free_section_t *) * sect->u.indirect.indir_nents)))
+ if(NULL == (sect->u.indirect.indir_ents = (H5HF_free_section_t **)H5MM_malloc(sizeof(H5HF_free_section_t *) * sect->u.indirect.indir_nents)))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for indirect section pointer array")
} /* end if */
else {
@@ -2794,7 +2797,7 @@ HDfprintf(stderr, "%s: child_iblock_addr = %a\n", FUNC, child_iblock_addr);
sect->u.indirect.dir_nrows = dir_nrows;
/* Make certain we've tracked the section's dependents correctly */
- HDassert(sect->u.indirect.rc ==
+ HDassert(sect->u.indirect.rc ==
(sect->u.indirect.indir_nents + sect->u.indirect.dir_nrows));
done:
@@ -2987,7 +2990,7 @@ HDfprintf(stderr, "%s: sect->u.indirect.u.iblock_off = %Hu\n", FUNC, sect->u.ind
sect->u.indirect.u.iblock = sec_iblock;
/* Set the number of entries in the indirect block */
- sect->u.indirect.iblock_entries = hdr->man_dtable.cparam.width *
+ sect->u.indirect.iblock_entries = hdr->man_dtable.cparam.width *
sect->u.indirect.u.iblock->max_rows;
/* Unlock indirect block */
@@ -3054,7 +3057,7 @@ HDfprintf(stderr, "%s: sect->u.indirect.u.iblock_off = %Hu\n", FUNC, sect->u.ind
sect->u.indirect.u.iblock = sect_iblock;
/* Set the number of entries in the indirect block */
- sect->u.indirect.iblock_entries = hdr->man_dtable.cparam.width *
+ sect->u.indirect.iblock_entries = hdr->man_dtable.cparam.width *
sect->u.indirect.u.iblock->max_rows;
/* Section is "live" now */
@@ -3228,7 +3231,7 @@ HDfprintf(stderr, "%s: sect->u.indirect.dir_nrows = %u\n", FUNC, sect->u.indirec
HDassert(sect->u.indirect.indir_ents);
/* Eliminate direct rows for this section */
- sect->u.indirect.dir_rows = H5MM_xfree(sect->u.indirect.dir_rows);
+ sect->u.indirect.dir_rows = (H5HF_free_section_t **)H5MM_xfree(sect->u.indirect.dir_rows);
/* Make new "first row" in indirect section */
if(row_sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW)
@@ -3310,17 +3313,17 @@ HDfprintf(stderr, "%s: iblock = %p, iblock_off = %Hu\n", FUNC, iblock, iblock_of
/* Set up direct row & indirect entry information for peer section */
peer_sect->u.indirect.dir_nrows = peer_dir_nrows;
- if(NULL == (peer_sect->u.indirect.dir_rows = H5MM_malloc(sizeof(H5HF_free_section_t *) * peer_dir_nrows)))
+ if(NULL == (peer_sect->u.indirect.dir_rows = (H5HF_free_section_t **)H5MM_malloc(sizeof(H5HF_free_section_t *) * peer_dir_nrows)))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for row section pointer array")
peer_sect->u.indirect.indir_nents = 0;
peer_sect->u.indirect.indir_ents = NULL;
/* Transfer row sections between current & peer sections */
HDmemcpy(&peer_sect->u.indirect.dir_rows[0],
- &sect->u.indirect.dir_rows[0],
+ &sect->u.indirect.dir_rows[0],
(sizeof(H5HF_free_section_t *) * peer_dir_nrows));
- HDmemmove(&sect->u.indirect.dir_rows[0],
- &sect->u.indirect.dir_rows[peer_dir_nrows],
+ HDmemmove(&sect->u.indirect.dir_rows[0],
+ &sect->u.indirect.dir_rows[peer_dir_nrows],
(sizeof(H5HF_free_section_t *) * (sect->u.indirect.dir_nrows - peer_dir_nrows)));
sect->u.indirect.dir_nrows -= peer_dir_nrows;
HDassert(row_sect == sect->u.indirect.dir_rows[0]);
@@ -3352,9 +3355,9 @@ HDfprintf(stderr, "%s: iblock = %p, iblock_off = %Hu\n", FUNC, iblock, iblock_of
sect->u.indirect.num_entries -= (peer_nentries + 1); /* Transferred entries, plus the entry allocated out of the row */
/* Make certain we've tracked the sections' dependents correctly */
- HDassert(sect->u.indirect.rc ==
+ HDassert(sect->u.indirect.rc ==
(sect->u.indirect.indir_nents + sect->u.indirect.dir_nrows));
- HDassert(peer_sect->u.indirect.rc ==
+ HDassert(peer_sect->u.indirect.rc ==
(peer_sect->u.indirect.indir_nents + peer_sect->u.indirect.dir_nrows));
} /* end else */
} /* end if */
@@ -3365,7 +3368,7 @@ HDfprintf(stderr, "%s: iblock = %p, iblock_off = %Hu\n", FUNC, iblock, iblock_of
HDassert(sect->u.indirect.dir_nrows == 0);
/* Eliminate direct rows for this section */
- sect->u.indirect.dir_rows = H5MM_xfree(sect->u.indirect.dir_rows);
+ sect->u.indirect.dir_rows = (H5HF_free_section_t **)H5MM_xfree(sect->u.indirect.dir_rows);
} /* end else */
done:
@@ -3497,7 +3500,7 @@ HDfprintf(stderr, "%s: Child is at end of indirect section\n", FUNC);
/* Adjust indirect entry information */
sect->u.indirect.indir_nents--;
if(sect->u.indirect.indir_nents == 0)
- sect->u.indirect.indir_ents = H5MM_xfree(sect->u.indirect.indir_ents);
+ sect->u.indirect.indir_ents = (H5HF_free_section_t **)H5MM_xfree(sect->u.indirect.indir_ents);
} /* end if */
else {
H5HF_free_section_t *peer_sect; /* Peer indirect section */
@@ -3571,18 +3574,18 @@ HDfprintf(stderr, "%s: peer_sect_addr = %a\n", FUNC, peer_sect_addr);
peer_sect->u.indirect.dir_nrows = 0;
peer_sect->u.indirect.dir_rows = NULL;
peer_sect->u.indirect.indir_nents = peer_nentries;
- if(NULL == (peer_sect->u.indirect.indir_ents = H5MM_malloc(sizeof(H5HF_free_section_t *) * peer_nentries)))
+ if(NULL == (peer_sect->u.indirect.indir_ents = (H5HF_free_section_t **)H5MM_malloc(sizeof(H5HF_free_section_t *) * peer_nentries)))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for indirect section pointer array")
/* Transfer child indirect sections between current & peer sections */
HDmemcpy(&peer_sect->u.indirect.indir_ents[0],
- &sect->u.indirect.indir_ents[sect->u.indirect.indir_nents - peer_nentries],
+ &sect->u.indirect.indir_ents[sect->u.indirect.indir_nents - peer_nentries],
(sizeof(H5HF_free_section_t *) * peer_nentries));
sect->u.indirect.indir_nents -= (peer_nentries + 1); /* Transferred blocks, plus child entry */
/* Eliminate indirect entries for this section, if appropriate */
if(sect->u.indirect.indir_nents == 0)
- sect->u.indirect.indir_ents = H5MM_xfree(sect->u.indirect.indir_ents);
+ sect->u.indirect.indir_ents = (H5HF_free_section_t **)H5MM_xfree(sect->u.indirect.indir_ents);
#ifdef QAK
HDfprintf(stderr, "%s: sect->u.indirect.indir_nents = %u\n", FUNC, sect->u.indirect.indir_nents);
#endif /* QAK */
@@ -3610,9 +3613,9 @@ HDfprintf(stderr, "%s: peer_sect->u.indirect.rc = %u\n", FUNC, peer_sect->u.indi
/* (Note modified on current section's ref. count, since we haven't
* detached the child section yet)
*/
- HDassert((sect->u.indirect.rc - 1) ==
+ HDassert((sect->u.indirect.rc - 1) ==
(sect->u.indirect.indir_nents + sect->u.indirect.dir_nrows));
- HDassert(peer_sect->u.indirect.rc ==
+ HDassert(peer_sect->u.indirect.rc ==
(peer_sect->u.indirect.indir_nents + peer_sect->u.indirect.dir_nrows));
} /* end else */
} /* end if */
@@ -3623,7 +3626,7 @@ HDfprintf(stderr, "%s: peer_sect->u.indirect.rc = %u\n", FUNC, peer_sect->u.indi
HDassert(sect->u.indirect.indir_nents == 0);
/* Eliminate indirect entries for this section */
- sect->u.indirect.indir_ents = H5MM_xfree(sect->u.indirect.indir_ents);
+ sect->u.indirect.indir_ents = (H5HF_free_section_t **)H5MM_xfree(sect->u.indirect.indir_ents);
} /* end else */
/* Decrement # of sections which depend on this row */
@@ -3776,10 +3779,9 @@ H5HF_sect_indirect_merge_row(H5HF_hdr_t *hdr, hid_t dxpl_id,
unsigned start_entry1; /* Start entry for section #1 */
unsigned start_row1, start_col1; /* Starting row & column for section #1 */
unsigned end_entry1; /* End entry for section #1 */
- unsigned end_row1, end_col1; /* Ending row & column for section #1 */
+ unsigned end_row1; /* Ending row for section #1 */
unsigned start_entry2; /* Start entry for section #2 */
unsigned start_row2, start_col2; /* Starting row & column for section #2 */
- unsigned end_row2, end_col2; /* Ending row & column for section #2 */
unsigned end_entry2; /* End entry for section #2 */
hbool_t merged_rows; /* Flag to indicate that rows was merged together */
unsigned u; /* Local index variable */
@@ -3822,24 +3824,20 @@ HDfprintf(stderr, "%s: sect2->sect_info = {%a, %Hu, %u, %s}\n", FUNC, sect2->sec
start_entry1 = (start_row1 * hdr->man_dtable.cparam.width) + start_col1;
end_entry1 = (start_entry1 + sect1->u.indirect.num_entries) - 1;
end_row1 = end_entry1 / hdr->man_dtable.cparam.width;
- end_col1 = end_entry1 % hdr->man_dtable.cparam.width;
#ifdef QAK
HDfprintf(stderr, "%s: sect1->u.indirect.dir_nrows = %u\n", FUNC, sect1->u.indirect.dir_nrows);
HDfprintf(stderr, "%s: start_row1 = %u, start_col1 = %u, start_entry1 = %u\n", FUNC, start_row1, start_col1, start_entry1);
HDfprintf(stderr, "%s: sect1->u.indirect.num_entries = %u\n", FUNC, sect1->u.indirect.num_entries);
-HDfprintf(stderr, "%s: end_row1 = %u, end_col1 = %u, end_entry1 = %u\n", FUNC, end_row1, end_col1, end_entry1);
+HDfprintf(stderr, "%s: end_row1 = %u, end_entry1 = %u\n", FUNC, end_row1, end_entry1);
#endif /* QAK */
start_row2 = sect2->u.indirect.row;
start_col2 = sect2->u.indirect.col;
start_entry2 = (start_row2 * hdr->man_dtable.cparam.width) + start_col2;
end_entry2 = (start_entry2 + sect2->u.indirect.num_entries) - 1;
- end_row2 = end_entry2 / hdr->man_dtable.cparam.width;
- end_col2 = end_entry2 % hdr->man_dtable.cparam.width;
#ifdef QAK
HDfprintf(stderr, "%s: sect2->u.indirect.dir_nrows = %u\n", FUNC, sect2->u.indirect.dir_nrows);
HDfprintf(stderr, "%s: start_row2 = %u, start_col2 = %u, start_entry2 = %u\n", FUNC, start_row2, start_col2, start_entry2);
HDfprintf(stderr, "%s: sect2->u.indirect.num_entries = %u\n", FUNC, sect2->u.indirect.num_entries);
-HDfprintf(stderr, "%s: end_row2 = %u, end_col2 = %u, end_entry2 = %u\n", FUNC, end_row2, end_col2, end_entry2);
#endif /* QAK */
/* Check for direct sections in second section */
@@ -3912,13 +3910,13 @@ HDfprintf(stderr, "%s: nrows_moved2 = %u\n", FUNC, nrows_moved2);
H5HF_free_section_t **new_dir_rows; /* Pointer to new array of direct row pointers */
/* Extend the first section's row array */
- if(NULL == (new_dir_rows = H5MM_realloc(sect1->u.indirect.dir_rows, sizeof(H5HF_free_section_t *) * new_dir_nrows1)))
+ if(NULL == (new_dir_rows = (H5HF_free_section_t **)H5MM_realloc(sect1->u.indirect.dir_rows, sizeof(H5HF_free_section_t *) * new_dir_nrows1)))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for row section pointer array")
sect1->u.indirect.dir_rows = new_dir_rows;
/* Transfer the second section's rows to first section */
- HDmemcpy(&sect1->u.indirect.dir_rows[sect1->u.indirect.dir_nrows],
- &sect2->u.indirect.dir_rows[src_row2],
+ HDmemcpy(&sect1->u.indirect.dir_rows[sect1->u.indirect.dir_nrows],
+ &sect2->u.indirect.dir_rows[src_row2],
(sizeof(H5HF_free_section_t *) * nrows_moved2));
/* Re-target the row sections moved from second section */
@@ -3958,13 +3956,13 @@ HDfprintf(stderr, "%s: nrows_moved2 = %u\n", FUNC, nrows_moved2);
H5HF_free_section_t **new_indir_ents; /* Pointer to new array of indirect entries */
/* Extend the first section's entry array */
- if(NULL == (new_indir_ents = H5MM_realloc(sect1->u.indirect.indir_ents, sizeof(H5HF_free_section_t *) * new_indir_nents1)))
+ if(NULL == (new_indir_ents = (H5HF_free_section_t **)H5MM_realloc(sect1->u.indirect.indir_ents, sizeof(H5HF_free_section_t *) * new_indir_nents1)))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for row section pointer array")
sect1->u.indirect.indir_ents = new_indir_ents;
/* Transfer the second section's entries to first section */
- HDmemcpy(&sect1->u.indirect.indir_ents[sect1->u.indirect.indir_nents],
- &sect2->u.indirect.indir_ents[0],
+ HDmemcpy(&sect1->u.indirect.indir_ents[sect1->u.indirect.indir_nents],
+ &sect2->u.indirect.indir_ents[0],
(sizeof(H5HF_free_section_t *) * sect2->u.indirect.indir_nents));
} /* end else */
@@ -3985,7 +3983,7 @@ HDfprintf(stderr, "%s: nrows_moved2 = %u\n", FUNC, nrows_moved2);
sect1->u.indirect.span_size += sect2->u.indirect.span_size;
/* Make certain we've tracked the first section's dependents correctly */
- HDassert(sect1->u.indirect.rc ==
+ HDassert(sect1->u.indirect.rc ==
(sect1->u.indirect.indir_nents + sect1->u.indirect.dir_nrows));
/* Wrap up, freeing or re-inserting second row section */
@@ -4103,7 +4101,7 @@ HDfprintf(stderr, "%s: par_entry = %u, par_row = %u, par_col = %u\n", FUNC, par_
HDassert(par_iblock);
/* Create parent indirect section */
- if(NULL == (par_sect = H5HF_sect_indirect_new(hdr, sect->sect_info.addr,
+ if(NULL == (par_sect = H5HF_sect_indirect_new(hdr, sect->sect_info.addr,
sect->sect_info.size, par_iblock, par_iblock->block_off,
par_row, par_col, 1)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section")
@@ -4114,7 +4112,7 @@ HDfprintf(stderr, "%s: par_entry = %u, par_row = %u, par_col = %u\n", FUNC, par_
/* Allocate space for the child indirect sections */
par_sect->u.indirect.indir_nents = 1;
- if(NULL == (par_sect->u.indirect.indir_ents = H5MM_malloc(sizeof(H5HF_free_section_t *))))
+ if(NULL == (par_sect->u.indirect.indir_ents = (H5HF_free_section_t **)H5MM_malloc(sizeof(H5HF_free_section_t *))))
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for indirect section pointer array")
/* Attach sections together */
@@ -4287,7 +4285,7 @@ H5HF_sect_indirect_deserialize(H5HF_hdr_t *hdr, hid_t dxpl_id,
unsigned *des_flags)
{
H5HF_free_section_t *new_sect; /* New indirect section */
- hsize_t iblock_off; /* Indirect block's offset */
+ hsize_t iblock_off; /* Indirect block's offset */
unsigned start_row; /* Indirect section's start row */
unsigned start_col; /* Indirect section's start column */
unsigned nentries; /* Indirect section's number of entries */
@@ -4387,10 +4385,10 @@ H5HF_sect_indirect_free(H5HF_free_section_t *sect)
HDassert(sect);
/* Release the memory for tracking direct rows */
- sect->u.indirect.dir_rows = H5MM_xfree(sect->u.indirect.dir_rows);
+ sect->u.indirect.dir_rows = (H5HF_free_section_t **)H5MM_xfree(sect->u.indirect.dir_rows);
/* Release the memory for tracking indirect entries */
- sect->u.indirect.indir_ents = H5MM_xfree(sect->u.indirect.indir_ents);
+ sect->u.indirect.indir_ents = (H5HF_free_section_t **)H5MM_xfree(sect->u.indirect.indir_ents);
/* Check for live reference to an indirect block */
if(sect->sect_info.state == H5FS_SECT_LIVE) {
@@ -4428,7 +4426,6 @@ H5HF_sect_indirect_valid(const H5HF_hdr_t *hdr, const H5HF_free_section_t *sect)
unsigned start_col; /* Column for first block covered */
unsigned start_entry; /* Entry for first block covered */
unsigned end_row; /* Row for last block covered */
- unsigned end_col; /* Column for last block covered */
unsigned end_entry; /* Entry for last block covered */
unsigned u; /* Local index variable */
@@ -4455,10 +4452,9 @@ HDfprintf(stderr, "%u, %u, %u}\n", sect->u.indirect.row, sect->u.indirect.col, s
/* Compute ending entry, column & row */
end_entry = (start_entry + sect->u.indirect.num_entries) - 1;
end_row = end_entry / hdr->man_dtable.cparam.width;
- end_col = end_entry % hdr->man_dtable.cparam.width;
#ifdef QAK
HDfprintf(stderr, "%s: start_row = %u, start_col = %u, start_entry = %u\n", "H5HF_sect_indirect_valid", start_row, start_col, start_entry);
-HDfprintf(stderr, "%s: end_row = %u, end_col = %u, end_entry = %u\n", "H5HF_sect_indirect_valid", end_row, end_col, end_entry);
+HDfprintf(stderr, "%s: end_row = %u, end_entry = %u\n", "H5HF_sect_indirect_valid", end_row, end_entry);
#endif /* QAK */
/* Sanity check any direct rows */
diff --git a/src/H5HFspace.c b/src/H5HFspace.c
index 16eae51..aa419de 100644
--- a/src/H5HFspace.c
+++ b/src/H5HFspace.c
@@ -44,6 +44,8 @@
#define H5HF_FSPACE_SHRINK 80 /* Percent of "normal" size to shrink serialized free space size */
#define H5HF_FSPACE_EXPAND 120 /* Percent of "normal" size to expand serialized free space size */
+#define H5HF_FSPACE_THRHD_DEF 1 /* Default: no alignment threshold */
+#define H5HF_FSPACE_ALIGN_DEF 1 /* Default: no alignment */
/******************/
/* Local Typedefs */
@@ -91,10 +93,15 @@
* koziol@ncsa.uiuc.edu
* May 2 2006
*
+ * Modifications:
+ * Vailin Choi, July 29th, 2008
+ * Pass values of alignment and threshold to FS_create() and FS_open()
+ * for handling alignment.
+ *
*-------------------------------------------------------------------------
*/
herr_t
-H5HF_space_start(H5HF_hdr_t *hdr, hid_t dxpl_id)
+H5HF_space_start(H5HF_hdr_t *hdr, hid_t dxpl_id, hbool_t may_create)
{
const H5FS_section_class_t *classes[] = { /* Free space section classes implemented for fractal heap */
H5HF_FSPACE_SECT_CLS_SINGLE,
@@ -114,23 +121,27 @@ H5HF_space_start(H5HF_hdr_t *hdr, hid_t dxpl_id)
if(H5F_addr_defined(hdr->fs_addr)) {
/* Open an existing free space structure for the heap */
if(NULL == (hdr->fspace = H5FS_open(hdr->f, dxpl_id, hdr->fs_addr,
- NELMTS(classes), classes, hdr)))
+ NELMTS(classes), classes, hdr, (hsize_t)H5HF_FSPACE_THRHD_DEF, (hsize_t)H5HF_FSPACE_ALIGN_DEF)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize free space info")
} /* end if */
else {
- H5FS_create_t fs_create; /* Free space creation parameters */
-
- /* Set the free space creation parameters */
- fs_create.client = H5FS_CLIENT_FHEAP_ID;
- fs_create.shrink_percent = H5HF_FSPACE_SHRINK;
- fs_create.expand_percent = H5HF_FSPACE_EXPAND;
- fs_create.max_sect_size = hdr->man_dtable.cparam.max_direct_size;
- fs_create.max_sect_addr = hdr->man_dtable.cparam.max_index;
-
- /* Create the free space structure for the heap */
- if(NULL == (hdr->fspace = H5FS_create(hdr->f, dxpl_id, &hdr->fs_addr,
- &fs_create, NELMTS(classes), classes, hdr)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize free space info")
+ /* Check if we are allowed to create the free space manager */
+ if(may_create) {
+ H5FS_create_t fs_create; /* Free space creation parameters */
+
+ /* Set the free space creation parameters */
+ fs_create.client = H5FS_CLIENT_FHEAP_ID;
+ fs_create.shrink_percent = H5HF_FSPACE_SHRINK;
+ fs_create.expand_percent = H5HF_FSPACE_EXPAND;
+ fs_create.max_sect_size = hdr->man_dtable.cparam.max_direct_size;
+ fs_create.max_sect_addr = hdr->man_dtable.cparam.max_index;
+
+ /* Create the free space structure for the heap */
+ if(NULL == (hdr->fspace = H5FS_create(hdr->f, dxpl_id, &hdr->fs_addr,
+ &fs_create, NELMTS(classes), classes, hdr, (hsize_t)H5HF_FSPACE_THRHD_DEF, (hsize_t)H5HF_FSPACE_ALIGN_DEF)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize free space info")
+ HDassert(H5F_addr_defined(hdr->fs_addr));
+ } /* end if */
} /* end else */
done:
@@ -170,7 +181,7 @@ H5HF_space_add(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *node,
/* Check if the free space for the heap has been initialized */
if(!hdr->fspace)
- if(H5HF_space_start(hdr, dxpl_id) < 0)
+ if(H5HF_space_start(hdr, dxpl_id, TRUE) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize heap free space")
/* Construct user data */
@@ -204,7 +215,7 @@ done:
htri_t
H5HF_space_find(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t request, H5HF_free_section_t **node)
{
- htri_t node_found; /* Whether an existing free list node was found */
+ htri_t node_found = FALSE; /* Whether an existing free list node was found */
htri_t ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_space_find)
@@ -218,12 +229,13 @@ H5HF_space_find(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t request, H5HF_free_secti
/* Check if the free space for the heap has been initialized */
if(!hdr->fspace)
- if(H5HF_space_start(hdr, dxpl_id) < 0)
+ if(H5HF_space_start(hdr, dxpl_id, FALSE) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize heap free space")
/* Search for free space in the heap */
- if((node_found = H5FS_sect_find(hdr->f, dxpl_id, hdr->fspace, request, (H5FS_section_info_t **)node)) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't locate free space in fractal heap")
+ if(hdr->fspace)
+ if((node_found = H5FS_sect_find(hdr->f, dxpl_id, hdr->fspace, request, (H5FS_section_info_t **)node)) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't locate free space in fractal heap")
/* Set return value */
ret_value = node_found;
@@ -262,12 +274,16 @@ H5HF_space_size(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t *fs_size)
/* Check if the free space for the heap has been initialized */
if(!hdr->fspace)
- if(H5HF_space_start(hdr, dxpl_id) < 0)
+ if(H5HF_space_start(hdr, dxpl_id, FALSE) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize heap free space")
/* Get free space metadata size */
- if(H5FS_size(hdr->f, hdr->fspace, fs_size) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't retrieve FS meta storage info")
+ if(hdr->fspace) {
+ if(H5FS_size(hdr->f, hdr->fspace, fs_size) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't retrieve FS meta storage info")
+ } /* end if */
+ else
+ *fs_size = 0;
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -343,7 +359,7 @@ H5HF_space_close(H5HF_hdr_t *hdr, hid_t dxpl_id)
hsize_t nsects; /* Number of sections for this heap */
/* Retrieve the number of sections for this heap */
- if(H5FS_get_sect_count(hdr->fspace, &nsects) < 0)
+ if(H5FS_sect_stats(hdr->fspace, NULL, &nsects) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTCOUNT, FAIL, "can't query free space section count")
#ifdef QAK
HDfprintf(stderr, "%s: nsects = %Hu\n", FUNC, nsects);
diff --git a/src/H5HFstat.c b/src/H5HFstat.c
index 2e3e189..8d6b2ba 100644
--- a/src/H5HFstat.c
+++ b/src/H5HFstat.c
@@ -112,7 +112,7 @@ H5HF_stat_info(const H5HF_t *fh, H5HF_stat_t *stats)
* Function: H5HF_size
*
* Purpose: Retrieve storage info for:
- * 1. fractal heap
+ * 1. fractal heap
* 2. btree storage used by huge objects in fractal heap
* 3. free space storage info
*
@@ -128,6 +128,7 @@ H5HF_size(const H5HF_t *fh, hid_t dxpl_id, hsize_t *heap_size)
{
H5HF_hdr_t *hdr; /* Fractal heap header */
herr_t ret_value = SUCCEED; /* Return value */
+ hsize_t meta_size = 0; /* free space storage size */
FUNC_ENTER_NOAPI(H5HF_size, FAIL)
@@ -147,7 +148,7 @@ H5HF_size(const H5HF_t *fh, hid_t dxpl_id, hsize_t *heap_size)
/* Check for indirect blocks for managed objects */
if(H5F_addr_defined(hdr->man_dtable.table_addr) && hdr->man_dtable.curr_root_rows != 0)
- if(H5HF_man_iblock_size(hdr->f, dxpl_id, hdr, hdr->man_dtable.table_addr, hdr->man_dtable.curr_root_rows, heap_size) < 0)
+ if(H5HF_man_iblock_size(hdr->f, dxpl_id, hdr, hdr->man_dtable.table_addr, hdr->man_dtable.curr_root_rows, NULL, 0, heap_size) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to get fractal heap storage info for indirect block")
/* Get B-tree storage for huge objects in fractal heap */
@@ -172,9 +173,11 @@ H5HF_size(const H5HF_t *fh, hid_t dxpl_id, hsize_t *heap_size)
} /* end if */
/* Get storage for free-space tracking info */
- if(H5F_addr_defined(hdr->fs_addr))
- if(H5HF_space_size(hdr, dxpl_id, heap_size) < 0)
+ if(H5F_addr_defined(hdr->fs_addr)) {
+ if(H5HF_space_size(hdr, dxpl_id, &meta_size) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTGET, FAIL, "can't retrieve FS meta storage info")
+ *heap_size += meta_size;
+ }
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5HG.c b/src/H5HG.c
index 4ee63d1..b5f8988 100644
--- a/src/H5HG.c
+++ b/src/H5HG.c
@@ -37,33 +37,28 @@
* in the collection, and temporal locality.
*/
+/****************/
+/* Module Setup */
+/****************/
+
#define H5F_PACKAGE /*suppress error about including H5Fpkg */
#define H5HG_PACKAGE /*suppress error about including H5HGpkg */
+/***********/
+/* Headers */
+/***********/
#include "H5private.h" /* Generic Functions */
-#include "H5ACprivate.h" /* Metadata cache */
#include "H5Eprivate.h" /* Error handling */
#include "H5Fpkg.h" /* File access */
-#include "H5FLprivate.h" /* Free lists */
#include "H5HGpkg.h" /* Global heaps */
#include "H5MFprivate.h" /* File memory management */
#include "H5MMprivate.h" /* Memory management */
-/* Private macros */
-/*
- * Global heap collection version.
- */
-#define H5HG_VERSION 1
-
-/*
- * All global heap collections are at least this big. This allows us to read
- * most collections with a single read() since we don't have to read a few
- * bytes of header to figure out the size. If the heap is larger than this
- * then a second read gets the rest after we've decoded the header.
- */
-#define H5HG_MINSIZE 4096
+/****************/
+/* Local Macros */
+/****************/
/*
* Limit global heap collections to the some reasonable size. This is
@@ -73,12 +68,6 @@
#define H5HG_MAXSIZE 65536
/*
- * Maximum length of the CWFS list, the list of remembered collections that
- * have free space.
- */
-#define H5HG_NCWFS 16
-
-/*
* The maximum number of links allowed to a global heap object.
*/
#define H5HG_MAXLINK 65535
@@ -88,70 +77,47 @@
*/
#define H5HG_MAXIDX 65535
-/*
- * The size of the collection header, always a multiple of the alignment so
- * that the stuff that follows the header is aligned.
- */
-#define H5HG_SIZEOF_HDR(f) \
- H5HG_ALIGN(4 + /*magic number */ \
- 1 + /*version number */ \
- 3 + /*reserved */ \
- H5F_SIZEOF_SIZE(f)) /*collection size */
-/*
- * The initial guess for the number of messages in a collection. We assume
- * that all objects in that collection are zero length, giving the maximum
- * possible number of objects in the collection. The collection itself has
- * some overhead and each message has some overhead. The `+2' accounts for
- * rounding and for the free space object.
- */
-#define H5HG_NOBJS(f,z) (int)((((z)-H5HG_SIZEOF_HDR(f))/ \
- H5HG_SIZEOF_OBJHDR(f)+2))
+/******************/
+/* Local Typedefs */
+/******************/
-/*
- * Makes a global heap object pointer undefined, or checks whether one is
- * defined.
- */
-#define H5HG_undef(HGP) ((HGP)->idx=0)
-#define H5HG_defined(HGP) ((HGP)->idx!=0)
-/* Private typedefs */
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
-/* PRIVATE PROTOTYPES */
static haddr_t H5HG_create(H5F_t *f, hid_t dxpl_id, size_t size);
-#ifdef NOT_YET
-static void *H5HG_peek(H5F_t *f, hid_t dxpl_id, H5HG_t *hobj);
-#endif /* NOT_YET */
-
-/* Metadata cache callbacks */
-static H5HG_heap_t *H5HG_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1,
- void *udata2);
-static herr_t H5HG_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr,
- H5HG_heap_t *heap, unsigned UNUSED * flags_ptr);
-static herr_t H5HG_dest(H5F_t *f, H5HG_heap_t *heap);
-static herr_t H5HG_clear(H5F_t *f, H5HG_heap_t *heap, hbool_t destroy);
-static herr_t H5HG_compute_size(const H5F_t *f, const H5HG_heap_t *heap, size_t *size_ptr);
-/*
- * H5HG inherits cache-like properties from H5AC
- */
-const H5AC_class_t H5AC_GHEAP[1] = {{
- H5AC_GHEAP_ID,
- (H5AC_load_func_t)H5HG_load,
- (H5AC_flush_func_t)H5HG_flush,
- (H5AC_dest_func_t)H5HG_dest,
- (H5AC_clear_func_t)H5HG_clear,
- (H5AC_size_func_t)H5HG_compute_size,
-}};
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
/* Declare a free list to manage the H5HG_t struct */
-H5FL_DEFINE_STATIC(H5HG_heap_t);
+H5FL_DEFINE(H5HG_heap_t);
/* Declare a free list to manage sequences of H5HG_obj_t's */
-H5FL_SEQ_DEFINE_STATIC(H5HG_obj_t);
+H5FL_SEQ_DEFINE(H5HG_obj_t);
/* Declare a PQ free list to manage heap chunks */
-H5FL_BLK_DEFINE_STATIC(heap_chunk);
+H5FL_BLK_DEFINE(gheap_chunk);
+
/*-------------------------------------------------------------------------
@@ -220,7 +186,7 @@ H5HG_create (H5F_t *f, hid_t dxpl_id, size_t size)
heap->addr = addr;
heap->size = size;
- if (NULL==(heap->chunk = H5FL_BLK_MALLOC (heap_chunk,size)))
+ if (NULL==(heap->chunk = H5FL_BLK_MALLOC (gheap_chunk,size)))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, \
"memory allocation failed");
#ifdef H5_CLEAR_MEMORY
@@ -233,8 +199,8 @@ HDmemset(heap->chunk, 0, size);
"memory allocation failed");
/* Initialize the header */
- HDmemcpy (heap->chunk, H5HG_MAGIC, (size_t)H5HG_SIZEOF_MAGIC);
- p = heap->chunk + H5HG_SIZEOF_MAGIC;
+ HDmemcpy (heap->chunk, H5HG_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ p = heap->chunk + H5_SIZEOF_MAGIC;
*p++ = H5HG_VERSION;
*p++ = 0; /*reserved*/
*p++ = 0; /*reserved*/
@@ -268,18 +234,18 @@ HDmemset(heap->chunk, 0, size);
#endif /* OLD_WAY */
/* Add this heap to the beginning of the CWFS list */
- if (NULL==f->shared->cwfs) {
- f->shared->cwfs = H5MM_malloc (H5HG_NCWFS * sizeof(H5HG_heap_t*));
- if (NULL==(f->shared->cwfs))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, \
- "memory allocation failed");
+ if(NULL == f->shared->cwfs) {
+ f->shared->cwfs = (H5HG_heap_t **)H5MM_malloc(H5HG_NCWFS * sizeof(H5HG_heap_t *));
+ if(NULL == (f->shared->cwfs))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, "memory allocation failed")
f->shared->cwfs[0] = heap;
f->shared->ncwfs = 1;
- } else {
- HDmemmove (f->shared->cwfs+1, f->shared->cwfs,
- MIN (f->shared->ncwfs, H5HG_NCWFS-1)*sizeof(H5HG_heap_t*));
+ } /* end if */
+ else {
+ HDmemmove(f->shared->cwfs + 1, f->shared->cwfs,
+ MIN(f->shared->ncwfs, H5HG_NCWFS - 1) * sizeof(H5HG_heap_t *));
f->shared->cwfs[0] = heap;
- f->shared->ncwfs = MIN (H5HG_NCWFS, f->shared->ncwfs+1);
+ f->shared->ncwfs = MIN(H5HG_NCWFS, f->shared->ncwfs+1);
}
/* Add the heap to the cache */
@@ -301,361 +267,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5HG_load
- *
- * Purpose: Loads a global heap collection from disk.
- *
- * Return: Success: Ptr to a global heap collection.
- *
- * Failure: NULL
- *
- * Programmer: Robb Matzke
- * Friday, March 27, 1998
- *
- * Modifications:
- * Robb Matzke, 1999-07-28
- * The ADDR argument is passed by value.
- *
- * Quincey Koziol, 2002-7-180
- * Added dxpl parameter to allow more control over I/O from metadata
- * cache.
- *-------------------------------------------------------------------------
- */
-static H5HG_heap_t *
-H5HG_load (H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * udata1,
- void UNUSED * udata2)
-{
- H5HG_heap_t *heap = NULL;
- uint8_t *p = NULL;
- int i;
- size_t nalloc, need;
- size_t max_idx=0; /* The maximum index seen */
- H5HG_heap_t *ret_value = NULL; /* Return value */
-
- FUNC_ENTER_NOAPI(H5HG_load, NULL);
-
- /* check arguments */
- assert (f);
- assert (H5F_addr_defined (addr));
- assert (!udata1);
- assert (!udata2);
-
- /* Read the initial 4k page */
- if(NULL == (heap = H5FL_CALLOC (H5HG_heap_t)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
- heap->addr = addr;
- if(NULL == (heap->chunk = H5FL_BLK_MALLOC(heap_chunk, (size_t)H5HG_MINSIZE)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
- if(H5F_block_read(f, H5FD_MEM_GHEAP, addr, (size_t)H5HG_MINSIZE, dxpl_id, heap->chunk)<0)
- HGOTO_ERROR (H5E_HEAP, H5E_READERROR, NULL, "unable to read global heap collection");
-
- /* Magic number */
- if(HDmemcmp(heap->chunk, H5HG_MAGIC, (size_t)H5HG_SIZEOF_MAGIC))
- HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL, "bad global heap collection signature");
- p = heap->chunk + H5HG_SIZEOF_MAGIC;
-
- /* Version */
- if (H5HG_VERSION!=*p++)
- HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL, "wrong version number in global heap");
-
- /* Reserved */
- p += 3;
-
- /* Size */
- H5F_DECODE_LENGTH (f, p, heap->size);
- assert (heap->size>=H5HG_MINSIZE);
-
- /*
- * If we didn't read enough in the first try, then read the rest of the
- * collection now.
- */
- if (heap->size > H5HG_MINSIZE) {
- haddr_t next_addr = addr + (hsize_t)H5HG_MINSIZE;
- if (NULL==(heap->chunk = H5FL_BLK_REALLOC (heap_chunk, heap->chunk, heap->size)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
- if (H5F_block_read (f, H5FD_MEM_GHEAP, next_addr, (heap->size-H5HG_MINSIZE), dxpl_id, heap->chunk+H5HG_MINSIZE)<0)
- HGOTO_ERROR (H5E_HEAP, H5E_READERROR, NULL, "unable to read global heap collection");
- }
-
- /* Decode each object */
- p = heap->chunk + H5HG_SIZEOF_HDR (f);
- nalloc = H5HG_NOBJS (f, heap->size);
- if (NULL==(heap->obj = H5FL_SEQ_MALLOC (H5HG_obj_t,nalloc)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
- heap->obj[0].size=heap->obj[0].nrefs=0;
- heap->obj[0].begin=NULL;
-
- heap->nalloc = nalloc;
- while (p<heap->chunk+heap->size) {
- if (p+H5HG_SIZEOF_OBJHDR(f)>heap->chunk+heap->size) {
- /*
- * The last bit of space is too tiny for an object header, so we
- * assume that it's free space.
- */
- assert (NULL==heap->obj[0].begin);
- heap->obj[0].size = (heap->chunk+heap->size) - p;
- heap->obj[0].begin = p;
- p += heap->obj[0].size;
- } else {
- unsigned idx;
- uint8_t *begin = p;
-
- UINT16DECODE (p, idx);
-
- /* Check if we need more room to store heap objects */
- if(idx>=heap->nalloc) {
- size_t new_alloc; /* New allocation number */
- H5HG_obj_t *new_obj; /* New array of object descriptions */
-
- /* Determine the new number of objects to index */
- new_alloc=MAX(heap->nalloc*2,(idx+1));
-
- /* Reallocate array of objects */
- if (NULL==(new_obj = H5FL_SEQ_REALLOC (H5HG_obj_t, heap->obj, new_alloc)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
-
- /* Update heap information */
- heap->nalloc=new_alloc;
- heap->obj=new_obj;
- } /* end if */
-
- UINT16DECODE (p, heap->obj[idx].nrefs);
- p += 4; /*reserved*/
- H5F_DECODE_LENGTH (f, p, heap->obj[idx].size);
- heap->obj[idx].begin = begin;
- /*
- * The total storage size includes the size of the object header
- * and is zero padded so the next object header is properly
- * aligned. The last bit of space is the free space object whose
- * size is never padded and already includes the object header.
- */
- if (idx>0) {
- need = H5HG_SIZEOF_OBJHDR(f) + H5HG_ALIGN(heap->obj[idx].size);
-
- /* Check for "gap" in index numbers (caused by deletions) and fill in heap object values */
- if(idx>(max_idx+1))
- HDmemset(&heap->obj[max_idx+1],0,sizeof(H5HG_obj_t)*(idx-(max_idx+1)));
- max_idx=idx;
- } else {
- need = heap->obj[idx].size;
- }
- p = begin + need;
- }
- }
- assert(p==heap->chunk+heap->size);
- assert(H5HG_ISALIGNED(heap->obj[0].size));
-
- /* Set the next index value to use */
- if(max_idx>0)
- heap->nused=max_idx+1;
- else
- heap->nused=1;
-
- /*
- * Add the new heap to the CWFS list, removing some other entry if
- * necessary to make room. We remove the right-most entry that has less
- * free space than this heap.
- */
- if (!f->shared->cwfs) {
- f->shared->cwfs = H5MM_malloc (H5HG_NCWFS*sizeof(H5HG_heap_t*));
- if (NULL==f->shared->cwfs)
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
- f->shared->ncwfs = 1;
- f->shared->cwfs[0] = heap;
- } else if (H5HG_NCWFS==f->shared->ncwfs) {
- for (i=H5HG_NCWFS-1; i>=0; --i) {
- if (f->shared->cwfs[i]->obj[0].size < heap->obj[0].size) {
- HDmemmove (f->shared->cwfs+1, f->shared->cwfs, i * sizeof(H5HG_heap_t*));
- f->shared->cwfs[0] = heap;
- break;
- }
- }
- } else {
- HDmemmove (f->shared->cwfs+1, f->shared->cwfs, f->shared->ncwfs*sizeof(H5HG_heap_t*));
- f->shared->ncwfs += 1;
- f->shared->cwfs[0] = heap;
- }
-
- ret_value = heap;
-
-done:
- if (!ret_value && heap) {
- if(H5HG_dest(f,heap)<0)
- HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, NULL, "unable to destroy global heap collection");
- }
- FUNC_LEAVE_NOAPI(ret_value);
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5HG_flush
- *
- * Purpose: Flushes a global heap collection from memory to disk if it's
- * dirty. Optionally deletes teh heap from memory.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Robb Matzke
- * Friday, March 27, 1998
- *
- * Modifications:
- * Robb Matzke, 1999-07-28
- * The ADDR argument is passed by value.
- *
- * Quincey Koziol, 2002-7-180
- * Added dxpl parameter to allow more control over I/O from metadata
- * cache.
- *
- * JRM -- 8/21/06
- * Added the flags_ptr parameter. This parameter exists to
- * allow the flush routine to report to the cache if the
- * entry is resized or renamed as a result of the flush.
- * *flags_ptr is set to H5C_CALLBACK__NO_FLAGS_SET on entry.
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HG_flush (H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HG_heap_t *heap, unsigned UNUSED * flags_ptr)
-{
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5HG_flush, FAIL);
-
- /* Check arguments */
- assert (f);
- assert (H5F_addr_defined (addr));
- assert (H5F_addr_eq (addr, heap->addr));
- assert (heap);
-
- if (heap->cache_info.is_dirty) {
- if (H5F_block_write (f, H5FD_MEM_GHEAP, addr, heap->size, dxpl_id, heap->chunk)<0)
- HGOTO_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write global heap collection to file");
- heap->cache_info.is_dirty = FALSE;
- }
-
- if (destroy) {
- if(H5HG_dest(f,heap)<0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy global heap collection");
- }
-
-done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5HG_dest
- *
- * Purpose: Destroys a global heap collection in memory
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Wednesday, January 15, 2003
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HG_dest (H5F_t *f, H5HG_heap_t *heap)
-{
- int i;
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HG_dest);
-
- /* Check arguments */
- assert (heap);
-
- /* Verify that node is clean */
- assert (heap->cache_info.is_dirty==FALSE);
-
- for (i=0; i<f->shared->ncwfs; i++) {
- if (f->shared->cwfs[i]==heap) {
- f->shared->ncwfs -= 1;
- HDmemmove (f->shared->cwfs+i, f->shared->cwfs+i+1, (f->shared->ncwfs-i) * sizeof(H5HG_heap_t*));
- break;
- }
- }
-
- 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);
-} /* H5HG_dest() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5HG_clear
- *
- * Purpose: Mark a global heap in memory as non-dirty.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Thursday, March 20, 2003
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HG_clear(H5F_t *f, H5HG_heap_t *heap, hbool_t destroy)
-{
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT(H5HG_clear);
-
- /* Check arguments */
- assert (heap);
-
- /* Mark heap as clean */
- heap->cache_info.is_dirty = FALSE;
-
- if (destroy)
- if (H5HG_dest(f, heap) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy global heap collection");
-
-done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* H5HG_clear() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5HG_compute_size
- *
- * Purpose: Compute the size in bytes of the specified instance of
- * H5HG_heap_t on disk, and return it in *len_ptr. On failure,
- * the value of *len_ptr is undefined.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: John Mainzer
- * 5/13/04
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HG_compute_size(const H5F_t UNUSED *f, const H5HG_heap_t *heap, size_t *size_ptr)
-{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HG_compute_size);
-
- /* Check arguments */
- HDassert(heap);
- HDassert(size_ptr);
-
- *size_ptr = heap->size;
-
- FUNC_LEAVE_NOAPI(SUCCEED);
-} /* H5HG_compute_size() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5HG_alloc
*
* Purpose: Given a heap with enough free space, this function will split
@@ -721,7 +332,7 @@ H5HG_alloc (H5F_t *f, H5HG_heap_t *heap, size_t size, unsigned * heap_flags_ptr)
/* Reallocate array of objects */
if (NULL==(new_obj = H5FL_SEQ_REALLOC (H5HG_obj_t, heap->obj, new_alloc)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, 0, "memory allocation failed");
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "memory allocation failed")
/* Update heap information */
heap->nalloc=new_alloc;
@@ -810,75 +421,60 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5HG_extend (H5F_t *f, H5HG_heap_t *heap, size_t size, unsigned * heap_flags_ptr)
+H5HG_extend(H5F_t *f, H5HG_heap_t *heap, size_t need, unsigned *heap_flags_ptr)
{
- size_t need; /* Actual space needed to store object */
size_t old_size; /* Previous size of the heap's chunk */
- uint8_t *new_chunk=NULL; /* Pointer to new chunk information */
+ uint8_t *new_chunk = NULL; /* Pointer to new chunk information */
uint8_t *p = NULL; /* Pointer to raw heap info */
unsigned u; /* Local index variable */
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5HG_extend);
+ FUNC_ENTER_NOAPI_NOINIT(H5HG_extend)
/* Check args */
- assert (f);
- assert (heap);
- assert (heap_flags_ptr);
-
- /* Compute total space need to add to this heap */
- need = H5HG_SIZEOF_OBJHDR(f) + H5HG_ALIGN(size);
-
- /* Decrement the amount needed in the heap by the amount of free space available */
- assert(need>heap->obj[0].size);
- need -= heap->obj[0].size;
-
- /* Don't do anything less than double the size of the heap */
- need = MAX(heap->size,need);
-
- /* Extend the space allocated for this heap on disk */
- if(H5MF_extend(f,H5FD_MEM_GHEAP,heap->addr,(hsize_t)heap->size,(hsize_t)need)<0)
- HGOTO_ERROR (H5E_HEAP, H5E_NOSPACE, FAIL, "can't extend heap on disk");
+ HDassert(f);
+ HDassert(heap);
+ HDassert(heap_flags_ptr);
/* Re-allocate the heap information in memory */
- if (NULL==(new_chunk = H5FL_BLK_REALLOC (heap_chunk, heap->chunk, heap->size+need)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "new heap allocation failed");
+ if(NULL == (new_chunk = H5FL_BLK_REALLOC(gheap_chunk, heap->chunk, (heap->size + need))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "new heap allocation failed")
#ifdef H5_CLEAR_MEMORY
HDmemset(new_chunk + heap->size, 0, need);
#endif /* H5_CLEAR_MEMORY */
/* Adjust the size of the heap */
- old_size=heap->size;
- heap->size+=need;
+ old_size = heap->size;
+ heap->size += need;
/* Encode the new size of the heap */
- p = new_chunk + H5HG_SIZEOF_MAGIC + 1 /* version */ + 3 /* reserved */;
- H5F_ENCODE_LENGTH (f, p, heap->size);
+ p = new_chunk + H5_SIZEOF_MAGIC + 1 /* version */ + 3 /* reserved */;
+ H5F_ENCODE_LENGTH(f, p, heap->size);
/* Move the pointers to the existing objects to their new locations */
- for (u=0; u<heap->nused; u++)
+ for(u = 0; u < heap->nused; u++)
if(heap->obj[u].begin)
heap->obj[u].begin = new_chunk + (heap->obj[u].begin - heap->chunk);
/* Update the heap chunk pointer now */
- heap->chunk=new_chunk;
+ heap->chunk = new_chunk;
/* Update the free space information for the heap */
- heap->obj[0].size+=need;
- if(heap->obj[0].begin==NULL)
- heap->obj[0].begin=heap->chunk+old_size;
+ heap->obj[0].size += need;
+ if(heap->obj[0].begin == NULL)
+ heap->obj[0].begin = heap->chunk+old_size;
p = heap->obj[0].begin;
UINT16ENCODE(p, 0); /*id*/
UINT16ENCODE(p, 0); /*nrefs*/
UINT32ENCODE(p, 0); /*reserved*/
- H5F_ENCODE_LENGTH (f, p, heap->obj[0].size);
+ H5F_ENCODE_LENGTH(f, p, heap->obj[0].size);
assert(H5HG_ISALIGNED(heap->obj[0].size));
/* Mark the heap as dirty */
*heap_flags_ptr |= H5AC__DIRTIED_FLAG;
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HG_extend() */
@@ -929,26 +525,26 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5HG_insert (H5F_t *f, hid_t dxpl_id, size_t size, void *obj, H5HG_t *hobj/*out*/)
+H5HG_insert(H5F_t *f, hid_t dxpl_id, size_t size, void *obj, H5HG_t *hobj/*out*/)
{
size_t need; /*total space needed for object */
- int cwfsno;
+ int cwfsno;
size_t idx;
haddr_t addr = HADDR_UNDEF;
H5HG_heap_t *heap = NULL;
unsigned heap_flags = H5AC__NO_FLAGS_SET;
- hbool_t found=0; /* Flag to indicate a heap with enough space was found */
- herr_t ret_value=SUCCEED; /* Return value */
+ hbool_t found = FALSE; /* Flag to indicate a heap with enough space was found */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5HG_insert, FAIL);
+ FUNC_ENTER_NOAPI(H5HG_insert, FAIL)
/* Check args */
- assert (f);
- assert (0==size || obj);
- assert (hobj);
+ HDassert(f);
+ HDassert(0 == size || obj);
+ HDassert(hobj);
- if (0==(f->intent & H5F_ACC_RDWR))
- HGOTO_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file");
+ if(0 == (f->intent & H5F_ACC_RDWR))
+ HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file")
/* Find a large enough collection on the CWFS list */
need = H5HG_SIZEOF_OBJHDR(f) + H5HG_ALIGN(size);
@@ -977,20 +573,18 @@ H5HG_insert (H5F_t *f, hid_t dxpl_id, size_t size, void *obj, H5HG_t *hobj/*out*
* take any of it as gospel.
* JRM - 5/24/04
*/
-
- for (cwfsno=0; cwfsno<f->shared->ncwfs; cwfsno++) {
- if (f->shared->cwfs[cwfsno]->obj[0].size>=need) {
+ for(cwfsno = 0; cwfsno < f->shared->ncwfs; cwfsno++)
+ if(f->shared->cwfs[cwfsno]->obj[0].size >= need) {
addr = f->shared->cwfs[cwfsno]->addr;
- found=1;
+ found = TRUE;
break;
} /* end if */
- } /* end for */
/*
* If we didn't find any collection with enough free space the check if
* we can extend any of the collections to make enough room.
*/
- if (!found) {
+ if(!found) {
size_t new_need;
for (cwfsno=0; cwfsno<f->shared->ncwfs; cwfsno++) {
@@ -998,12 +592,19 @@ H5HG_insert (H5F_t *f, hid_t dxpl_id, size_t size, void *obj, H5HG_t *hobj/*out*
new_need -= f->shared->cwfs[cwfsno]->obj[0].size;
new_need = MAX(f->shared->cwfs[cwfsno]->size, new_need);
- if((f->shared->cwfs[cwfsno]->size+new_need)<=H5HG_MAXSIZE && H5MF_can_extend(f,H5FD_MEM_GHEAP,f->shared->cwfs[cwfsno]->addr,(hsize_t)f->shared->cwfs[cwfsno]->size,(hsize_t)new_need)) {
- if(H5HG_extend(f,f->shared->cwfs[cwfsno],size, &heap_flags)<0)
- HGOTO_ERROR (H5E_HEAP, H5E_CANTINIT, FAIL, "unable to extend global heap collection");
- addr = f->shared->cwfs[cwfsno]->addr;
- found=1;
- break;
+ if((f->shared->cwfs[cwfsno]->size + new_need) <= H5HG_MAXSIZE) {
+ htri_t extended; /* Whether the heap was extended */
+
+ extended = H5MF_try_extend(f, dxpl_id, H5FD_MEM_GHEAP, f->shared->cwfs[cwfsno]->addr, (hsize_t)f->shared->cwfs[cwfsno]->size, (hsize_t)new_need);
+ if(extended < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, FAIL, "error trying to extend heap")
+ else if(extended == TRUE) {
+ if(H5HG_extend(f, f->shared->cwfs[cwfsno], new_need, &heap_flags) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to extend global heap collection")
+ addr = f->shared->cwfs[cwfsno]->addr;
+ found = TRUE;
+ break;
+ } /* end if */
} /* end if */
} /* end for */
} /* end if */
@@ -1012,43 +613,40 @@ H5HG_insert (H5F_t *f, hid_t dxpl_id, size_t size, void *obj, H5HG_t *hobj/*out*
* If we didn't find any collection with enough free space then allocate a
* new collection large enough for the message plus the collection header.
*/
- if (!found) {
-
+ if(!found) {
addr = H5HG_create(f, dxpl_id, need+H5HG_SIZEOF_HDR (f));
- if ( ! H5F_addr_defined(addr) )
- HGOTO_ERROR (H5E_HEAP, H5E_CANTINIT, FAIL, \
- "unable to allocate a global heap collection");
+ if(!H5F_addr_defined(addr))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to allocate a global heap collection")
cwfsno = 0;
} /* end if */
else {
-
/* Move the collection forward in the CWFS list, if it's not
* already at the front
*/
- if (cwfsno>0) {
+ if(cwfsno > 0) {
H5HG_heap_t *tmp = f->shared->cwfs[cwfsno];
- f->shared->cwfs[cwfsno] = f->shared->cwfs[cwfsno-1];
- f->shared->cwfs[cwfsno-1] = tmp;
+
+ f->shared->cwfs[cwfsno] = f->shared->cwfs[cwfsno - 1];
+ f->shared->cwfs[cwfsno - 1] = tmp;
--cwfsno;
} /* end if */
} /* end else */
HDassert(H5F_addr_defined(addr));
-
- if ( NULL == (heap = H5AC_protect(f, dxpl_id, H5AC_GHEAP, addr, NULL, NULL, H5AC_WRITE)) )
- HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap");
+ if(NULL == (heap = (H5HG_heap_t *)H5AC_protect(f, dxpl_id, H5AC_GHEAP, addr, NULL, NULL, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap")
/* Split the free space to make room for the new object */
- idx = H5HG_alloc (f, heap, size, &heap_flags);
+ idx = H5HG_alloc(f, heap, size, &heap_flags);
/* Copy data into the heap */
- if(size>0) {
- HDmemcpy(heap->obj[idx].begin+H5HG_SIZEOF_OBJHDR(f), obj, size);
+ if(size > 0) {
+ HDmemcpy(heap->obj[idx].begin + H5HG_SIZEOF_OBJHDR(f), obj, size);
#ifdef OLD_WAY
/* Don't bother zeroing out the rest of the info in the heap -QAK */
- HDmemset(heap->obj[idx].begin+H5HG_SIZEOF_OBJHDR(f)+size, 0,
- need-(H5HG_SIZEOF_OBJHDR(f)+size));
+ HDmemset(heap->obj[idx].begin + H5HG_SIZEOF_OBJHDR(f) + size, 0,
+ need - (H5HG_SIZEOF_OBJHDR(f) + size));
#endif /* OLD_WAY */
} /* end if */
heap_flags |= H5AC__DIRTIED_FLAG;
@@ -1058,10 +656,10 @@ H5HG_insert (H5F_t *f, hid_t dxpl_id, size_t size, void *obj, H5HG_t *hobj/*out*
hobj->idx = idx;
done:
- if ( heap && H5AC_unprotect(f, dxpl_id, H5AC_GHEAP, heap->addr, heap, heap_flags) < 0 )
- HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to unprotect heap.");
+ if(heap && H5AC_unprotect(f, dxpl_id, H5AC_GHEAP, heap->addr, heap, heap_flags) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to unprotect heap.")
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* H5HG_insert() */
@@ -1105,7 +703,7 @@ H5HG_read(H5F_t *f, hid_t dxpl_id, H5HG_t *hobj, void *object/*out*/,
HDassert(hobj);
/* Load the heap */
- if(NULL == (heap = H5AC_protect(f, dxpl_id, H5AC_GHEAP, hobj->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (heap = (H5HG_heap_t *)H5AC_protect(f, dxpl_id, H5AC_GHEAP, hobj->addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unable to load heap")
HDassert(hobj->idx < heap->nused);
@@ -1187,19 +785,19 @@ H5HG_link (H5F_t *f, hid_t dxpl_id, const H5HG_t *hobj, int adjust)
assert (f);
assert (hobj);
if (0==(f->intent & H5F_ACC_RDWR))
- HGOTO_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file");
+ HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file")
if(adjust!=0) {
/* Load the heap */
- if (NULL == (heap = H5AC_protect(f, dxpl_id, H5AC_GHEAP, hobj->addr, NULL, NULL, H5AC_WRITE)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap");
+ if (NULL == (heap = (H5HG_heap_t *)H5AC_protect(f, dxpl_id, H5AC_GHEAP, hobj->addr, NULL, NULL, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap")
assert (hobj->idx<heap->nused);
assert (heap->obj[hobj->idx].begin);
if (heap->obj[hobj->idx].nrefs+adjust<0)
- HGOTO_ERROR (H5E_HEAP, H5E_BADRANGE, FAIL, "new link count would be out of range");
+ HGOTO_ERROR (H5E_HEAP, H5E_BADRANGE, FAIL, "new link count would be out of range")
if (heap->obj[hobj->idx].nrefs+adjust>H5HG_MAXLINK)
- HGOTO_ERROR (H5E_HEAP, H5E_BADVALUE, FAIL, "new link count would be out of range");
+ HGOTO_ERROR (H5E_HEAP, H5E_BADVALUE, FAIL, "new link count would be out of range")
heap->obj[hobj->idx].nrefs += adjust;
heap_flags |= H5AC__DIRTIED_FLAG;
} /* end if */
@@ -1209,7 +807,7 @@ H5HG_link (H5F_t *f, hid_t dxpl_id, const H5HG_t *hobj, int adjust)
done:
if (heap && H5AC_unprotect(f, dxpl_id, H5AC_GHEAP, hobj->addr, heap, heap_flags)<0)
- HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release object header");
+ HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value);
}
@@ -1237,88 +835,88 @@ done:
herr_t
H5HG_remove (H5F_t *f, hid_t dxpl_id, H5HG_t *hobj)
{
- uint8_t *p=NULL, *obj_start=NULL;
H5HG_heap_t *heap = NULL;
+ uint8_t *p = NULL, *obj_start = NULL;
size_t need;
- int i;
unsigned u;
- unsigned flags=H5AC__NO_FLAGS_SET;/* Whether the heap gets deleted */
- herr_t ret_value=SUCCEED; /* Return value */
+ unsigned flags = H5AC__NO_FLAGS_SET;/* Whether the heap gets deleted */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5HG_remove, FAIL);
/* Check args */
- assert (f);
- assert (hobj);
- if (0==(f->intent & H5F_ACC_RDWR))
- HGOTO_ERROR (H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file");
+ HDassert(f);
+ HDassert(hobj);
+ if(0 == (f->intent & H5F_ACC_RDWR))
+ HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "no write intent on file")
/* Load the heap */
- if (NULL == (heap = H5AC_protect(f, dxpl_id, H5AC_GHEAP, hobj->addr, NULL, NULL, H5AC_WRITE)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap");
+ if(NULL == (heap = (H5HG_heap_t *)H5AC_protect(f, dxpl_id, H5AC_GHEAP, hobj->addr, NULL, NULL, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap")
- assert (hobj->idx<heap->nused);
- assert (heap->obj[hobj->idx].begin);
+ HDassert(hobj->idx < heap->nused);
+ HDassert(heap->obj[hobj->idx].begin);
obj_start = heap->obj[hobj->idx].begin;
/* Include object header size */
- need = H5HG_ALIGN(heap->obj[hobj->idx].size)+H5HG_SIZEOF_OBJHDR(f);
+ need = H5HG_ALIGN(heap->obj[hobj->idx].size) + H5HG_SIZEOF_OBJHDR(f);
/* Move the new free space to the end of the heap */
- for (u=0; u<heap->nused; u++) {
- if (heap->obj[u].begin > heap->obj[hobj->idx].begin)
+ for(u = 0; u < heap->nused; u++)
+ if(heap->obj[u].begin > heap->obj[hobj->idx].begin)
heap->obj[u].begin -= need;
- }
- if (NULL==heap->obj[0].begin) {
- heap->obj[0].begin = heap->chunk + (heap->size-need);
+ if(NULL == heap->obj[0].begin) {
+ heap->obj[0].begin = heap->chunk + (heap->size - need);
heap->obj[0].size = need;
heap->obj[0].nrefs = 0;
- } else {
+ } /* end if */
+ else
heap->obj[0].size += need;
- }
- HDmemmove (obj_start, obj_start+need,
- heap->size-((obj_start+need)-heap->chunk));
- if (heap->obj[0].size>=H5HG_SIZEOF_OBJHDR (f)) {
+ HDmemmove(obj_start, obj_start + need,
+ heap->size - ((obj_start + need) - heap->chunk));
+ if(heap->obj[0].size >= H5HG_SIZEOF_OBJHDR(f)) {
p = heap->obj[0].begin;
UINT16ENCODE(p, 0); /*id*/
UINT16ENCODE(p, 0); /*nrefs*/
UINT32ENCODE(p, 0); /*reserved*/
H5F_ENCODE_LENGTH (f, p, heap->obj[0].size);
- }
- HDmemset (heap->obj+hobj->idx, 0, sizeof(H5HG_obj_t));
+ } /* end if */
+ HDmemset(heap->obj + hobj->idx, 0, sizeof(H5HG_obj_t));
flags |= H5AC__DIRTIED_FLAG;
- if (heap->obj[0].size+H5HG_SIZEOF_HDR(f)==heap->size) {
+ if((heap->obj[0].size + H5HG_SIZEOF_HDR(f)) == heap->size) {
/*
* The collection is empty. Remove it from the CWFS list and return it
* to the file free list.
*/
- H5_CHECK_OVERFLOW(heap->size,size_t,hsize_t);
- H5MF_xfree(f, H5FD_MEM_GHEAP, dxpl_id, heap->addr, (hsize_t)heap->size);
- flags |= H5C__DELETED_FLAG; /* Indicate that the object was deleted, for the unprotect call */
- } else {
+ H5_CHECK_OVERFLOW(heap->size, size_t, hsize_t);
+ flags |= H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG; /* Indicate that the object was deleted, for the unprotect call */
+ } /* end if */
+ else {
+ int i; /* Local index variable */
+
/*
* If the heap is in the CWFS list then advance it one position. The
* H5AC_protect() might have done that too, but that's okay. If the
* heap isn't on the CWFS list then add it to the end.
*/
- for (i=0; i<f->shared->ncwfs; i++) {
- if (f->shared->cwfs[i]==heap) {
- if (i) {
- f->shared->cwfs[i] = f->shared->cwfs[i-1];
- f->shared->cwfs[i-1] = heap;
- }
+ for(i = 0; i < f->shared->ncwfs; i++)
+ if(f->shared->cwfs[i] == heap) {
+ if(i) {
+ f->shared->cwfs[i] = f->shared->cwfs[i - 1];
+ f->shared->cwfs[i - 1] = heap;
+ } /* end if */
break;
- }
- }
- if (i>=f->shared->ncwfs) {
- f->shared->ncwfs = MIN (f->shared->ncwfs+1, H5HG_NCWFS);
- f->shared->cwfs[f->shared->ncwfs-1] = heap;
- }
- }
+ } /* end if */
+ if(i >= f->shared->ncwfs) {
+ f->shared->ncwfs = MIN(f->shared->ncwfs + 1, H5HG_NCWFS);
+ f->shared->cwfs[f->shared->ncwfs - 1] = heap;
+ } /* end if */
+ } /* end else */
done:
- if (heap && H5AC_unprotect(f, dxpl_id, H5AC_GHEAP, hobj->addr, heap, flags) != SUCCEED)
- HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release object header");
+ if(heap && H5AC_unprotect(f, dxpl_id, H5AC_GHEAP, hobj->addr, heap, flags) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value);
-}
+} /* end H5HG_remove() */
+
diff --git a/src/H5HGcache.c b/src/H5HGcache.c
new file mode 100644
index 0000000..1a9e92c
--- /dev/null
+++ b/src/H5HGcache.c
@@ -0,0 +1,442 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5HGcache.c
+ * Feb 5 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: Implement global heap metadata cache methods.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5F_PACKAGE /*suppress error about including H5Fpkg */
+#define H5HG_PACKAGE /*suppress error about including H5HGpkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fpkg.h" /* File access */
+#include "H5HGpkg.h" /* Global heaps */
+#include "H5MFprivate.h" /* File memory management */
+#include "H5MMprivate.h" /* Memory management */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+/* Metadata cache callbacks */
+static H5HG_heap_t *H5HG_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1,
+ void *udata2);
+static herr_t H5HG_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr,
+ H5HG_heap_t *heap, unsigned UNUSED * flags_ptr);
+static herr_t H5HG_clear(H5F_t *f, H5HG_heap_t *heap, hbool_t destroy);
+static herr_t H5HG_size(const H5F_t *f, const H5HG_heap_t *heap, size_t *size_ptr);
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* H5HG inherits cache-like properties from H5AC */
+const H5AC_class_t H5AC_GHEAP[1] = {{
+ H5AC_GHEAP_ID,
+ (H5AC_load_func_t)H5HG_load,
+ (H5AC_flush_func_t)H5HG_flush,
+ (H5AC_dest_func_t)H5HG_dest,
+ (H5AC_clear_func_t)H5HG_clear,
+ (H5AC_size_func_t)H5HG_size,
+}};
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HG_load
+ *
+ * Purpose: Loads a global heap collection from disk.
+ *
+ * Return: Success: Ptr to a global heap collection.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Friday, March 27, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5HG_heap_t *
+H5HG_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * udata1,
+ void UNUSED * udata2)
+{
+ H5HG_heap_t *heap = NULL;
+ uint8_t *p = NULL;
+ size_t nalloc, need;
+ size_t max_idx = 0; /* The maximum index seen */
+ H5HG_heap_t *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5HG_load, NULL)
+
+ /* check arguments */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(!udata1);
+ HDassert(!udata2);
+
+ /* Read the initial 4k page */
+ if(NULL == (heap = H5FL_CALLOC(H5HG_heap_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ heap->addr = addr;
+ if(NULL == (heap->chunk = H5FL_BLK_MALLOC(gheap_chunk, (size_t)H5HG_MINSIZE)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ if(H5F_block_read(f, H5FD_MEM_GHEAP, addr, (size_t)H5HG_MINSIZE, dxpl_id, heap->chunk) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read global heap collection")
+
+ /* Magic number */
+ if(HDmemcmp(heap->chunk, H5HG_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad global heap collection signature")
+ p = heap->chunk + H5_SIZEOF_MAGIC;
+
+ /* Version */
+ if(H5HG_VERSION != *p++)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong version number in global heap")
+
+ /* Reserved */
+ p += 3;
+
+ /* Size */
+ H5F_DECODE_LENGTH(f, p, heap->size);
+ HDassert(heap->size >= H5HG_MINSIZE);
+
+ /*
+ * If we didn't read enough in the first try, then read the rest of the
+ * collection now.
+ */
+ if(heap->size > H5HG_MINSIZE) {
+ haddr_t next_addr = addr + (hsize_t)H5HG_MINSIZE;
+
+ if(NULL == (heap->chunk = H5FL_BLK_REALLOC(gheap_chunk, heap->chunk, heap->size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ if(H5F_block_read(f, H5FD_MEM_GHEAP, next_addr, (heap->size - H5HG_MINSIZE), dxpl_id, heap->chunk + H5HG_MINSIZE) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read global heap collection")
+ } /* end if */
+
+ /* Decode each object */
+ p = heap->chunk + H5HG_SIZEOF_HDR(f);
+ nalloc = H5HG_NOBJS(f, heap->size);
+ if(NULL == (heap->obj = H5FL_SEQ_MALLOC(H5HG_obj_t, nalloc)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ heap->obj[0].size = heap->obj[0].nrefs = 0;
+ heap->obj[0].begin = NULL;
+
+ heap->nalloc = nalloc;
+ while(p < (heap->chunk + heap->size)) {
+ if((p + H5HG_SIZEOF_OBJHDR(f)) > (heap->chunk + heap->size)) {
+ /*
+ * The last bit of space is too tiny for an object header, so we
+ * assume that it's free space.
+ */
+ HDassert(NULL == heap->obj[0].begin);
+ heap->obj[0].size = (heap->chunk + heap->size) - p;
+ heap->obj[0].begin = p;
+ p += heap->obj[0].size;
+ } /* end if */
+ else {
+ unsigned idx;
+ uint8_t *begin = p;
+
+ UINT16DECODE(p, idx);
+
+ /* Check if we need more room to store heap objects */
+ if(idx >= heap->nalloc) {
+ size_t new_alloc; /* New allocation number */
+ H5HG_obj_t *new_obj; /* New array of object descriptions */
+
+ /* Determine the new number of objects to index */
+ new_alloc = MAX(heap->nalloc * 2, (idx + 1));
+
+ /* Reallocate array of objects */
+ if(NULL == (new_obj = H5FL_SEQ_REALLOC(H5HG_obj_t, heap->obj, new_alloc)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+
+ /* Update heap information */
+ heap->nalloc = new_alloc;
+ heap->obj = new_obj;
+ } /* end if */
+
+ UINT16DECODE(p, heap->obj[idx].nrefs);
+ p += 4; /*reserved*/
+ H5F_DECODE_LENGTH(f, p, heap->obj[idx].size);
+ heap->obj[idx].begin = begin;
+
+ /*
+ * The total storage size includes the size of the object header
+ * and is zero padded so the next object header is properly
+ * aligned. The last bit of space is the free space object whose
+ * size is never padded and already includes the object header.
+ */
+ if(idx > 0) {
+ need = H5HG_SIZEOF_OBJHDR(f) + H5HG_ALIGN(heap->obj[idx].size);
+
+ /* Check for "gap" in index numbers (caused by deletions) and fill in heap object values */
+ if(idx > (max_idx + 1))
+ HDmemset(&heap->obj[max_idx + 1], 0, sizeof(H5HG_obj_t) * (idx - (max_idx + 1)));
+ max_idx = idx;
+ } /* end if */
+ else
+ need = heap->obj[idx].size;
+ p = begin + need;
+ } /* end else */
+ } /* end while */
+ HDassert(p == heap->chunk + heap->size);
+ HDassert(H5HG_ISALIGNED(heap->obj[0].size));
+
+ /* Set the next index value to use */
+ if(max_idx > 0)
+ heap->nused = max_idx + 1;
+ else
+ heap->nused = 1;
+
+ /*
+ * Add the new heap to the CWFS list, removing some other entry if
+ * necessary to make room. We remove the right-most entry that has less
+ * free space than this heap.
+ */
+ if(!f->shared->cwfs) {
+ f->shared->cwfs = (H5HG_heap_t **)H5MM_malloc(H5HG_NCWFS * sizeof(H5HG_heap_t *));
+ if(NULL == f->shared->cwfs)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ f->shared->ncwfs = 1;
+ f->shared->cwfs[0] = heap;
+ } else if(H5HG_NCWFS == f->shared->ncwfs) {
+ int i; /* Local index variable */
+
+ for(i = H5HG_NCWFS - 1; i >= 0; --i)
+ if(f->shared->cwfs[i]->obj[0].size < heap->obj[0].size) {
+ HDmemmove(f->shared->cwfs + 1, f->shared->cwfs, i * sizeof(H5HG_heap_t *));
+ f->shared->cwfs[0] = heap;
+ break;
+ } /* end if */
+ } else {
+ HDmemmove(f->shared->cwfs + 1, f->shared->cwfs, f->shared->ncwfs * sizeof(H5HG_heap_t *));
+ f->shared->ncwfs += 1;
+ f->shared->cwfs[0] = heap;
+ } /* end else */
+
+ ret_value = heap;
+
+done:
+ if(!ret_value && heap)
+ if(H5HG_dest(f, heap) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, NULL, "unable to destroy global heap collection")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HG_load() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HG_flush
+ *
+ * Purpose: Flushes a global heap collection from memory to disk if it's
+ * dirty. Optionally deletes teh heap from memory.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * Friday, March 27, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HG_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HG_heap_t *heap, unsigned UNUSED * flags_ptr)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5HG_flush, FAIL)
+
+ /* Check arguments */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(H5F_addr_eq(addr, heap->addr));
+ HDassert(heap);
+
+ if(heap->cache_info.is_dirty) {
+ if(H5F_block_write(f, H5FD_MEM_GHEAP, addr, heap->size, dxpl_id, heap->chunk) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write global heap collection to file")
+ heap->cache_info.is_dirty = FALSE;
+ } /* end if */
+
+ if(destroy)
+ if(H5HG_dest(f, heap) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy global heap collection")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HG_flush() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HG_dest
+ *
+ * Purpose: Destroys a global heap collection in memory
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Wednesday, January 15, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HG_dest(H5F_t *f, H5HG_heap_t *heap)
+{
+ int i; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HG_dest)
+
+ /* Check arguments */
+ HDassert(heap);
+
+ /* Verify that node is clean */
+ HDassert(heap->cache_info.is_dirty == FALSE);
+
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!heap->cache_info.free_file_space_on_destroy || H5F_addr_defined(heap->cache_info.addr));
+
+ /* Check for freeing file space for globalheap */
+ if(heap->cache_info.free_file_space_on_destroy) {
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_GHEAP, H5AC_dxpl_id, heap->cache_info.addr, (hsize_t)heap->size) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free global heap")
+ } /* end if */
+
+ /* Remove heap from NCWFS array, if it's present */
+ for(i = 0; i < f->shared->ncwfs; i++)
+ if(f->shared->cwfs[i] == heap) {
+ f->shared->ncwfs -= 1;
+ HDmemmove(f->shared->cwfs + i, f->shared->cwfs + i + 1, (f->shared->ncwfs - i) * sizeof(H5HG_heap_t *));
+ break;
+ } /* end if */
+
+ /* Release resources */
+ if(heap->chunk)
+ heap->chunk = H5FL_BLK_FREE(gheap_chunk, heap->chunk);
+ if(heap->obj)
+ heap->obj = H5FL_SEQ_FREE(H5HG_obj_t, heap->obj);
+ (void)H5FL_FREE(H5HG_heap_t, heap);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5HG_dest() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HG_clear
+ *
+ * Purpose: Mark a global heap in memory as non-dirty.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, March 20, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HG_clear(H5F_t *f, H5HG_heap_t *heap, hbool_t destroy)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HG_clear)
+
+ /* Check arguments */
+ HDassert(heap);
+
+ /* Mark heap as clean */
+ heap->cache_info.is_dirty = FALSE;
+
+ if(destroy)
+ if(H5HG_dest(f, heap) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy global heap collection")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5HG_clear() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HG_size
+ *
+ * Purpose: Compute the size in bytes of the specified instance of
+ * H5HG_heap_t on disk, and return it in *len_ptr. On failure,
+ * the value of *len_ptr is undefined.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 5/13/04
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HG_size(const H5F_t UNUSED *f, const H5HG_heap_t *heap, size_t *size_ptr)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HG_size)
+
+ /* Check arguments */
+ HDassert(heap);
+ HDassert(size_ptr);
+
+ *size_ptr = heap->size;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5HG_size() */
+
diff --git a/src/H5HGdbg.c b/src/H5HGdbg.c
index 0e5aff8..43c1ed0 100644
--- a/src/H5HGdbg.c
+++ b/src/H5HGdbg.c
@@ -73,7 +73,7 @@ H5HG_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent,
assert(indent >= 0);
assert(fwidth >= 0);
- if (NULL == (h = H5AC_protect(f, dxpl_id, H5AC_GHEAP, addr, NULL, NULL, H5AC_READ)))
+ if (NULL == (h = (H5HG_heap_t *)H5AC_protect(f, dxpl_id, H5AC_GHEAP, addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load global heap collection");
fprintf(stream, "%*sGlobal Heap Collection...\n", indent, "");
diff --git a/src/H5HGpkg.h b/src/H5HGpkg.h
index e814367..96be009 100644
--- a/src/H5HGpkg.h
+++ b/src/H5HGpkg.h
@@ -32,6 +32,9 @@
#include "H5HGprivate.h"
/* Other private headers needed by this file */
+#include "H5ACprivate.h" /* Metadata cache */
+#include "H5FLprivate.h" /* Free lists */
+
/*****************************/
/* Package Private Variables */
@@ -40,11 +43,40 @@
/* The cache subclass */
H5_DLLVAR const H5AC_class_t H5AC_GHEAP[1];
+/* Declare extern the free list to manage the H5HG_t struct */
+H5FL_EXTERN(H5HG_heap_t);
+
+/* Declare extern the free list to manage sequences of H5HG_obj_t's */
+H5FL_SEQ_EXTERN(H5HG_obj_t);
+
+/* Declare extern the PQ free list to manage heap chunks */
+H5FL_BLK_EXTERN(gheap_chunk);
+
+
/**************************/
/* Package Private Macros */
/**************************/
/*
+ * Global heap collection version.
+ */
+#define H5HG_VERSION 1
+
+/*
+ * All global heap collections are at least this big. This allows us to read
+ * most collections with a single read() since we don't have to read a few
+ * bytes of header to figure out the size. If the heap is larger than this
+ * then a second read gets the rest after we've decoded the header.
+ */
+#define H5HG_MINSIZE 4096
+
+/*
+ * Maximum length of the CWFS list, the list of remembered collections that
+ * have free space.
+ */
+#define H5HG_NCWFS 16
+
+/*
* Pad all global heap messages to a multiple of eight bytes so we can load
* the entire collection into memory and operate on it there. Eight should
* be sufficient for machines that have alignment constraints because our
@@ -56,6 +88,16 @@ H5_DLLVAR const H5AC_class_t H5AC_GHEAP[1];
#define H5HG_ISALIGNED(X) ((X)==H5HG_ALIGN(X))
/*
+ * The size of the collection header, always a multiple of the alignment so
+ * that the stuff that follows the header is aligned.
+ */
+#define H5HG_SIZEOF_HDR(f) \
+ H5HG_ALIGN(4 + /*magic number */ \
+ 1 + /*version number */ \
+ 3 + /*reserved */ \
+ H5F_SIZEOF_SIZE(f)) /*collection size */
+
+/*
* The overhead associated with each object in the heap, always a multiple of
* the alignment so that the stuff that follows the header is aligned.
*/
@@ -65,6 +107,17 @@ H5_DLLVAR const H5AC_class_t H5AC_GHEAP[1];
4 + /*reserved */ \
H5F_SIZEOF_SIZE(f)) /*object data size */
+/*
+ * The initial guess for the number of messages in a collection. We assume
+ * that all objects in that collection are zero length, giving the maximum
+ * possible number of objects in the collection. The collection itself has
+ * some overhead and each message has some overhead. The `+2' accounts for
+ * rounding and for the free space object.
+ */
+#define H5HG_NOBJS(f,z) (int)((((z)-H5HG_SIZEOF_HDR(f))/ \
+ H5HG_SIZEOF_OBJHDR(f)+2))
+
+
/****************************/
/* Package Private Typedefs */
/****************************/
@@ -92,6 +145,7 @@ struct H5HG_heap_t {
/******************************/
/* Package Private Prototypes */
/******************************/
+H5_DLL herr_t H5HG_dest(H5F_t *f, H5HG_heap_t *heap);
-#endif
+#endif /* _H5HGpkg_H */
diff --git a/src/H5HGprivate.h b/src/H5HGprivate.h
index 6e2c492..b6cdb4a 100644
--- a/src/H5HGprivate.h
+++ b/src/H5HGprivate.h
@@ -26,12 +26,6 @@
/* Private headers needed by this file. */
#include "H5Fprivate.h" /* File access */
-/*
- * Each collection has a magic number for some redundancy.
- */
-#define H5HG_MAGIC "GCOL"
-#define H5HG_SIZEOF_MAGIC 4
-
/* Information to locate object in global heap */
typedef struct H5HG_t {
haddr_t addr; /*address of collection */
diff --git a/src/H5HL.c b/src/H5HL.c
index c861978..a69eb16 100644
--- a/src/H5HL.c
+++ b/src/H5HL.c
@@ -22,69 +22,75 @@
* Purpose: Heap functions for the local heaps used by symbol
* tables to store names (among other things).
*
- * Modifications:
- *
- * Robb Matzke, 5 Aug 1997
- * Added calls to H5E.
- *
*-------------------------------------------------------------------------
*/
+
+/****************/
+/* Module Setup */
+/****************/
+
#define H5F_PACKAGE /* Suppress error about including H5Fpkg */
#define H5HL_PACKAGE /* Suppress error about including H5HLpkg */
+/***********/
+/* Headers */
+/***********/
#include "H5private.h" /* Generic Functions */
-#include "H5ACprivate.h" /* Metadata cache */
#include "H5Eprivate.h" /* Error handling */
#include "H5Fpkg.h" /* File access */
-#include "H5FLprivate.h" /* Free lists */
#include "H5HLpkg.h" /* Local Heaps */
#include "H5MFprivate.h" /* File memory management */
-/* Private macros */
-#define H5HL_FREE_NULL 1 /*end of free list on disk */
+
+/****************/
+/* Local Macros */
+/****************/
+
#define H5HL_MIN_HEAP 128 /* Minimum size to reduce heap buffer to */
-/*
- * Local heap collection version.
- */
-#define H5HL_VERSION 0
-/* Private typedefs */
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
-/* PRIVATE PROTOTYPES */
-static herr_t H5HL_serialize(H5F_t *f, H5HL_t *heap, uint8_t *buf);
static H5HL_free_t *H5HL_remove_free(H5HL_t *heap, H5HL_free_t *fl);
static herr_t H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap);
-/* Metadata cache callbacks */
-static H5HL_t *H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1,
- void *udata2);
-static herr_t H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, H5HL_t *heap, unsigned UNUSED * flags_ptr);
-static herr_t H5HL_dest(H5F_t *f, H5HL_t *heap);
-static herr_t H5HL_clear(H5F_t *f, H5HL_t *heap, hbool_t destroy);
-static herr_t H5HL_size(const H5F_t *f, const H5HL_t *heap, size_t *size_ptr);
-/*
- * H5HL inherits cache-like properties from H5AC
- */
-const H5AC_class_t H5AC_LHEAP[1] = {{
- H5AC_LHEAP_ID,
- (H5AC_load_func_t)H5HL_load,
- (H5AC_flush_func_t)H5HL_flush,
- (H5AC_dest_func_t)H5HL_dest,
- (H5AC_clear_func_t)H5HL_clear,
- (H5AC_size_func_t)H5HL_size,
-}};
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
/* Declare a free list to manage the H5HL_free_t struct */
-H5FL_DEFINE_STATIC(H5HL_free_t);
+H5FL_DEFINE(H5HL_free_t);
/* Declare a free list to manage the H5HL_t struct */
-H5FL_DEFINE_STATIC(H5HL_t);
+H5FL_DEFINE(H5HL_t);
/* Declare a PQ free list to manage the heap chunk information */
-H5FL_BLK_DEFINE_STATIC(heap_chunk);
+H5FL_BLK_DEFINE(lheap_chunk);
+
/*-------------------------------------------------------------------------
@@ -106,15 +112,6 @@ H5FL_BLK_DEFINE_STATIC(heap_chunk);
* matzke@llnl.gov
* Jul 16 1997
*
- * Modifications:
- *
- * Robb Matzke, 5 Aug 1997
- * Takes a flag that determines the type of heap that is
- * created.
- *
- * John Mainzer, 6/7/05
- * Removed code modifying the is_dirty field of the cache info.
- *
*-------------------------------------------------------------------------
*/
herr_t
@@ -125,175 +122,58 @@ H5HL_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, haddr_t *addr_p/*out*/)
size_t sizeof_hdr; /* Cache H5HL header size for file */
herr_t ret_value = SUCCEED;
- FUNC_ENTER_NOAPI(H5HL_create, FAIL);
+ FUNC_ENTER_NOAPI(H5HL_create, FAIL)
/* check arguments */
- assert(f);
- assert(addr_p);
+ HDassert(f);
+ HDassert(addr_p);
- if (size_hint && size_hint < H5HL_SIZEOF_FREE(f))
+ if(size_hint && size_hint < H5HL_SIZEOF_FREE(f))
size_hint = H5HL_SIZEOF_FREE(f);
size_hint = H5HL_ALIGN(size_hint);
/* Cache this for later */
- sizeof_hdr= H5HL_SIZEOF_HDR(f);
+ sizeof_hdr = H5HL_SIZEOF_HDR(f);
/* allocate file version */
total_size = sizeof_hdr + size_hint;
- if (HADDR_UNDEF==(*addr_p=H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, total_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate file memory");
+ if(HADDR_UNDEF == (*addr_p = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, total_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate file memory")
/* allocate memory version */
- if (NULL==(heap = H5FL_CALLOC(H5HL_t)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
+ if(NULL == (heap = H5FL_CALLOC(H5HL_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
heap->addr = *addr_p + (hsize_t)sizeof_hdr;
heap->heap_alloc = size_hint;
- if (NULL==(heap->chunk = H5FL_BLK_CALLOC(heap_chunk,(sizeof_hdr + size_hint))))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
+ if(NULL == (heap->chunk = H5FL_BLK_CALLOC(lheap_chunk, (sizeof_hdr + size_hint))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
/* free list */
- if (size_hint) {
- if (NULL==(heap->freelist = H5FL_MALLOC(H5HL_free_t)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
+ if(size_hint) {
+ if(NULL == (heap->freelist = H5FL_MALLOC(H5HL_free_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
heap->freelist->offset = 0;
heap->freelist->size = size_hint;
heap->freelist->prev = heap->freelist->next = NULL;
- } else {
+ } /* end if */
+ else
heap->freelist = NULL;
- }
/* add to cache */
- if (H5AC_set(f, dxpl_id, H5AC_LHEAP, *addr_p, heap, H5AC__NO_FLAGS_SET) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to cache heap");
+ if(H5AC_set(f, dxpl_id, H5AC_LHEAP, *addr_p, heap, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to cache heap")
done:
- if (ret_value<0) {
- if (H5F_addr_defined(*addr_p))
+ if(ret_value < 0) {
+ if(H5F_addr_defined(*addr_p))
H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, *addr_p, total_size);
- if (heap) {
- if(H5HL_dest(f,heap)<0)
- HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap collection");
- }
- }
- FUNC_LEAVE_NOAPI(ret_value);
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5HL_load
- *
- * Purpose: Loads a heap from disk.
- *
- * Return: Success: Ptr to a local heap memory data structure.
- *
- * Failure: NULL
- *
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Jul 17 1997
- *
- * Modifications:
- * Robb Matzke, 1999-07-28
- * The ADDR argument is passed by value.
- *
- * Quincey Koziol, 2002-7-180
- * Added dxpl parameter to allow more control over I/O from metadata
- * cache.
- *-------------------------------------------------------------------------
- */
-static H5HL_t *
-H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * udata1,
- void UNUSED * udata2)
-{
- uint8_t hdr[52];
- size_t sizeof_hdr; /* Cache H5HL header size for file */
- const uint8_t *p = NULL;
- H5HL_t *heap = NULL;
- H5HL_free_t *fl = NULL, *tail = NULL;
- size_t free_block = H5HL_FREE_NULL;
- H5HL_t *ret_value;
-
- FUNC_ENTER_NOAPI(H5HL_load, NULL);
-
- /* check arguments */
- assert(f);
- assert(H5F_addr_defined(addr));
- assert(!udata1);
- assert(!udata2);
-
- /* Cache this for later */
- sizeof_hdr= H5HL_SIZEOF_HDR(f);
- assert(sizeof_hdr <= sizeof(hdr));
-
- /* Get the local heap's header */
- if (H5F_block_read(f, H5FD_MEM_LHEAP, addr, sizeof_hdr, dxpl_id, hdr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read heap header");
- p = hdr;
-
- /* Check magic number */
- if(HDmemcmp(hdr, H5HL_MAGIC, (size_t)H5HL_SIZEOF_MAGIC))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap signature");
- p += H5HL_SIZEOF_MAGIC;
-
- /* Version */
- if (H5HL_VERSION!=*p++)
- HGOTO_ERROR (H5E_HEAP, H5E_CANTLOAD, NULL, "wrong version number in global heap");
-
- /* Reserved */
- p += 3;
-
- /* Allocate space in memory for the heap */
- if (NULL==(heap = H5FL_CALLOC(H5HL_t)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
-
- /* heap data size */
- H5F_DECODE_LENGTH(f, p, heap->heap_alloc);
-
- /* free list head */
- H5F_DECODE_LENGTH(f, p, free_block);
- if (free_block != H5HL_FREE_NULL && free_block >= heap->heap_alloc)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list");
-
- /* data */
- H5F_addr_decode(f, &p, &(heap->addr));
- if (NULL==(heap->chunk = H5FL_BLK_CALLOC(heap_chunk,(sizeof_hdr + heap->heap_alloc))))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
- if (heap->heap_alloc &&
- H5F_block_read(f, H5FD_MEM_LHEAP, heap->addr, heap->heap_alloc, dxpl_id, heap->chunk + sizeof_hdr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unable to read heap data");
-
- /* Build free list */
- while (H5HL_FREE_NULL != free_block) {
- if (free_block >= heap->heap_alloc)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list");
- if (NULL==(fl = H5FL_MALLOC(H5HL_free_t)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
- fl->offset = free_block;
- fl->prev = tail;
- fl->next = NULL;
- if (tail) tail->next = fl;
- tail = fl;
- if (!heap->freelist) heap->freelist = fl;
-
- p = heap->chunk + sizeof_hdr + free_block;
- H5F_DECODE_LENGTH(f, p, free_block);
- H5F_DECODE_LENGTH(f, p, fl->size);
-
- if (fl->offset + fl->size > heap->heap_alloc)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list");
- }
-
- /* Set return value */
- ret_value = heap;
-
-done:
- if (!ret_value && heap) {
- if(H5HL_dest(f,heap)<0)
- HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, NULL, "unable to destroy local heap collection");
- }
+ if(heap)
+ if(H5HL_dest(f,heap) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap collection")
+ } /* end if */
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HL_create() */
/*-------------------------------------------------------------------------
@@ -309,22 +189,6 @@ done:
* wendling@ncsa.uiuc.edu
* Sept. 16, 2003
*
- * Modifications:
- *
- * John Mainzer, 8/10/05
- * Reworked this function for a different role.
- *
- * It used to be called during cache eviction, where it
- * attempted to size the disk space allocation for the
- * actual size of the heap. However, this causes problems
- * in the parallel case, as the reuslting disk allocations
- * may not be synchronized.
- *
- * It is now called from H5HL_remove(), where it is used to
- * reduce heap size in response to an entry deletion. This
- * means that the function should either do nothing, or
- * reduce the size of the disk allocation.
- *
*-------------------------------------------------------------------------
*/
static herr_t
@@ -425,15 +289,15 @@ H5HL_minimize_heap_space(H5F_t *f, hid_t dxpl_id, H5HL_t *heap)
HDassert(new_heap_size < heap->heap_alloc);
/* Resize the memory buffer */
- heap->chunk = H5FL_BLK_REALLOC(heap_chunk, heap->chunk, (sizeof_hdr + new_heap_size));
+ heap->chunk = H5FL_BLK_REALLOC(lheap_chunk, heap->chunk, (sizeof_hdr + new_heap_size));
if(!heap->chunk)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Release old space on disk */
/* (Should be safe to free old heap space first, since it's shrinking -QAK) */
H5_CHECK_OVERFLOW(heap->heap_alloc, size_t, hsize_t);
- H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, old_addr, (hsize_t)heap->heap_alloc);
- H5E_clear_stack(NULL); /* don't really care if the free failed */
+ if(H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, old_addr, (hsize_t)heap->heap_alloc) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap")
/* Allocate new space on disk */
H5_CHECK_OVERFLOW(new_heap_size, size_t, hsize_t);
@@ -451,268 +315,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5HL_serialize
- *
- * Purpose: Serialize the heap. This function will eliminate free
- * blocks at the tail of the heap and also split the block
- * if it needs to be split for the file. This is so that we
- * can serialize it correctly.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Bill Wendling
- * wendling@ncsa.uiuc.edu
- * Sept. 16, 2003
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HL_serialize(H5F_t *f, H5HL_t *heap, uint8_t *buf)
-{
- H5HL_free_t *fl;
- uint8_t *p;
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_serialize)
-
- /* check args */
- assert(buf);
- assert(heap);
-
- /* serialize the header */
- p = buf;
- fl = heap->freelist;
- HDmemcpy(p, H5HL_MAGIC, (size_t)H5HL_SIZEOF_MAGIC);
- p += H5HL_SIZEOF_MAGIC;
- *p++ = H5HL_VERSION;
- *p++ = 0; /*reserved*/
- *p++ = 0; /*reserved*/
- *p++ = 0; /*reserved*/
- H5F_ENCODE_LENGTH(f, p, heap->heap_alloc);
- H5F_ENCODE_LENGTH(f, p, fl ? fl->offset : H5HL_FREE_NULL);
- H5F_addr_encode(f, &p, heap->addr);
-
- /* serialize the free list */
- for (; fl; fl = fl->next) {
- assert (fl->offset == H5HL_ALIGN (fl->offset));
- p = heap->chunk + H5HL_SIZEOF_HDR(f) + fl->offset;
-
- if (fl->next) {
- H5F_ENCODE_LENGTH(f, p, fl->next->offset);
- } else {
- H5F_ENCODE_LENGTH(f, p, H5HL_FREE_NULL);
- }
-
- H5F_ENCODE_LENGTH(f, p, fl->size);
- }
-
- FUNC_LEAVE_NOAPI(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5HL_flush
- *
- * Purpose: Flushes a heap from memory to disk if it's dirty. Optionally
- * deletes the heap from memory.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Jul 17 1997
- *
- * Modifications:
- * rky, 1998-08-28
- * Only p0 writes metadata to disk.
- *
- * Robb Matzke, 1999-07-28
- * The ADDR argument is passed by value.
- *
- * Quincey Koziol, 2002-7-180
- * Added dxpl parameter to allow more control over I/O from metadata
- * cache.
- *
- * Bill Wendling, 2003-09-16
- * Separated out the bit that serializes the heap.
- *
- * John Mainzer, 2005-08-10
- * Removed call to H5HL_minimize_heap_space(). It does disk space
- * allocation, which can cause problems if done at flush time.
- * Instead, disk space allocation/deallocation is now done at
- * insert/remove time.
- *
- * John Mainzer, 2006-08-21
- * Added the flags_ptr parameter. This parameter exists to
- * allow the flush routine to report to the cache if the
- * entry is resized or renamed as a result of the flush.
- * *flags_ptr is set to H5C_CALLBACK__NO_FLAGS_SET on entry.
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HL_t *heap, unsigned UNUSED * flags_ptr)
-{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5HL_flush, FAIL);
-
- /* check arguments */
- HDassert( f );
- HDassert( H5F_addr_defined(addr) );
- HDassert( heap );
-
- if (heap->cache_info.is_dirty) {
- haddr_t hdr_end_addr;
- size_t sizeof_hdr = H5HL_SIZEOF_HDR(f); /* cache H5HL header size for file */
-
- /* Write the header */
- if (H5HL_serialize(f, heap, heap->chunk) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTSERIALIZE, FAIL, "unable to serialize local heap")
-
- /* Copy buffer to disk */
- hdr_end_addr = addr + (hsize_t)sizeof_hdr;
-
- if (H5F_addr_eq(heap->addr, hdr_end_addr)) {
- /* The header and data are contiguous */
- if (H5F_block_write(f, H5FD_MEM_LHEAP, addr, (sizeof_hdr + heap->heap_alloc),
- dxpl_id, heap->chunk) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header and data to file")
- } else {
- if (H5F_block_write(f, H5FD_MEM_LHEAP, addr, sizeof_hdr, dxpl_id, heap->chunk) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header to file")
-
- if (H5F_block_write(f, H5FD_MEM_LHEAP, heap->addr, heap->heap_alloc,
- dxpl_id, heap->chunk + sizeof_hdr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap data to file")
- }
-
- heap->cache_info.is_dirty = FALSE;
- }
-
- /* Should we destroy the memory version? */
- if (destroy) {
- if (H5HL_dest(f,heap) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap collection")
- }
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5HL_dest
- *
- * Purpose: Destroys a heap in memory.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Jan 15 2003
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HL_dest(H5F_t UNUSED *f, H5HL_t *heap)
-{
- H5HL_free_t *fl;
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_dest);
-
- /* check arguments */
- assert(heap);
-
- /* Verify that node is clean */
- assert (heap->cache_info.is_dirty==FALSE);
-
- if(heap->chunk)
- heap->chunk = H5FL_BLK_FREE(heap_chunk,heap->chunk);
- while (heap->freelist) {
- fl = heap->freelist;
- heap->freelist = fl->next;
- H5FL_FREE(H5HL_free_t,fl);
- }
- H5FL_FREE(H5HL_t,heap);
-
- FUNC_LEAVE_NOAPI(SUCCEED);
-} /* end H5HL_dest() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5HL_clear
- *
- * Purpose: Mark a local heap in memory as non-dirty.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Mar 20 2003
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HL_clear(H5F_t *f, H5HL_t *heap, hbool_t destroy)
-{
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT(H5HL_clear);
-
- /* check arguments */
- assert(heap);
-
- /* Mark heap as clean */
- heap->cache_info.is_dirty = FALSE;
-
- if (destroy)
- if (H5HL_dest(f, heap) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap collection");
-
-done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5HL_clear() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5HL_size
- *
- * Purpose: Compute the size in bytes of the specified instance of
- * H5HL_t on disk, and return it in *len_ptr. On failure,
- * the value of *len_ptr is undefined.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: John Mainzer
- * 5/13/04
- *
- * Modifications:
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HL_size(const H5F_t *f, const H5HL_t *heap, size_t *size_ptr)
-{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_size);
-
- /* check arguments */
- HDassert(f);
- HDassert(heap);
- HDassert(size_ptr);
-
- *size_ptr = H5HL_SIZEOF_HDR(f) + heap->heap_alloc;
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5HL_size() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5HL_protect
*
* Purpose: This function is a wrapper for the H5AC_protect call. The
@@ -754,7 +356,7 @@ H5HL_protect(H5F_t *f, hid_t dxpl_id, haddr_t addr, H5AC_protect_t rw)
HDassert(f);
HDassert(H5F_addr_defined(addr));
- if(NULL == (ret_value = H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, rw)))
+ if(NULL == (ret_value = (H5HL_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, rw)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unable to load heap")
done:
@@ -775,8 +377,6 @@ done:
* wendling@ncsa.uiuc.edu
* Sept. 17, 2003
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
void *
@@ -787,11 +387,13 @@ H5HL_offset_into(H5F_t *f, const H5HL_t *heap, size_t offset)
* valid heap pointer. So, this can remain "FUNC_ENTER_NOAPI_NOINIT"
*/
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_offset_into)
- assert(f);
- assert(heap);
- assert(offset < heap->heap_alloc);
+
+ HDassert(f);
+ HDassert(heap);
+ HDassert(offset < heap->heap_alloc);
+
FUNC_LEAVE_NOAPI(heap->chunk + H5HL_SIZEOF_HDR(f) + offset)
-}
+} /* end H5HL_offset_into() */
/*-------------------------------------------------------------------------
@@ -840,22 +442,23 @@ done:
* matzke@llnl.gov
* Jul 17 1997
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static H5HL_free_t *
H5HL_remove_free(H5HL_t *heap, H5HL_free_t *fl)
{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_remove_free);
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_remove_free)
- if (fl->prev) fl->prev->next = fl->next;
- if (fl->next) fl->next->prev = fl->prev;
+ if(fl->prev)
+ fl->prev->next = fl->next;
+ if(fl->next)
+ fl->next->prev = fl->prev;
- if (!fl->prev) heap->freelist = fl->next;
+ if(!fl->prev)
+ heap->freelist = fl->next;
- FUNC_LEAVE_NOAPI(H5FL_FREE(H5HL_free_t,fl));
-}
+ FUNC_LEAVE_NOAPI((H5HL_free_t *)H5FL_FREE(H5HL_free_t, fl))
+} /* end H5HL_remove_free() */
/*-------------------------------------------------------------------------
@@ -944,9 +547,9 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t buf_size, const void *
* free chunk. If the heap must expand, we double its size.
*/
if(found == FALSE) {
- size_t need_more; /* How much more space we need */
- size_t new_heap_alloc; /* Final size of space allocated for heap */
- htri_t can_extend; /* Whether the local heap's data segment on disk can be extended */
+ size_t need_more; /* How much more space we need */
+ size_t new_heap_alloc; /* Final size of space allocated for heap */
+ htri_t extended; /* Whether the local heap's data segment on disk was extended */
/* At least double the heap's size, making certain there's enough room
* for the new object */
@@ -963,38 +566,64 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t buf_size, const void *
need_more = need_size;
new_heap_alloc = heap->heap_alloc + need_more;
+#if 0 /* JRM */ /* delete this once we are convinced that the general
+ * fix will do the job.
+ */
+/*
+ * XXX: This is a _total_ hack, a real kludge. :-/ The metadata cache currently
+ * responds very poorly when an object is inserted into the cache (or
+ * resized) that is larger than the current cache size. It waits through
+ * an entire 'epoch' of cache operations to resize the cache larger (getting
+ * _very_ poor performance), instead of immediately accommodating the large
+ * object by increasing the cache size.
+ *
+ * So, what we are doing here is to look at the current cache size, check
+ * if the new local heap will overwhelm the cache and, if so, resize the
+ * cache to be large enough to hold the new local heap block along with
+ * leaving room for other objects in the cache.
+ *
+ * John will be working on a fix inside the cache itself, so this special
+ * case code here can be removed when he's finished. - QAK, 2007/12/21
+ */
+{
+ H5AC_cache_config_t mdc_config;
+
+ /* Retrieve the current cache information */
+ mdc_config.version = H5AC__CURR_CACHE_CONFIG_VERSION;
+ if(H5AC_get_cache_auto_resize_config(f->shared->cache, &mdc_config) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, (size_t)-1, "H5AC_get_cache_auto_resize_config() failed.")
+
+ /* Check if the current cache will get blown out by adding this heap
+ * block and resize it if so.
+ */
+ if((2 * new_heap_alloc) >= mdc_config.initial_size) {
+ mdc_config.set_initial_size = TRUE;
+ mdc_config.initial_size = 2 * new_heap_alloc;
+
+ if(H5AC_set_cache_auto_resize_config(f->shared->cache, &mdc_config) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, (size_t)-1, "H5AC_set_cache_auto_resize_config() failed.")
+ } /* end if */
+}
+#endif /* JRM */
HDassert(heap->heap_alloc < new_heap_alloc);
H5_CHECK_OVERFLOW(heap->heap_alloc, size_t, hsize_t);
H5_CHECK_OVERFLOW(new_heap_alloc, size_t, hsize_t);
- /* Check if current heap is extendible */
- can_extend = H5MF_can_extend(f, H5FD_MEM_LHEAP, heap->addr, (hsize_t)(heap->heap_alloc), (hsize_t)need_more);
- if(can_extend < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "unable to check whether heap can be extended")
+ /* Extend current heap if possible */
+ extended = H5MF_try_extend(f, dxpl_id, H5FD_MEM_LHEAP, heap->addr, (hsize_t)(heap->heap_alloc), (hsize_t)need_more);
+ if(extended < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, (size_t)(-1), "error trying to extend heap")
- /* extend the current heap if we can... */
- if(can_extend == TRUE) {
- if(H5MF_extend(f, H5FD_MEM_LHEAP, heap->addr, (hsize_t)(heap->heap_alloc), (hsize_t)need_more) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "can't extend heap on disk")
- } /* end if */
- else { /* ...if we can't, allocate a new chunk & release the old */
- haddr_t new_addr;
-
- /* The new allocation may fail -- to avoid the possiblity of
- * file corruption, allocate the new heap first, and then
- * deallocate the old.
- */
+ /* If we couldn't extend the heap, release old chunk and allocate a new one */
+ if(extended == FALSE) {
+ /* Release old space on disk */
+ if(H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, heap->addr, (hsize_t)heap->heap_alloc) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, (size_t)(-1), "unable to free local heap")
/* allocate new disk space for the heap */
- if((new_addr = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, (hsize_t)new_heap_alloc)) == HADDR_UNDEF)
+ if((heap->addr = H5MF_alloc(f, H5FD_MEM_LHEAP, dxpl_id, (hsize_t)new_heap_alloc)) == HADDR_UNDEF)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "unable to allocate file space for heap")
-
- /* Release old space on disk */
- H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, heap->addr, (hsize_t)heap->heap_alloc);
- H5E_clear_stack(NULL); /* don't really care if the free failed */
-
- heap->addr = new_addr;
- } /* end else */
+ } /* end if */
/* If the last free list in the heap is at the end of the heap, extend it */
if(last_fl && last_fl->offset + last_fl->size == heap->heap_alloc) {
@@ -1052,7 +681,7 @@ H5HL_insert(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t buf_size, const void *
}
#endif
heap->heap_alloc = new_heap_alloc;
- heap->chunk = H5FL_BLK_REALLOC(heap_chunk, heap->chunk, (sizeof_hdr + heap->heap_alloc));
+ heap->chunk = H5FL_BLK_REALLOC(lheap_chunk, heap->chunk, (sizeof_hdr + heap->heap_alloc));
if(NULL == heap->chunk)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, (size_t)(-1), "memory allocation failed")
@@ -1104,7 +733,7 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size)
H5HL_free_t *fl = NULL;
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5HL_remove, FAIL);
+ FUNC_ENTER_NOAPI(H5HL_remove, FAIL)
/* check arguments */
HDassert(f);
@@ -1124,7 +753,7 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size)
* if an error occurs -QAK)
*/
if(H5AC_mark_pinned_or_protected_entry_dirty(f, heap) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTMARKDIRTY, (size_t)(-1), "unable to mark heap as dirty")
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTMARKDIRTY, FAIL, "unable to mark heap as dirty")
/*
* Check if this chunk can be prepended or appended to an already
@@ -1228,7 +857,7 @@ H5HL_remove(H5F_t *f, hid_t dxpl_id, H5HL_t *heap, size_t offset, size_t size)
} /* end if */
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HL_remove() */
@@ -1243,67 +872,33 @@ done:
* koziol@ncsa.uiuc.edu
* Mar 22 2003
*
- * Modifications:
- *
- * John Mainzer - 6/17/05
- * Modified function to use the new dirtied parmeter of
- * H5AC_unprotect(), which allows management of the is_dirty
- * field of the cache info to be moved into the cache code.
- *
*-------------------------------------------------------------------------
*/
herr_t
H5HL_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr)
{
- H5HL_t *heap = NULL;
- size_t sizeof_hdr; /* Cache H5HL header size for file */
- herr_t ret_value=SUCCEED; /* Return value */
+ H5HL_t *heap = NULL; /* Local heap to delete */
+ unsigned cache_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting heap */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5HL_delete, FAIL);
+ FUNC_ENTER_NOAPI(H5HL_delete, FAIL)
/* check arguments */
- assert(f);
- assert(H5F_addr_defined(addr));
-
- /* Cache this for later */
- sizeof_hdr= H5HL_SIZEOF_HDR(f);
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
/* Get heap pointer */
- if (NULL == (heap = H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_WRITE)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap");
-
- /* Check if the heap is contiguous on disk */
- assert(!H5F_addr_overflow(addr,sizeof_hdr));
- if(H5F_addr_eq(heap->addr,addr+sizeof_hdr)) {
- /* Free the contiguous local heap in one call */
- H5_CHECK_OVERFLOW(sizeof_hdr+heap->heap_alloc,size_t,hsize_t);
- if (H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, addr, (hsize_t)(sizeof_hdr+heap->heap_alloc))<0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free contiguous local heap");
- } /* end if */
- else {
- /* Free the local heap's header */
- H5_CHECK_OVERFLOW(sizeof_hdr,size_t,hsize_t);
- if (H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, addr, (hsize_t)sizeof_hdr)<0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap header");
-
- /* Free the local heap's data */
- H5_CHECK_OVERFLOW(heap->heap_alloc,size_t,hsize_t);
- if (H5MF_xfree(f, H5FD_MEM_LHEAP, dxpl_id, heap->addr, (hsize_t)heap->heap_alloc)<0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap data");
- } /* end else */
-
- /* Release the local heap metadata from the cache */
- if (H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, heap, H5AC__DIRTIED_FLAG | H5C__DELETED_FLAG)<0) {
- heap = NULL;
- HGOTO_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release local heap");
- }
- heap = NULL;
+ if(NULL == (heap = (H5HL_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap")
+
+ /* Set the cache flags to delete the heap & free its file space */
+ cache_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
done:
- if (heap && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, heap, H5AC__NO_FLAGS_SET)<0)
- HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release local heap");
+ if(heap && H5AC_unprotect(f, dxpl_id, H5AC_LHEAP, addr, heap, cache_flags) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release local heap")
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HL_delete() */
@@ -1334,7 +929,7 @@ H5HL_get_size(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t *size)
HDassert(size);
/* Get heap pointer */
- if(NULL == (heap = H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (heap = (H5HL_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap")
/* Set the size to return */
@@ -1376,7 +971,7 @@ H5HL_heapsize(H5F_t *f, hid_t dxpl_id, haddr_t addr, hsize_t *heap_size)
HDassert(heap_size);
/* Get heap pointer */
- if(NULL == (heap = H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (heap = (H5HL_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap")
/* Get the total size of the local heap */
diff --git a/src/H5HLcache.c b/src/H5HLcache.c
new file mode 100644
index 0000000..449e166
--- /dev/null
+++ b/src/H5HLcache.c
@@ -0,0 +1,478 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5HLcache.c
+ * Feb 5 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: Implement local heap metadata cache methods.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5HL_PACKAGE /* Suppress error about including H5HLpkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5HLpkg.h" /* Local Heaps */
+#include "H5MFprivate.h" /* File memory management */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+#define H5HL_VERSION 0 /* Local heap collection version */
+#define H5HL_FREE_NULL 1 /* End of free list on disk */
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+/* Local encode/decode routines */
+static herr_t H5HL_serialize(H5F_t *f, H5HL_t *heap, uint8_t *buf);
+
+/* Metadata cache callbacks */
+static H5HL_t *H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata1,
+ void *udata2);
+static herr_t H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t dest, haddr_t addr, H5HL_t *heap, unsigned UNUSED * flags_ptr);
+static herr_t H5HL_clear(H5F_t *f, H5HL_t *heap, hbool_t destroy);
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* H5HL inherits cache-like properties from H5AC */
+const H5AC_class_t H5AC_LHEAP[1] = {{
+ H5AC_LHEAP_ID,
+ (H5AC_load_func_t)H5HL_load,
+ (H5AC_flush_func_t)H5HL_flush,
+ (H5AC_dest_func_t)H5HL_dest,
+ (H5AC_clear_func_t)H5HL_clear,
+ (H5AC_size_func_t)H5HL_size,
+}};
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HL_serialize
+ *
+ * Purpose: Serialize the heap. This function will eliminate free
+ * blocks at the tail of the heap and also split the block
+ * if it needs to be split for the file. This is so that we
+ * can serialize it correctly.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Bill Wendling
+ * wendling@ncsa.uiuc.edu
+ * Sept. 16, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HL_serialize(H5F_t *f, H5HL_t *heap, uint8_t *buf)
+{
+ H5HL_free_t *fl;
+ uint8_t *p;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_serialize)
+
+ /* check args */
+ assert(buf);
+ assert(heap);
+
+ /* serialize the header */
+ p = buf;
+ fl = heap->freelist;
+ HDmemcpy(p, H5HL_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ p += H5_SIZEOF_MAGIC;
+ *p++ = H5HL_VERSION;
+ *p++ = 0; /*reserved*/
+ *p++ = 0; /*reserved*/
+ *p++ = 0; /*reserved*/
+ H5F_ENCODE_LENGTH(f, p, heap->heap_alloc);
+ H5F_ENCODE_LENGTH(f, p, fl ? fl->offset : H5HL_FREE_NULL);
+ H5F_addr_encode(f, &p, heap->addr);
+
+ /* serialize the free list */
+ for (; fl; fl = fl->next) {
+ assert (fl->offset == H5HL_ALIGN (fl->offset));
+ p = heap->chunk + H5HL_SIZEOF_HDR(f) + fl->offset;
+
+ if (fl->next) {
+ H5F_ENCODE_LENGTH(f, p, fl->next->offset);
+ } else {
+ H5F_ENCODE_LENGTH(f, p, H5HL_FREE_NULL);
+ }
+
+ H5F_ENCODE_LENGTH(f, p, fl->size);
+ }
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HL_serialize() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HL_load
+ *
+ * Purpose: Loads a heap from disk.
+ *
+ * Return: Success: Ptr to a local heap memory data structure.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Jul 17 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5HL_t *
+H5HL_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * udata1,
+ void UNUSED * udata2)
+{
+ uint8_t hdr[52];
+ size_t sizeof_hdr; /* Cache H5HL header size for file */
+ const uint8_t *p = NULL;
+ H5HL_t *heap = NULL;
+ H5HL_free_t *fl = NULL, *tail = NULL;
+ size_t free_block = H5HL_FREE_NULL;
+ H5HL_t *ret_value;
+
+ FUNC_ENTER_NOAPI(H5HL_load, NULL)
+
+ /* check arguments */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(!udata1);
+ HDassert(!udata2);
+
+ /* Cache this for later */
+ sizeof_hdr = H5HL_SIZEOF_HDR(f);
+ HDassert(sizeof_hdr <= sizeof(hdr));
+
+ /* Get the local heap's header */
+ if(H5F_block_read(f, H5FD_MEM_LHEAP, addr, sizeof_hdr, dxpl_id, hdr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_READERROR, NULL, "unable to read heap header")
+ p = hdr;
+
+ /* Check magic number */
+ if(HDmemcmp(hdr, H5HL_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap signature")
+ p += H5_SIZEOF_MAGIC;
+
+ /* Version */
+ if(H5HL_VERSION != *p++)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "wrong version number in global heap")
+
+ /* Reserved */
+ p += 3;
+
+ /* Allocate space in memory for the heap */
+ if(NULL == (heap = H5FL_CALLOC(H5HL_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+
+ /* heap data size */
+ H5F_DECODE_LENGTH(f, p, heap->heap_alloc);
+
+ /* free list head */
+ H5F_DECODE_LENGTH(f, p, free_block);
+ if(free_block != H5HL_FREE_NULL && free_block >= heap->heap_alloc)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list")
+
+ /* data */
+ H5F_addr_decode(f, &p, &(heap->addr));
+ if(NULL == (heap->chunk = H5FL_BLK_CALLOC(lheap_chunk, (sizeof_hdr + heap->heap_alloc))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ if(heap->heap_alloc &&
+ H5F_block_read(f, H5FD_MEM_LHEAP, heap->addr, heap->heap_alloc, dxpl_id, heap->chunk + sizeof_hdr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unable to read heap data")
+
+ /* Build free list */
+ while(H5HL_FREE_NULL != free_block) {
+ if(free_block >= heap->heap_alloc)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list")
+ if(NULL == (fl = H5FL_MALLOC(H5HL_free_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ fl->offset = free_block;
+ fl->prev = tail;
+ fl->next = NULL;
+ if(tail)
+ tail->next = fl;
+ tail = fl;
+ if(!heap->freelist)
+ heap->freelist = fl;
+
+ p = heap->chunk + sizeof_hdr + free_block;
+
+ H5F_DECODE_LENGTH(f, p, free_block);
+ if(free_block == 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "free block size is zero?")
+
+ H5F_DECODE_LENGTH(f, p, fl->size);
+ if(fl->offset + fl->size > heap->heap_alloc)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "bad heap free list")
+ } /* end while */
+
+ /* Set return value */
+ ret_value = heap;
+
+done:
+ if(!ret_value && heap)
+ if(H5HL_dest(f,heap) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, NULL, "unable to destroy local heap collection")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HL_load() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HL_flush
+ *
+ * Purpose: Flushes a heap from memory to disk if it's dirty. Optionally
+ * deletes the heap from memory.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Jul 17 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HL_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5HL_t *heap, unsigned UNUSED * flags_ptr)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5HL_flush, FAIL)
+
+ /* check arguments */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(heap);
+
+ if(heap->cache_info.is_dirty) {
+ haddr_t hdr_end_addr;
+ size_t sizeof_hdr = H5HL_SIZEOF_HDR(f); /* cache H5HL header size for file */
+
+ /* Write the header */
+ if(H5HL_serialize(f, heap, heap->chunk) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSERIALIZE, FAIL, "unable to serialize local heap")
+
+ /* Copy buffer to disk */
+ hdr_end_addr = addr + (hsize_t)sizeof_hdr;
+
+ if(H5F_addr_eq(heap->addr, hdr_end_addr)) {
+ /* The header and data are contiguous */
+ if(H5F_block_write(f, H5FD_MEM_LHEAP, addr, (sizeof_hdr + heap->heap_alloc), dxpl_id, heap->chunk) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header and data to file")
+ } /* end if */
+ else {
+ if(H5F_block_write(f, H5FD_MEM_LHEAP, addr, sizeof_hdr, dxpl_id, heap->chunk) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap header to file")
+
+ if(H5F_block_write(f, H5FD_MEM_LHEAP, heap->addr, heap->heap_alloc, dxpl_id, heap->chunk + sizeof_hdr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "unable to write heap data to file")
+ } /* end else */
+
+ heap->cache_info.is_dirty = FALSE;
+ } /* end if */
+
+ /* Should we destroy the memory version? */
+ if(destroy)
+ if(H5HL_dest(f, heap) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap collection")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HL_flush() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HL_dest
+ *
+ * Purpose: Destroys a heap in memory.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Jan 15 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HL_dest(H5F_t *f, H5HL_t *heap)
+{
+ H5HL_free_t *fl; /* Heap object free list */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HL_dest)
+
+ /* check arguments */
+ HDassert(heap);
+
+ /* Verify that node is clean */
+ HDassert(heap->cache_info.is_dirty == FALSE);
+
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!heap->cache_info.free_file_space_on_destroy || H5F_addr_defined(heap->cache_info.addr));
+
+ /* Check for freeing file space for local heap */
+ if(heap->cache_info.free_file_space_on_destroy) {
+ size_t sizeof_hdr; /* H5HL header size for file */
+ haddr_t hdr_addr; /* Address of heap header in file */
+
+ /* Compute this for later */
+ sizeof_hdr = H5HL_SIZEOF_HDR(f);
+ hdr_addr = heap->cache_info.addr;
+
+ /* Check if the heap is contiguous on disk */
+ HDassert(!H5F_addr_overflow(hdr_addr, sizeof_hdr));
+ if(H5F_addr_eq(heap->addr, hdr_addr + sizeof_hdr)) {
+ /* Free the contiguous local heap in one call */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ H5_CHECK_OVERFLOW(sizeof_hdr + heap->heap_alloc, size_t, hsize_t);
+ if(H5MF_xfree(f, H5FD_MEM_LHEAP, H5AC_dxpl_id, hdr_addr, (hsize_t)(sizeof_hdr + heap->heap_alloc)) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free contiguous local heap")
+ } /* end if */
+ else {
+ /* Free the local heap's header */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ H5_CHECK_OVERFLOW(sizeof_hdr, size_t, hsize_t);
+ if(H5MF_xfree(f, H5FD_MEM_LHEAP, H5AC_dxpl_id, hdr_addr, (hsize_t)sizeof_hdr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap header")
+
+ /* Free the local heap's data */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ H5_CHECK_OVERFLOW(heap->heap_alloc, size_t, hsize_t);
+ if(H5MF_xfree(f, H5FD_MEM_LHEAP, H5AC_dxpl_id, heap->addr, (hsize_t)heap->heap_alloc) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free local heap data")
+ } /* end else */
+ } /* end if */
+
+ /* Release resources */
+ if(heap->chunk)
+ heap->chunk = H5FL_BLK_FREE(lheap_chunk, heap->chunk);
+ while(heap->freelist) {
+ fl = heap->freelist;
+ heap->freelist = fl->next;
+ (void)H5FL_FREE(H5HL_free_t, fl);
+ } /* end while */
+ (void)H5FL_FREE(H5HL_t, heap);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HL_dest() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HL_clear
+ *
+ * Purpose: Mark a local heap in memory as non-dirty.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Mar 20 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HL_clear(H5F_t *f, H5HL_t *heap, hbool_t destroy)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HL_clear)
+
+ /* check arguments */
+ HDassert(heap);
+
+ /* Mark heap as clean */
+ heap->cache_info.is_dirty = FALSE;
+
+ if(destroy)
+ if(H5HL_dest(f, heap) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy local heap collection")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HL_clear() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HL_size
+ *
+ * Purpose: Compute the size in bytes of the specified instance of
+ * H5HL_t on disk, and return it in *len_ptr. On failure,
+ * the value of *len_ptr is undefined.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: John Mainzer
+ * 5/13/04
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HL_size(const H5F_t *f, const H5HL_t *heap, size_t *size_ptr)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HL_size)
+
+ /* check arguments */
+ HDassert(f);
+ HDassert(heap);
+ HDassert(size_ptr);
+
+ *size_ptr = H5HL_SIZEOF_HDR(f) + heap->heap_alloc;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5HL_size() */
+
diff --git a/src/H5HLdbg.c b/src/H5HLdbg.c
index f4211f8..1ebb14f 100644
--- a/src/H5HLdbg.c
+++ b/src/H5HLdbg.c
@@ -70,7 +70,7 @@ H5HL_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent, int
assert(indent >= 0);
assert(fwidth >= 0);
- if (NULL == (h = H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_READ)))
+ if (NULL == (h = (H5HL_t *)H5AC_protect(f, dxpl_id, H5AC_LHEAP, addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load heap");
fprintf(stream, "%*sLocal Heap...\n", indent, "");
@@ -91,7 +91,7 @@ H5HL_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent, int
* Traverse the free list and check that all free blocks fall within
* the heap and that no two free blocks point to the same region of
* the heap. */
- if (NULL==(marker = H5MM_calloc(h->heap_alloc)))
+ if (NULL==(marker = (uint8_t *)H5MM_calloc(h->heap_alloc)))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
fprintf(stream, "%*sFree Blocks (offset, size):\n", indent, "");
diff --git a/src/H5HLpkg.h b/src/H5HLpkg.h
index fe6f107..1e34a48 100644
--- a/src/H5HLpkg.h
+++ b/src/H5HLpkg.h
@@ -32,6 +32,9 @@
#include "H5HLprivate.h"
/* Other private headers needed by this file */
+#include "H5ACprivate.h" /* Metadata cache */
+#include "H5FLprivate.h" /* Free lists */
+
/*****************************/
/* Package Private Variables */
@@ -40,17 +43,28 @@
/* The cache subclass */
H5_DLLVAR const H5AC_class_t H5AC_LHEAP[1];
+/* Declare extern the free list to manage the H5HL_free_t struct */
+H5FL_EXTERN(H5HL_free_t);
+
+/* Declare extern the free list to manage the H5HL_t struct */
+H5FL_EXTERN(H5HL_t);
+
+/* Declare extern the PQ free list to manage the heap chunk information */
+H5FL_BLK_EXTERN(lheap_chunk);
+
+
/**************************/
/* Package Private Macros */
/**************************/
#define H5HL_SIZEOF_HDR(F) \
- H5HL_ALIGN(H5HL_SIZEOF_MAGIC + /*heap signature */ \
+ H5HL_ALIGN(H5_SIZEOF_MAGIC + /*heap signature */ \
4 + /*reserved */ \
H5F_SIZEOF_SIZE (F) + /*data size */ \
H5F_SIZEOF_SIZE (F) + /*free list head */ \
H5F_SIZEOF_ADDR (F)) /*data address */
+
/****************************/
/* Package Private Typedefs */
/****************************/
@@ -71,10 +85,13 @@ struct H5HL_t {
H5HL_free_t *freelist; /*the free list */
};
+
/******************************/
/* Package Private Prototypes */
/******************************/
-#endif
+H5_DLL herr_t H5HL_dest(H5F_t *f, H5HL_t *heap);
+H5_DLL herr_t H5HL_size(const H5F_t *f, const H5HL_t *heap, size_t *size_ptr);
+#endif /* _H5HLpkg_H */
diff --git a/src/H5HLprivate.h b/src/H5HLprivate.h
index d8a4b49..2a3e2df 100644
--- a/src/H5HLprivate.h
+++ b/src/H5HLprivate.h
@@ -44,9 +44,6 @@
# undef H5HL_DEBUG
#endif
-#define H5HL_MAGIC "HEAP" /*heap magic number */
-#define H5HL_SIZEOF_MAGIC 4
-
#define H5HL_ALIGN(X) (((X)+7)&(unsigned)(~0x07)) /*align on 8-byte boundary */
#define H5HL_SIZEOF_FREE(F) \
diff --git a/src/H5HP.c b/src/H5HP.c
index e0a94a7..2b1fe89 100644
--- a/src/H5HP.c
+++ b/src/H5HP.c
@@ -235,11 +235,11 @@ H5HP_sink_max(H5HP_t *heap, size_t loc)
} /* end while */
/* Put object into heap at correct location */
- heap->heap[loc].val=val;
- heap->heap[loc].obj=obj;
+ heap->heap[loc].val = val;
+ heap->heap[loc].obj = (H5HP_info_t *)obj;
/* Update heap location for object */
- heap->heap[loc].obj->heap_loc=loc;
+ heap->heap[loc].obj->heap_loc = loc;
FUNC_LEAVE_NOAPI(ret_value);
} /* end H5HP_sink_max() */
@@ -304,11 +304,11 @@ H5HP_sink_min(H5HP_t *heap, size_t loc)
} /* end while */
/* Put object into heap at correct location */
- heap->heap[loc].val=val;
- heap->heap[loc].obj=obj;
+ heap->heap[loc].val = val;
+ heap->heap[loc].obj = (H5HP_info_t *)obj;
/* Update heap location for object */
- heap->heap[loc].obj->heap_loc=loc;
+ heap->heap[loc].obj->heap_loc = loc;
FUNC_LEAVE_NOAPI(ret_value);
} /* end H5HP_sink_min() */
@@ -382,7 +382,7 @@ done:
if(new_heap!=NULL) {
if(new_heap->heap!=NULL)
H5FL_SEQ_FREE(H5HP_ent_t,new_heap->heap);
- H5FL_FREE(H5HP_t,new_heap);
+ (void)H5FL_FREE(H5HP_t,new_heap);
} /* end if */
} /* end if */
@@ -489,9 +489,9 @@ H5HP_insert(H5HP_t *heap, int val, void *obj)
} /* end if */
/* Insert new object at end of heap */
- heap->heap[heap->nobjs].val=val;
- heap->heap[heap->nobjs].obj=obj;
- heap->heap[heap->nobjs].obj->heap_loc=heap->nobjs;
+ heap->heap[heap->nobjs].val = val;
+ heap->heap[heap->nobjs].obj = (H5HP_info_t *)obj;
+ heap->heap[heap->nobjs].obj->heap_loc = heap->nobjs;
/* Restore heap condition */
if(heap->type==H5HP_MAX_HEAP) {
@@ -896,25 +896,25 @@ done:
herr_t
H5HP_close(H5HP_t *heap)
{
- FUNC_ENTER_NOAPI_NOFUNC(H5HP_close);
+ FUNC_ENTER_NOAPI_NOFUNC(H5HP_close)
/* Check args */
- assert(heap);
+ HDassert(heap);
/* Check internal consistency */
/* (Pre-condition) */
- assert(heap->nobjs<heap->nalloc);
- assert(heap->heap);
- assert((heap->type==H5HP_MAX_HEAP && heap->heap[0].val==INT_MAX) ||
- (heap->type==H5HP_MIN_HEAP && heap->heap[0].val==INT_MIN));
- assert(heap->heap[0].obj==NULL);
+ HDassert(heap->nobjs < heap->nalloc);
+ HDassert(heap->heap);
+ HDassert((heap->type == H5HP_MAX_HEAP && heap->heap[0].val == INT_MAX) ||
+ (heap->type == H5HP_MIN_HEAP && heap->heap[0].val == INT_MIN));
+ HDassert(NULL == heap->heap[0].obj);
/* Free internal structures for heap */
- H5FL_SEQ_FREE(H5HP_ent_t,heap->heap);
+ H5FL_SEQ_FREE(H5HP_ent_t, heap->heap);
/* Free actual heap object */
- H5FL_FREE(H5HP_t,heap);
+ (void)H5FL_FREE(H5HP_t, heap);
- FUNC_LEAVE_NOAPI(SUCCEED);
+ FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5HP_close() */
diff --git a/src/H5I.c b/src/H5I.c
index 0b8b84e..b308712 100644
--- a/src/H5I.c
+++ b/src/H5I.c
@@ -90,6 +90,7 @@
typedef struct H5I_id_info_t {
hid_t id; /* ID for this info */
unsigned count; /* ref. count for this atom */
+ unsigned app_count; /* ref. count of application visible atoms */
void *obj_ptr; /* pointer associated with the atom */
struct H5I_id_info_t *next; /* link to next atom (in case of hash-clash)*/
} H5I_id_info_t;
@@ -145,10 +146,10 @@ DESCRIPTION
static herr_t
H5I_init_interface(void)
{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5I_init_interface);
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5I_init_interface)
- FUNC_LEAVE_NOAPI(SUCCEED);
-}
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5I_init_interface() */
/*-------------------------------------------------------------------------
@@ -174,31 +175,32 @@ H5I_term_interface(void)
{
H5I_id_type_t *type_ptr;
H5I_type_t type;
- int n=0;
+ int n = 0;
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5I_term_interface);
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5I_term_interface)
- if (H5_interface_initialize_g) {
+ if(H5_interface_initialize_g) {
/* How many types are still being used? */
- for (type=(H5I_type_t)0; type<H5I_next_type; H5_INC_ENUM(H5I_type_t,type)) {
- if ((type_ptr=H5I_id_type_list_g[type]) && type_ptr->id_list)
+ for(type = (H5I_type_t)0; type < H5I_next_type; H5_INC_ENUM(H5I_type_t, type)) {
+ if((type_ptr = H5I_id_type_list_g[type]) && type_ptr->id_list)
n++;
- }
+ } /* end for */
/* If no types are used then clean up */
- if (0==n) {
- for (type=(H5I_type_t)0; type<H5I_next_type; H5_INC_ENUM(H5I_type_t,type)) {
+ if(0 == n) {
+ for(type = (H5I_type_t)0; type < H5I_next_type; H5_INC_ENUM(H5I_type_t,type)) {
type_ptr = H5I_id_type_list_g[type];
H5MM_xfree(type_ptr);
H5I_id_type_list_g[type] = NULL;
- }
- }
+ } /* end for */
+ } /* end if */
/* Mark interface closed */
H5_interface_initialize_g = 0;
- }
- FUNC_LEAVE_NOAPI(n);
-}
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(n)
+} /* end H5I_term_interface() */
/*-------------------------------------------------------------------------
@@ -225,17 +227,19 @@ H5I_term_interface(void)
*
*-------------------------------------------------------------------------
*/
-H5I_type_t H5Iregister_type(size_t hash_size, unsigned reserved, H5I_free_t free_func)
+H5I_type_t
+H5Iregister_type(size_t hash_size, unsigned reserved, H5I_free_t free_func)
{
- H5I_type_t ret_value;
- FUNC_ENTER_API(H5Iregister_type, H5I_BADID);
+ H5I_type_t ret_value; /* Return value */
- /* Call H5I_register_type with a value of 0 to get a new type */
- ret_value = H5I_register_type((H5I_type_t)0, hash_size, reserved, free_func);
+ FUNC_ENTER_API(H5Iregister_type, H5I_BADID)
+
+ /* Call H5I_register_type with a value of 0 to get a new type */
+ ret_value = H5I_register_type((H5I_type_t)0, hash_size, reserved, free_func);
done:
- FUNC_LEAVE_API(ret_value);
-}
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Iregister_type() */
/*-------------------------------------------------------------------------
@@ -275,100 +279,94 @@ done:
*
*-------------------------------------------------------------------------
*/
-
-H5I_type_t H5I_register_type(H5I_type_t type_id, size_t hash_size, unsigned reserved, H5I_free_t free_func)
+H5I_type_t
+H5I_register_type(H5I_type_t type_id, size_t hash_size, unsigned reserved,
+ H5I_free_t free_func)
{
- H5I_type_t ret_value=H5I_BADID; /* type ID to return */
- H5I_id_type_t *type_ptr = NULL; /*ptr to the atomic type*/
- int i;
- int done;
-
- FUNC_ENTER_NOAPI(H5I_register_type, H5I_BADID);
-
- /* Check that type_id is either a library type or zero */
- if(type_id < 0 || type_id >= H5I_NTYPES)
- {
- HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, H5I_BADID, "invalid type ID");
- }
-
- if(type_id == 0) /* Generate a new H5I_type_t value */
- {
- /* Increment the number of types*/
- if (H5I_next_type < MAX_NUM_TYPES)
- {
- ret_value = H5I_next_type;
- H5_INC_ENUM(H5I_type_t, H5I_next_type);
- }
- else
- {
- done = 0;
- /* Look for a free type to give out */
- for(i = H5I_NTYPES; i < MAX_NUM_TYPES && done==0; i++)
- {
- if(H5I_id_type_list_g[i] == NULL)
- {
- /* Found a free type ID */
- ret_value = (H5I_type_t)i;
- done = 1;
- }
- }
-
- /* Verify that we found a type to give out */
- if(done == 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5I_BADID, "Maximum number of ID types exceeded.");
- }
- }
- else /* type_id is a library type; use this value. */
- {
- ret_value = type_id;
- }
-
- /* Initialize the type */
+ H5I_id_type_t *type_ptr = NULL; /*ptr to the atomic type*/
+ H5I_type_t ret_value = H5I_BADID; /* type ID to return */
+
+ FUNC_ENTER_NOAPI(H5I_register_type, H5I_BADID)
+
+ /* Check that type_id is either a library type or zero */
+ if(type_id < 0 || type_id >= H5I_NTYPES)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, H5I_BADID, "invalid type ID")
+
+ if(type_id == 0) { /* Generate a new H5I_type_t value */
+ /* Increment the number of types*/
+ if(H5I_next_type < MAX_NUM_TYPES) {
+ ret_value = H5I_next_type;
+ H5_INC_ENUM(H5I_type_t, H5I_next_type);
+ }
+ else {
+ hbool_t done; /* Indicate that search was successful */
+ int i; /* Local index variable */
+
+ /* Look for a free type to give out */
+ done = FALSE;
+ for(i = H5I_NTYPES; i < MAX_NUM_TYPES && done == FALSE; i++) {
+ if(NULL == H5I_id_type_list_g[i]) {
+ /* Found a free type ID */
+ ret_value = (H5I_type_t)i;
+ done = TRUE;
+ } /* end if */
+ } /* end for */
+
+ /* Verify that we found a type to give out */
+ if(done == FALSE)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5I_BADID, "Maximum number of ID types exceeded.")
+ } /* end else */
+ } /* end if */
+ else /* type_id is a library type; use this value. */
+ ret_value = type_id;
+
+ /* Initialize the type */
+
/* Check arguments */
#ifdef HASH_SIZE_POWER_2
- if (!POWER_OF_TWO(hash_size) || hash_size == 1)
- HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, H5I_BADID, "invalid hash size");
+ if(!POWER_OF_TWO(hash_size) || hash_size == 1)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, H5I_BADID, "invalid hash size")
#endif /* HASH_SIZE_POWER_2 */
- if (H5I_id_type_list_g[ret_value] == NULL) {
- /* Allocate the type information for new type */
- if (NULL==(type_ptr = H5MM_calloc(sizeof(H5I_id_type_t))))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, H5I_BADID, "memory allocation failed");
- H5I_id_type_list_g[ret_value] = type_ptr;
- } else {
- /* Get the pointer to the existing type */
- type_ptr = H5I_id_type_list_g[ret_value];
- }
-
- if (type_ptr->count == 0) {
- /* Initialize the ID type structure for new types */
- type_ptr->hash_size = hash_size;
- type_ptr->reserved = reserved;
- type_ptr->wrapped = 0;
- type_ptr->ids = 0;
- type_ptr->nextid = reserved;
- type_ptr->free_func = free_func;
- type_ptr->id_list = H5MM_calloc(hash_size*sizeof(H5I_id_info_t *));
- if (NULL==type_ptr->id_list)
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, H5I_BADID, "memory allocation failed");
- }
+ if(NULL == H5I_id_type_list_g[ret_value]) {
+ /* Allocate the type information for new type */
+ if(NULL == (type_ptr = (H5I_id_type_t *)H5MM_calloc(sizeof(H5I_id_type_t))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5I_BADID, "memory allocation failed")
+ H5I_id_type_list_g[ret_value] = type_ptr;
+ } /* end if */
+ else {
+ /* Get the pointer to the existing type */
+ type_ptr = H5I_id_type_list_g[ret_value];
+ } /* end else */
+
+ if(type_ptr->count == 0) {
+ /* Initialize the ID type structure for new types */
+ type_ptr->hash_size = hash_size;
+ type_ptr->reserved = reserved;
+ type_ptr->wrapped = 0;
+ type_ptr->ids = 0;
+ type_ptr->nextid = reserved;
+ type_ptr->free_func = free_func;
+ type_ptr->id_list = (H5I_id_info_t **)H5MM_calloc(hash_size * sizeof(H5I_id_info_t *));
+ if(NULL == type_ptr->id_list)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5I_BADID, "memory allocation failed")
+ } /* end if */
/* Increment the count of the times this type has been initialized */
type_ptr->count++;
- done:
- if(ret_value == H5I_BADID) /* Clean up on error */
- {
- if (type_ptr != NULL)
- {
- H5MM_xfree(type_ptr->id_list);
- H5MM_xfree(type_ptr);
- }
- }
+done:
+ if(ret_value == H5I_BADID) { /* Clean up on error */
+ if(type_ptr != NULL) {
+ H5MM_xfree(type_ptr->id_list);
+ H5MM_xfree(type_ptr);
+ } /* end if */
+ } /* end if */
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5I_register_type() */
+
/*-------------------------------------------------------------------------
* Function: H5Itype_exists
*
@@ -387,21 +385,23 @@ H5I_type_t H5I_register_type(H5I_type_t type_id, size_t hash_size, unsigned rese
*
*-------------------------------------------------------------------------
*/
-htri_t H5Itype_exists(H5I_type_t type)
+htri_t
+H5Itype_exists(H5I_type_t type)
{
htri_t ret_value = TRUE; /* Return value */
- FUNC_ENTER_API(H5Itype_exists, FAIL);
+ FUNC_ENTER_API(H5Itype_exists, FAIL)
+ H5TRACE1("t", "It", type);
- if (type<=H5I_BADID || type>=H5I_next_type)
- HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number");
+ if(type <= H5I_BADID || type >= H5I_next_type)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
- if (H5I_id_type_list_g[type] == NULL)
+ if(NULL == H5I_id_type_list_g[type])
ret_value = FALSE;
done:
- FUNC_LEAVE_API(ret_value);
-}
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Itype_exists() */
/*-------------------------------------------------------------------------
@@ -428,37 +428,38 @@ done:
*
*-------------------------------------------------------------------------
*/
-herr_t H5Inmembers(H5I_type_t type, hsize_t *num_members)
+herr_t
+H5Inmembers(H5I_type_t type, hsize_t *num_members)
{
int ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_API(H5Inmembers, FAIL);
+ FUNC_ENTER_API(H5Inmembers, FAIL)
+ H5TRACE2("e", "It*h", type, num_members);
- if( H5I_IS_LIB_TYPE( type ) )
- HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type");
+ if(H5I_IS_LIB_TYPE(type))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type")
/* Validate parameters. This needs to be done here, instead of letting
* the private interface handle it, because the public interface throws
* an error when the supplied type does not exist.
*/
- if (type<=H5I_BADID || type>=H5I_next_type)
- HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number");
- if (NULL==H5I_id_type_list_g[type])
- HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "supplied type does not exist");
+ if(type <= H5I_BADID || type >= H5I_next_type)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
+ if(NULL == H5I_id_type_list_g[type])
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "supplied type does not exist")
- if (num_members)
- {
+ if(num_members) {
int members;
- if ((members = H5I_nmembers(type)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTCOUNT, FAIL, "can't compute number of members");
+ if((members = H5I_nmembers(type)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTCOUNT, FAIL, "can't compute number of members")
- *num_members=(hsize_t)members;
- }
+ *num_members = (hsize_t)members;
+ } /* end if */
done:
- FUNC_LEAVE_API(ret_value);
-}
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Inmembers() */
/*-------------------------------------------------------------------------
@@ -484,19 +485,19 @@ H5I_nmembers(H5I_type_t type)
H5I_id_type_t *type_ptr = NULL;
int ret_value;
- FUNC_ENTER_NOAPI(H5I_nmembers, FAIL);
+ FUNC_ENTER_NOAPI(H5I_nmembers, FAIL)
- if (type<=H5I_BADID || type>=H5I_next_type)
- HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number");
- if (NULL==(type_ptr=H5I_id_type_list_g[type]) || type_ptr->count<=0)
+ if(type <= H5I_BADID || type >= H5I_next_type)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
+ if(NULL == (type_ptr = H5I_id_type_list_g[type]) || type_ptr->count <= 0)
HGOTO_DONE(0);
/* Set return value */
H5_ASSIGN_OVERFLOW(ret_value, type_ptr->ids, unsigned, int);
done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5I_nmembers() */
/*-------------------------------------------------------------------------
@@ -517,22 +518,22 @@ done:
* Modifications:
*-------------------------------------------------------------------------
*/
-herr_t H5Iclear_type(H5I_type_t type, hbool_t force)
+herr_t
+H5Iclear_type(H5I_type_t type, hbool_t force)
{
- herr_t ret_value; /* Return value */
+ herr_t ret_value; /* Return value */
- FUNC_ENTER_API(H5Iclear_type, FAIL);
+ FUNC_ENTER_API(H5Iclear_type, FAIL)
+ H5TRACE2("e", "Itb", type, force);
- if( H5I_IS_LIB_TYPE( type ) )
- {
- HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type");
- }
+ if(H5I_IS_LIB_TYPE(type))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type")
- ret_value = H5I_clear_type(type, force);
+ ret_value = H5I_clear_type(type, force, TRUE);
- done:
- FUNC_LEAVE_API(ret_value);
-}
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Iclear_type() */
/*-------------------------------------------------------------------------
@@ -561,50 +562,56 @@ herr_t H5Iclear_type(H5I_type_t type, hbool_t force)
* things like property lists, files, etc. Objects that have a
* reference count larger than one are not affected unless FORCE
* is non-zero.
+ *
+ * Neil Fortner, 2008-08-08
+ * Added app_ref parameter. If app_ref is FALSE, then the
+ * application reference count is ignored (i.e. subtracted from
+ * the total reference count) when determining which id's to
+ * close.
*-------------------------------------------------------------------------
*/
herr_t
-H5I_clear_type(H5I_type_t type, hbool_t force)
+H5I_clear_type(H5I_type_t type, hbool_t force, hbool_t app_ref)
{
- H5I_id_type_t *type_ptr = NULL; /* ptr to the atomic type */
- H5I_id_info_t *cur=NULL; /* Current node being worked with */
- H5I_id_info_t *next=NULL; /* Next node in list */
- H5I_id_info_t *last=NULL; /* Last node seen */
- H5I_id_info_t *tmp=NULL; /* Temporary node ptr */
- int ret_value = SUCCEED;
- unsigned delete_node; /* Flag to indicate node should be removed from linked list */
- unsigned i;
+ H5I_id_type_t *type_ptr; /* ptr to the atomic type */
+ unsigned i; /* Local index variable */
+ int ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5I_clear_type, FAIL);
+ FUNC_ENTER_NOAPI(H5I_clear_type, FAIL)
- if (type <= H5I_BADID || type >= H5I_next_type)
- HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number");
+ if(type <= H5I_BADID || type >= H5I_next_type)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
type_ptr = H5I_id_type_list_g[type];
- if (type_ptr == NULL || type_ptr->count <= 0)
- HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type");
+ if(type_ptr == NULL || type_ptr->count <= 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type")
/*
* Call free method for all objects in type regardless of their reference
* counts. Ignore the return value from from the free method and remove
* object from type regardless if FORCE is non-zero.
*/
- for (i=0; i<type_ptr->hash_size; i++) {
- for (cur=type_ptr->id_list[i]; cur; cur=next) {
+ for(i = 0; i < type_ptr->hash_size; i++) {
+ H5I_id_info_t *cur; /* Current node being worked with */
+ H5I_id_info_t *next; /* Next node in list */
+
+ for(cur = type_ptr->id_list[i]; cur; cur = next) {
+ hbool_t delete_node; /* Flag to indicate node should be removed from linked list */
+
/*
* Do nothing to the object if the reference count is larger than
* one and forcing is off.
*/
- if (!force && cur->count>1) {
- next=cur->next;
+ if(!force && (cur->count - (!app_ref * cur->app_count)) > 1) {
+ next = cur->next;
continue;
} /* end if */
/* Check for a 'free' function and call it, if it exists */
- if (type_ptr->free_func && (type_ptr->free_func)(cur->obj_ptr)<0) {
- if (force) {
+ if(type_ptr->free_func && (type_ptr->free_func)(cur->obj_ptr) < 0) {
+ if(force) {
#ifdef H5I_DEBUG
- if (H5DEBUG(I)) {
+ if(H5DEBUG(I)) {
fprintf(H5DEBUG(I), "H5I: free type=%d obj=0x%08lx "
"failure ignored\n", (int)type,
(unsigned long)(cur->obj_ptr));
@@ -612,20 +619,23 @@ H5I_clear_type(H5I_type_t type, hbool_t force)
#endif /*H5I_DEBUG*/
/* Indicate node should be removed from list */
- delete_node=1;
+ delete_node = TRUE;
} /* end if */
else {
/* Indicate node should _NOT_ be remove from list */
- delete_node=0;
+ delete_node = FALSE;
} /* end else */
} /* end if */
else {
/* Indicate node should be removed from list */
- delete_node=1;
+ delete_node = TRUE;
} /* end else */
/* Check if we should delete this node or not */
if(delete_node) {
+ H5I_id_info_t *last; /* Last node seen */
+ H5I_id_info_t *tmp; /* Temporary node ptr */
+
/* Decrement the number of IDs in the type */
(type_ptr->ids)--;
@@ -637,28 +647,28 @@ H5I_clear_type(H5I_type_t type, hbool_t force)
/* list, because the node's 'free' callback could have */
/* make an H5I call, which could potentially change the */
/* order of the nodes on the list - QAK) */
- last=NULL;
- tmp=type_ptr->id_list[i];
- while(tmp!=cur) {
- assert(tmp!=NULL);
- last=tmp;
- tmp=tmp->next;
+ last = NULL;
+ tmp = type_ptr->id_list[i];
+ while(tmp != cur) {
+ HDassert(tmp != NULL);
+ last = tmp;
+ tmp = tmp->next;
} /* end while */
/* Delete the node from the list */
- if(last==NULL) {
+ if(NULL == last) {
/* Node at head of list, just advance the list head to next node */
- assert(type_ptr->id_list[i]==cur);
+ HDassert(type_ptr->id_list[i] == cur);
type_ptr->id_list[i] = next;
} /* end if */
else {
/* Node in middle of list, jump over it */
- assert(last->next==cur);
- last->next=next;
+ HDassert(last->next == cur);
+ last->next = next;
} /* end else */
/* Free the node */
- H5FL_FREE(H5I_id_info_t,cur);
+ (void)H5FL_FREE(H5I_id_info_t, cur);
} /* end if */
else {
/* Advance to next node */
@@ -668,8 +678,8 @@ H5I_clear_type(H5I_type_t type, hbool_t force)
} /* end for */
done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5I_clear_type() */
/*-------------------------------------------------------------------------
@@ -684,28 +694,28 @@ done:
* Return: Zero on success/Negative on failure
*
* Programmer: Nathaniel Furrer
- * James Laird
+ * James Laird
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
-herr_t H5Idestroy_type(H5I_type_t type)
+herr_t
+H5Idestroy_type(H5I_type_t type)
{
- herr_t ret_value;
+ herr_t ret_value; /* Return value */
- FUNC_ENTER_API(H5Idestroy_type, FAIL);
+ FUNC_ENTER_API(H5Idestroy_type, FAIL)
+ H5TRACE1("e", "It", type);
- if( H5I_IS_LIB_TYPE( type ) )
- {
- HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type");
- }
+ if(H5I_IS_LIB_TYPE(type))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type")
- ret_value = H5I_destroy_type(type);
+ ret_value = H5I_destroy_type(type);
- done:
- FUNC_LEAVE_API(ret_value);
-}
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Idestroy_type() */
/*-------------------------------------------------------------------------
@@ -719,37 +729,39 @@ herr_t H5Idestroy_type(H5I_type_t type)
* Return: Zero on success/Negative on failure
*
* Programmer: Nathaniel Furrer
- * James Laird
+ * James Laird
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
-herr_t H5I_destroy_type(H5I_type_t type)
+herr_t
+H5I_destroy_type(H5I_type_t type)
{
- herr_t ret_value = FAIL;
- H5I_id_type_t *type_ptr = NULL; /* ptr to the atomic type */
+ H5I_id_type_t *type_ptr; /* ptr to the atomic type */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5I_destroy_type, FAIL);
+ FUNC_ENTER_NOAPI(H5I_destroy_type, FAIL)
- if (type <= H5I_BADID || type >= H5I_next_type)
- HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number");
+ if(type <= H5I_BADID || type >= H5I_next_type)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
type_ptr = H5I_id_type_list_g[type];
- if (type_ptr == NULL || type_ptr->count <= 0)
- HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type");
+ if(type_ptr == NULL || type_ptr->count <= 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type")
- H5I_clear_type(type, TRUE);
- H5E_clear_stack(NULL); /*don't care about errors*/
- H5MM_xfree(type_ptr->id_list);
+ /* Close/clear/destroy all IDs for this type */
+ H5I_clear_type(type, TRUE, FALSE);
+ H5E_clear_stack(NULL); /*don't care about errors*/
- H5MM_free(type_ptr);
- H5I_id_type_list_g[type] = NULL;
- ret_value = 0;
+ H5MM_xfree(type_ptr->id_list);
+
+ H5MM_free(type_ptr);
+ H5I_id_type_list_g[type] = NULL;
done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5I_destroy_type() */
/*-------------------------------------------------------------------------
@@ -768,22 +780,22 @@ done:
*
*-------------------------------------------------------------------------
*/
-hid_t H5Iregister(H5I_type_t type, void *object)
+hid_t
+H5Iregister(H5I_type_t type, void *object)
{
- hid_t ret_value; /* Return value */
+ hid_t ret_value; /* Return value */
- FUNC_ENTER_API(H5Iregister, H5I_INVALID_HID);
+ FUNC_ENTER_API(H5Iregister, H5I_INVALID_HID)
+ H5TRACE2("i", "It*x", type, object);
- if( H5I_IS_LIB_TYPE( type ) )
- {
- HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type");
- }
+ if(H5I_IS_LIB_TYPE(type))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type")
- ret_value = H5I_register(type, object);
+ ret_value = H5I_register(type, object, TRUE);
- done:
- FUNC_LEAVE_API(ret_value);
-}
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Iregister() */
/*-------------------------------------------------------------------------
@@ -805,41 +817,47 @@ hid_t H5Iregister(H5I_type_t type, void *object)
*
* Modifications:
*
+ * Neil Fortner, 7 Aug 2008
+ * Added app_ref parameter and support for the app_count field, to
+ * distiguish between reference count from the library and from the
+ * application.
+ *
*-------------------------------------------------------------------------
*/
hid_t
-H5I_register(H5I_type_t type, void *object)
+H5I_register(H5I_type_t type, void *object, hbool_t app_ref)
{
- H5I_id_type_t *type_ptr=NULL; /*ptr to the type */
- H5I_id_info_t *id_ptr=NULL; /*ptr to the new ID information */
+ H5I_id_type_t *type_ptr; /*ptr to the type */
+ H5I_id_info_t *id_ptr; /*ptr to the new ID information */
hid_t new_id; /*new ID */
unsigned hash_loc; /*new item's hash table location*/
hid_t next_id; /*next ID to check */
- hid_t ret_value=SUCCEED; /*return value */
H5I_id_info_t *curr_id; /*ptr to the current atom */
unsigned i; /*counter */
+ hid_t ret_value = SUCCEED; /*return value */
- FUNC_ENTER_NOAPI(H5I_register, FAIL);
+ FUNC_ENTER_NOAPI(H5I_register, FAIL)
/* Check arguments */
- if (type <= H5I_BADID || type >= H5I_next_type)
- HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number");
+ if(type <= H5I_BADID || type >= H5I_next_type)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
type_ptr = H5I_id_type_list_g[type];
- if (type_ptr == NULL || type_ptr->count <= 0)
- HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type");
- if ((id_ptr = H5FL_MALLOC(H5I_id_info_t)) == NULL)
- HGOTO_ERROR(H5E_ATOM, H5E_NOSPACE, FAIL, "memory allocation failed");
+ if(NULL == type_ptr || type_ptr->count <= 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type")
+ if(NULL == (id_ptr = H5FL_MALLOC(H5I_id_info_t)))
+ HGOTO_ERROR(H5E_ATOM, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Create the struct & it's ID */
new_id = H5I_MAKE(type, type_ptr->nextid);
id_ptr->id = new_id;
id_ptr->count = 1; /*initial reference count*/
+ id_ptr->app_count = !!app_ref;
id_ptr->obj_ptr = object;
id_ptr->next = NULL;
/* hash bucket already full, prepend to front of chain */
- hash_loc = type_ptr->nextid % (unsigned) type_ptr->hash_size;
- if (type_ptr->id_list[hash_loc] != NULL)
+ hash_loc = type_ptr->nextid % (unsigned)type_ptr->hash_size;
+ if(type_ptr->id_list[hash_loc] != NULL)
id_ptr->next = type_ptr->id_list[hash_loc];
/* Insert into the type */
@@ -852,53 +870,55 @@ H5I_register(H5I_type_t type, void *object)
* wrapping around, thus necessitating checking for duplicate IDs being
* handed out.
*/
- if (type_ptr->nextid > (unsigned)ID_MASK) {
+ if(type_ptr->nextid > (unsigned)ID_MASK) {
type_ptr->wrapped = 1;
type_ptr->nextid = type_ptr->reserved;
- }
+ } /* end if */
/*
* If we've wrapped around then we need to check for duplicate id's being
* handed out.
*/
- if (type_ptr->wrapped) {
+ if(type_ptr->wrapped) {
/*
* Make sure we check all available ID's. If we're about at the end
* of the range then wrap around and check the beginning values. If
* we check all possible values and didn't find any free ones *then*
* we can fail.
*/
- for (i=type_ptr->reserved; i<ID_MASK; i++) {
+ for(i = type_ptr->reserved; i < ID_MASK; i++) {
/* Handle end of range by wrapping to beginning */
- if (type_ptr->nextid>(unsigned)ID_MASK)
+ if(type_ptr->nextid > (unsigned)ID_MASK)
type_ptr->nextid = type_ptr->reserved;
/* new ID to check for */
next_id = H5I_MAKE(type, type_ptr->nextid);
- hash_loc = H5I_LOC (type_ptr->nextid, type_ptr->hash_size);
+ hash_loc = H5I_LOC(type_ptr->nextid, type_ptr->hash_size);
curr_id = type_ptr->id_list[hash_loc];
- if (curr_id == NULL)
+ if(curr_id == NULL)
break; /* Ha! this is not likely... */
- while (curr_id) {
- if (curr_id->id == next_id)
+ while(curr_id) {
+ if(curr_id->id == next_id)
break;
curr_id = curr_id->next;
- }
- if (!curr_id)
+ } /* end while */
+ if(!curr_id)
break; /* must not have found a match */
type_ptr->nextid++;
- }
+ } /* end for */
- if (i>=(unsigned)ID_MASK)
+ if(i >= (unsigned)ID_MASK)
/* All the IDs are gone! */
- HGOTO_ERROR(H5E_ATOM, H5E_NOIDS, FAIL, "no IDs available in type");
- }
+ HGOTO_ERROR(H5E_ATOM, H5E_NOIDS, FAIL, "no IDs available in type")
+ } /* end if */
+
+ /* Set return value */
ret_value = new_id;
- done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5I_register() */
/*-------------------------------------------------------------------------
@@ -920,20 +940,20 @@ H5I_register(H5I_type_t type, void *object)
void *
H5I_object(hid_t id)
{
- H5I_id_info_t *id_ptr = NULL; /*ptr to the new atom */
+ H5I_id_info_t *id_ptr; /*ptr to the new atom */
void *ret_value = NULL; /*return value */
- FUNC_ENTER_NOAPI(H5I_object, NULL);
+ FUNC_ENTER_NOAPI(H5I_object, NULL)
/* General lookup of the ID */
- if (NULL!=(id_ptr = H5I_find_id(id))) {
+ if(NULL != (id_ptr = H5I_find_id(id))) {
/* Get the object pointer to return */
ret_value = id_ptr->obj_ptr;
} /* end if */
done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end if */
/*-------------------------------------------------------------------------
@@ -956,23 +976,24 @@ done:
*
*-------------------------------------------------------------------------
*/
-void *H5Iobject_verify(hid_t id, H5I_type_t id_type)
+void *
+H5Iobject_verify(hid_t id, H5I_type_t id_type)
{
- void * ret_value; /* Return value */
+ void * ret_value; /* Return value */
- FUNC_ENTER_API(H5Iobject_verify, NULL);
+ FUNC_ENTER_API(H5Iobject_verify, NULL)
- if( H5I_IS_LIB_TYPE( id_type ) )
- HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "cannot call public function on library type")
+ if(H5I_IS_LIB_TYPE(id_type))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "cannot call public function on library type")
- if(id_type < 1 || id_type >= H5I_next_type)
- HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "identifier has invalid type")
+ if(id_type < 1 || id_type >= H5I_next_type)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "identifier has invalid type")
- ret_value = H5I_object_verify(id, id_type);
+ ret_value = H5I_object_verify(id, id_type);
done:
- FUNC_LEAVE_API(ret_value);
-}
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Iobject_verify() */
/*-------------------------------------------------------------------------
@@ -999,18 +1020,18 @@ H5I_object_verify(hid_t id, H5I_type_t id_type)
H5I_id_info_t *id_ptr = NULL; /*ptr to the new atom */
void *ret_value = NULL; /*return value */
- FUNC_ENTER_NOAPI(H5I_object_verify, NULL);
+ FUNC_ENTER_NOAPI(H5I_object_verify, NULL)
- assert(id_type>=1 && id_type<H5I_next_type);
+ HDassert(id_type >= 1 && id_type < H5I_next_type);
/* Verify that the type of the ID is correct & lookup the ID */
- if(id_type == H5I_TYPE(id) && NULL!=(id_ptr = H5I_find_id(id))) {
+ if(id_type == H5I_TYPE(id) && NULL != (id_ptr = H5I_find_id(id))) {
/* Get the object pointer to return */
ret_value = id_ptr->obj_ptr;
} /* end if */
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* H5I_object_verify() */
@@ -1038,16 +1059,16 @@ H5I_get_type(hid_t id)
{
H5I_type_t ret_value = H5I_BADID;
- FUNC_ENTER_NOAPI(H5I_get_type, H5I_BADID);
+ FUNC_ENTER_NOAPI(H5I_get_type, H5I_BADID)
- if (id>0)
+ if(id > 0)
ret_value = H5I_TYPE(id);
- assert(ret_value>=H5I_BADID && ret_value<H5I_next_type);
+ HDassert(ret_value >= H5I_BADID && ret_value < H5I_next_type);
done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5I_get_type() */
/*-------------------------------------------------------------------------
@@ -1073,19 +1094,19 @@ done:
H5I_type_t
H5Iget_type(hid_t id)
{
- H5I_type_t ret_value = H5I_BADID;
+ H5I_type_t ret_value = H5I_BADID; /* Return value */
- FUNC_ENTER_API(H5Iget_type, H5I_BADID);
+ FUNC_ENTER_API(H5Iget_type, H5I_BADID)
H5TRACE1("It", "i", id);
ret_value = H5I_get_type(id);
- if (ret_value <= H5I_BADID || ret_value >= H5I_next_type || NULL==H5I_object(id))
+ if(ret_value <= H5I_BADID || ret_value >= H5I_next_type || NULL == H5I_object(id))
HGOTO_DONE(H5I_BADID);
done:
- FUNC_LEAVE_API(ret_value);
-}
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Iget_type() */
/*-------------------------------------------------------------------------
@@ -1108,21 +1129,22 @@ done:
*
*-------------------------------------------------------------------------
*/
-void *H5Iremove_verify(hid_t id, H5I_type_t id_type)
+void *
+H5Iremove_verify(hid_t id, H5I_type_t id_type)
{
- void * ret_value; /* Return value */
+ void * ret_value; /* Return value */
- FUNC_ENTER_API(H5Iremove_verify, NULL);
+ FUNC_ENTER_API(H5Iremove_verify, NULL)
- if( H5I_IS_LIB_TYPE( id_type ) )
- HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "cannot call public function on library type")
+ if(H5I_IS_LIB_TYPE(id_type))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "cannot call public function on library type")
- /* Remove the id */
- ret_value = H5I_remove_verify(id, id_type);
+ /* Remove the id */
+ ret_value = H5I_remove_verify(id, id_type);
- done:
- FUNC_LEAVE_API(ret_value);
-}
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Iremove_verify() */
/*-------------------------------------------------------------------------
@@ -1149,19 +1171,17 @@ H5I_remove_verify(hid_t id, H5I_type_t id_type)
{
void * ret_value = NULL; /*return value */
- FUNC_ENTER_NOAPI(H5I_remove_verify, NULL);
+ FUNC_ENTER_NOAPI(H5I_remove_verify, NULL)
- /* Argument checking will be performed by H5I_remove() */
+ /* Argument checking will be performed by H5I_remove() */
/* Verify that the type of the ID is correct */
if(id_type == H5I_TYPE(id))
- {
ret_value = H5I_remove(id);
- }
done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5I_remove_verify() */
@@ -1185,57 +1205,57 @@ done:
void *
H5I_remove(hid_t id)
{
- H5I_id_type_t *type_ptr = NULL;/*ptr to the atomic type */
+ H5I_id_type_t *type_ptr; /*ptr to the atomic type */
H5I_id_info_t *curr_id; /*ptr to the current atom */
H5I_id_info_t *last_id; /*ptr to the last atom */
H5I_type_t type; /*atom's atomic type */
unsigned hash_loc; /*atom's hash table location */
void * ret_value = NULL; /*return value */
- FUNC_ENTER_NOAPI(H5I_remove, NULL);
+ FUNC_ENTER_NOAPI(H5I_remove, NULL)
/* Check arguments */
type = H5I_TYPE(id);
- if (type <= H5I_BADID || type >= H5I_next_type)
- HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "invalid type number");
+ if(type <= H5I_BADID || type >= H5I_next_type)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "invalid type number")
type_ptr = H5I_id_type_list_g[type];
- if (type_ptr == NULL || type_ptr->count <= 0)
- HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "invalid type");
+ if(type_ptr == NULL || type_ptr->count <= 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "invalid type")
/* Get the bucket in which the ID is located */
- hash_loc = (unsigned) H5I_LOC(id, type_ptr->hash_size);
+ hash_loc = (unsigned)H5I_LOC(id, type_ptr->hash_size);
curr_id = type_ptr->id_list[hash_loc];
- if (curr_id == NULL)
- HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, NULL, "invalid ID");
+ if(NULL == curr_id)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, NULL, "invalid ID")
last_id = NULL;
- while (curr_id != NULL) {
- if (curr_id->id == id)
+ while(curr_id != NULL) {
+ if(curr_id->id == id)
break;
last_id = curr_id;
curr_id = curr_id->next;
- }
+ } /* end while */
- if (curr_id != NULL) {
- if (last_id == NULL) {
+ if(curr_id != NULL) {
+ if(last_id == NULL) {
/* ID is the first in the chain */
type_ptr->id_list[hash_loc] = curr_id->next;
} else {
last_id->next = curr_id->next;
}
ret_value = curr_id->obj_ptr;
- H5FL_FREE(H5I_id_info_t,curr_id);
+ (void)H5FL_FREE(H5I_id_info_t, curr_id);
} else {
/* couldn't find the ID in the proper place */
- HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, NULL, "invalid ID");
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, NULL, "invalid ID")
}
/* Decrement the number of IDs in the type */
(type_ptr->ids)--;
done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5I_remove() */
/*-------------------------------------------------------------------------
@@ -1260,19 +1280,19 @@ H5Idec_ref(hid_t id)
{
int ret_value; /* Return value */
- FUNC_ENTER_API(H5Idec_ref, FAIL);
+ FUNC_ENTER_API(H5Idec_ref, FAIL)
H5TRACE1("Is", "i", id);
/* Check arguments */
- if (id<0)
- HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "invalid ID");
+ if(id < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "invalid ID")
/* Do actual decrement operation */
- if((ret_value = H5I_dec_ref(id))<0)
- HGOTO_ERROR (H5E_ATOM, H5E_CANTDEC, FAIL, "can't decrement ID ref count");
+ if((ret_value = H5I_dec_ref(id, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTDEC, FAIL, "can't decrement ID ref count")
done:
- FUNC_LEAVE_API(ret_value);
+ FUNC_LEAVE_API(ret_value)
} /* end H5Idec_ref() */
@@ -1312,32 +1332,37 @@ done:
* count 1. This feature is needed by file close with H5F_CLOSE_SEMI
* value.
*
+ * Neil Fortner, 7 Aug 2008
+ * Added app_ref parameter and support for the app_count field, to
+ * distiguish between reference count from the library and from the
+ * application.
+ *
*-------------------------------------------------------------------------
*/
int
-H5I_dec_ref(hid_t id)
+H5I_dec_ref(hid_t id, hbool_t app_ref)
{
H5I_type_t type; /*type the object is in*/
H5I_id_type_t *type_ptr; /*ptr to the type */
H5I_id_info_t *id_ptr; /*ptr to the new ID */
int ret_value; /* Return value */
- FUNC_ENTER_NOAPI(H5I_dec_ref, FAIL);
+ FUNC_ENTER_NOAPI(H5I_dec_ref, FAIL)
/* Sanity check */
- assert(id>=0);
+ HDassert(id >= 0);
/* Check arguments */
type = H5I_TYPE(id);
- if (type <= H5I_BADID || type >= H5I_next_type)
- HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number");
+ if(type <= H5I_BADID || type >= H5I_next_type)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
type_ptr = H5I_id_type_list_g[type];
- if (type_ptr == NULL || type_ptr->count <= 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number");
+ if(NULL == type_ptr || type_ptr->count <= 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
/* General lookup of the ID */
- if ((id_ptr=H5I_find_id(id))==NULL)
- HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't locate ID");
+ if(NULL == (id_ptr=H5I_find_id(id)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't locate ID")
/*
* If this is the last reference to the object then invoke the type's
@@ -1349,20 +1374,24 @@ H5I_dec_ref(hid_t id)
*
* Beware: the free method may call other H5I functions.
*/
- if (1==id_ptr->count) {
- if (!type_ptr->free_func || (type_ptr->free_func)(id_ptr->obj_ptr)>=0) {
+ if(1 == id_ptr->count) {
+ if(!type_ptr->free_func || (type_ptr->free_func)(id_ptr->obj_ptr) >= 0) {
H5I_remove(id);
ret_value = 0;
} else {
ret_value = FAIL;
}
} else {
- ret_value = --(id_ptr->count);
+ --(id_ptr->count);
+ if (app_ref)
+ --(id_ptr->app_count);
+ HDassert(id_ptr->count >= id_ptr->app_count);
+ ret_value = app_ref ? id_ptr->app_count : id_ptr->count;
}
done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5I_dec_ref() */
/*-------------------------------------------------------------------------
@@ -1385,19 +1414,19 @@ H5Iinc_ref(hid_t id)
{
int ret_value; /* Return value */
- FUNC_ENTER_API(H5Iinc_ref, FAIL);
+ FUNC_ENTER_API(H5Iinc_ref, FAIL)
H5TRACE1("Is", "i", id);
/* Check arguments */
- if (id<0)
- HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "invalid ID");
+ if(id < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "invalid ID")
/* Do actual increment operation */
- if((ret_value = H5I_inc_ref(id))<0)
- HGOTO_ERROR (H5E_ATOM, H5E_CANTINC, FAIL, "can't increment ID ref count");
+ if((ret_value = H5I_inc_ref(id, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTINC, FAIL, "can't increment ID ref count")
done:
- FUNC_LEAVE_API(ret_value);
+ FUNC_LEAVE_API(ret_value)
} /* end H5Iinc_ref() */
@@ -1415,39 +1444,49 @@ done:
*
* Modifications:
*
+ * Neil Fortner, 7 Aug 2008
+ * Added app_ref parameter and support for the app_count field, to
+ * distiguish between reference count from the library and from the
+ * application.
+ *
*-------------------------------------------------------------------------
*/
int
-H5I_inc_ref(hid_t id)
+H5I_inc_ref(hid_t id, hbool_t app_ref)
{
H5I_type_t type; /*type the object is in*/
H5I_id_type_t *type_ptr; /*ptr to the type */
H5I_id_info_t *id_ptr; /*ptr to the ID */
int ret_value; /* Return value */
- FUNC_ENTER_NOAPI(H5I_inc_ref, FAIL);
+ FUNC_ENTER_NOAPI(H5I_inc_ref, FAIL)
/* Sanity check */
- assert(id>=0);
+ HDassert(id >= 0);
/* Check arguments */
type = H5I_TYPE(id);
- if (type <= H5I_BADID || type >= H5I_next_type)
- HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number");
+ if(type <= H5I_BADID || type >= H5I_next_type)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
type_ptr = H5I_id_type_list_g[type];
- if (!type_ptr || type_ptr->count<=0)
- HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type");
+ if(!type_ptr || type_ptr->count <= 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type")
/* General lookup of the ID */
- if (NULL==(id_ptr=H5I_find_id(id)))
- HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't locate ID");
+ if(NULL == (id_ptr = H5I_find_id(id)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't locate ID")
+
+ /* Adjust reference counts */
+ ++(id_ptr->count);
+ if (app_ref)
+ ++(id_ptr->app_count);
/* Set return value */
- ret_value=++(id_ptr->count);
+ ret_value = app_ref ? id_ptr->app_count : id_ptr->count;
done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5I_inc_ref() */
/*-------------------------------------------------------------------------
@@ -1470,19 +1509,19 @@ H5Iget_ref(hid_t id)
{
int ret_value; /* Return value */
- FUNC_ENTER_API(H5Iget_ref, FAIL);
+ FUNC_ENTER_API(H5Iget_ref, FAIL)
H5TRACE1("Is", "i", id);
/* Check arguments */
- if (id<0)
- HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "invalid ID");
+ if(id < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "invalid ID")
/* Do actual retrieve operation */
- if((ret_value = H5I_get_ref(id))<0)
- HGOTO_ERROR (H5E_ATOM, H5E_CANTGET, FAIL, "can't get ID ref count");
+ if((ret_value = H5I_get_ref(id, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't get ID ref count")
done:
- FUNC_LEAVE_API(ret_value);
+ FUNC_LEAVE_API(ret_value)
} /* end H5Iget_ref() */
@@ -1500,38 +1539,43 @@ done:
*
* Modifications:
*
+ * Neil Fortner, 7 Aug 2008
+ * Added app_ref parameter and support for the app_count field, to
+ * distiguish between reference count from the library and from the
+ * application.
+ *
*-------------------------------------------------------------------------
*/
int
-H5I_get_ref(hid_t id)
+H5I_get_ref(hid_t id, hbool_t app_ref)
{
H5I_type_t type; /*type the object is in*/
H5I_id_type_t *type_ptr; /*ptr to the type */
H5I_id_info_t *id_ptr; /*ptr to the ID */
int ret_value; /* Return value */
- FUNC_ENTER_NOAPI(H5I_get_ref, FAIL);
+ FUNC_ENTER_NOAPI(H5I_get_ref, FAIL)
/* Sanity check */
- assert(id>=0);
+ HDassert(id >= 0);
/* Check arguments */
type = H5I_TYPE(id);
- if (type <= H5I_BADID || type >= H5I_next_type)
- HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number");
+ if(type <= H5I_BADID || type >= H5I_next_type)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
type_ptr = H5I_id_type_list_g[type];
- if (!type_ptr || type_ptr->count<=0)
- HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type");
+ if(!type_ptr || type_ptr->count <= 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type")
/* General lookup of the ID */
- if (NULL==(id_ptr=H5I_find_id(id)))
- HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't locate ID");
+ if(NULL == (id_ptr = H5I_find_id(id)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't locate ID")
/* Set return value */
- ret_value=id_ptr->count;
+ ret_value = app_ref ? id_ptr->app_count : id_ptr->count;
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I_get_ref() */
@@ -1556,24 +1600,22 @@ H5Iinc_type_ref(H5I_type_t type)
{
int ret_value; /* Return value */
- FUNC_ENTER_API(H5Iinc_type_ref, FAIL);
+ FUNC_ENTER_API(H5Iinc_type_ref, FAIL)
H5TRACE1("Is", "It", type);
/* Check arguments */
- if (type<=0 || type >= H5I_next_type)
- HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "invalid ID type");
+ if(type <= 0 || type >= H5I_next_type)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "invalid ID type")
- if( H5I_IS_LIB_TYPE( type ) )
- {
- HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type");
- }
+ if(H5I_IS_LIB_TYPE(type))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type")
/* Do actual increment operation */
- if((ret_value = H5I_inc_type_ref(type))<0)
- HGOTO_ERROR (H5E_ATOM, H5E_CANTINC, FAIL, "can't increment ID type ref count");
+ if((ret_value = H5I_inc_type_ref(type)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTINC, FAIL, "can't increment ID type ref count")
done:
- FUNC_LEAVE_API(ret_value);
+ FUNC_LEAVE_API(ret_value)
} /* end H5Iinc_ref() */
@@ -1600,22 +1642,22 @@ H5I_inc_type_ref(H5I_type_t type)
H5I_id_type_t *type_ptr; /* ptr to the type */
int ret_value; /* Return value */
- FUNC_ENTER_NOAPI(H5I_inc_type_ref, FAIL);
+ FUNC_ENTER_NOAPI(H5I_inc_type_ref, FAIL)
/* Sanity check */
- assert(type>0 && type < H5I_next_type);
+ HDassert(type > 0 && type < H5I_next_type);
/* Check arguments */
type_ptr = H5I_id_type_list_g[type];
- if (!type_ptr )
- HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type");
+ if(!type_ptr)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type")
/* Set return value */
- ret_value=++(type_ptr->count);
+ ret_value = ++(type_ptr->count);
done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5I_inc_type_ref() */
/*-------------------------------------------------------------------------
@@ -1642,22 +1684,22 @@ done:
*
*-------------------------------------------------------------------------
*/
-herr_t H5Idec_type_ref(H5I_type_t type)
+herr_t
+H5Idec_type_ref(H5I_type_t type)
{
- herr_t ret_value;
+ herr_t ret_value; /* Return value */
- FUNC_ENTER_API(H5Idec_type_ref, FAIL);
+ FUNC_ENTER_API(H5Idec_type_ref, FAIL)
+ H5TRACE1("e", "It", type);
- if( H5I_IS_LIB_TYPE( type ) )
- {
- HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type");
- }
+ if(H5I_IS_LIB_TYPE(type))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type")
- ret_value = H5I_dec_type_ref(type);
+ ret_value = H5I_dec_type_ref(type);
- done:
- FUNC_LEAVE_API(ret_value);
-}
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Idec_type_ref() */
/*-------------------------------------------------------------------------
@@ -1688,38 +1730,36 @@ herr_t H5Idec_type_ref(H5I_type_t type)
herr_t
H5I_dec_type_ref(H5I_type_t type)
{
- H5I_id_type_t *type_ptr = NULL; /* ptr to the atomic type */
- herr_t ret_value = FAIL;
+ H5I_id_type_t *type_ptr; /* Pointer to the ID type */
+ herr_t ret_value; /* Return value */
- FUNC_ENTER_NOAPI(H5I_dec_type_ref, FAIL);
+ FUNC_ENTER_NOAPI(H5I_dec_type_ref, FAIL)
- if (type <= H5I_BADID || type >= H5I_next_type)
- HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number");
+ if(type <= H5I_BADID || type >= H5I_next_type)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid type number")
type_ptr = H5I_id_type_list_g[type];
- if (type_ptr == NULL || type_ptr->count <= 0)
- HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type");
+ if(type_ptr == NULL || type_ptr->count <= 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type")
/*
* Decrement the number of users of the atomic type. If this is the
* last user of the type then release all atoms from the type and
- * free all memory it used. The free function is invoked for each atom
- * being freed.
+ * free all memory it used. The free function is invoked for each atom
+ * being freed.
*/
- if (1==type_ptr->count)
- {
- H5I_destroy_type(type);
- ret_value = 0;
- }
- else
- {
+ if(1 == type_ptr->count) {
+ H5I_destroy_type(type);
+ ret_value = 0;
+ } /* end if */
+ else {
--(type_ptr->count);
- ret_value = type_ptr->count;
- }
+ ret_value = type_ptr->count;
+ } /* end else */
- done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5I_dec_type_ref() */
/*-------------------------------------------------------------------------
@@ -1743,24 +1783,22 @@ H5Iget_type_ref(H5I_type_t type)
{
int ret_value; /* Return value */
- FUNC_ENTER_API(H5Iget_type_ref, FAIL);
+ FUNC_ENTER_API(H5Iget_type_ref, FAIL)
H5TRACE1("Is", "It", type);
/* Check arguments */
- if (type<=0 || type >= H5I_next_type)
- HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "invalid ID type");
+ if(type <= 0 || type >= H5I_next_type)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "invalid ID type")
- if( H5I_IS_LIB_TYPE( type ) )
- {
- HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type");
- }
+ if(H5I_IS_LIB_TYPE(type))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "cannot call public function on library type")
/* Do actual retrieve operation */
- if((ret_value = H5I_get_type_ref(type))<0)
- HGOTO_ERROR (H5E_ATOM, H5E_CANTGET, FAIL, "can't get ID type ref count");
+ if((ret_value = H5I_get_type_ref(type)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't get ID type ref count")
done:
- FUNC_LEAVE_API(ret_value);
+ FUNC_LEAVE_API(ret_value)
} /* end H5Iget_ref() */
@@ -1787,22 +1825,70 @@ H5I_get_type_ref(H5I_type_t type)
H5I_id_type_t *type_ptr; /*ptr to the type */
int ret_value; /* Return value */
- FUNC_ENTER_NOAPI(H5I_get_type_ref, FAIL);
+ FUNC_ENTER_NOAPI(H5I_get_type_ref, FAIL)
/* Sanity check */
- assert(type>=0);
+ HDassert(type >= 0);
/* Check arguments */
type_ptr = H5I_id_type_list_g[type];
- if (!type_ptr )
- HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type");
+ if(!type_ptr)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type")
/* Set return value */
- ret_value=type_ptr->count;
+ ret_value = type_ptr->count;
done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5I_get_ref() */
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5I_get_type_ref() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Iis_valid
+ *
+ * Purpose: Check if the given id is valid. And id is valid if it is in
+ * use and has an application reference count of at least 1.
+ *
+ * Return: Success: TRUE if the id is valid, FALSE otherwise.
+ *
+ * Failure: Negative (never fails currently)
+ *
+ * Programmer: Neil Fortner
+ * Friday, October 31, 2008 (boo)
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5Iis_valid(hid_t id)
+{
+ H5I_id_type_t *type_ptr; /* ptr to ID's type */
+ H5I_id_info_t *id_ptr; /* ptr to the ID */
+ H5I_type_t type; /* ID's type */
+ htri_t ret_value = TRUE; /* Return value */
+
+ FUNC_ENTER_API(H5Iis_valid, FAIL)
+ H5TRACE1("t", "i", id);
+
+ type = H5I_TYPE(id);
+ /* Check for conditions that would cause H5I_find_id to throw an assertion */
+ if (type <= H5I_BADID || type >= H5I_next_type)
+ HGOTO_DONE(FALSE);
+
+ type_ptr = H5I_id_type_list_g[type];
+ if (!type_ptr || type_ptr->count <= 0)
+ ret_value = FALSE;
+
+ /* Find the ID */
+ else if (NULL == (id_ptr = H5I_find_id(id)))
+ ret_value = FALSE;
+
+ /* Check if the found id is an internal id */
+ else if (!id_ptr->app_count)
+ ret_value = FALSE;
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Iis_valid() */
/*-------------------------------------------------------------------------
@@ -1829,16 +1915,17 @@ done:
*
*-------------------------------------------------------------------------
*/
-void *H5Isearch(H5I_type_t type, H5I_search_func_t func, void *key)
+void *
+H5Isearch(H5I_type_t type, H5I_search_func_t func, void *key)
{
void * ret_value; /* Return value */
FUNC_ENTER_API(H5Isearch, NULL)
- if( H5I_IS_LIB_TYPE( type ) )
+ if(H5I_IS_LIB_TYPE(type))
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "cannot call public function on library type")
- ret_value = H5I_search(type, func, key);
+ ret_value = H5I_search(type, func, key, TRUE);
done:
FUNC_LEAVE_API(ret_value)
@@ -1866,36 +1953,40 @@ done:
* Programmer: Robb Matzke
* Friday, February 19, 1999
*
- * Modifications:
+ * Modifications: Neil Fortner
+ * Wednesday, October 1, 2008
+ * Added app_ref parameter. When set to TRUE, the function will only
+ * operate on ids that have a nonzero application reference count.
*
*-------------------------------------------------------------------------
*/
void *
-H5I_search(H5I_type_t type, H5I_search_func_t func, void *key)
+H5I_search(H5I_type_t type, H5I_search_func_t func, void *key, hbool_t app_ref)
{
- H5I_id_type_t *type_ptr = NULL; /*ptr to the type */
- H5I_id_info_t *id_ptr = NULL; /*ptr to the new ID */
- H5I_id_info_t *next_id = NULL; /*ptr to the next ID */
- unsigned i; /*counter */
+ H5I_id_type_t *type_ptr; /*ptr to the type */
void *ret_value = NULL; /*return value */
- FUNC_ENTER_NOAPI(H5I_search, NULL);
+ FUNC_ENTER_NOAPI(H5I_search, NULL)
/* Check arguments */
- if (type <= H5I_BADID || type >= H5I_next_type)
- HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "invalid type number");
+ if(type <= H5I_BADID || type >= H5I_next_type)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "invalid type number")
type_ptr = H5I_id_type_list_g[type];
- if (type_ptr == NULL || type_ptr->count <= 0)
- HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "invalid type");
+ if(type_ptr == NULL || type_ptr->count <= 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, NULL, "invalid type")
/* Only iterate through hash table if there are IDs in group */
if(type_ptr->ids > 0) {
+ H5I_id_info_t *id_ptr; /*ptr to the new ID */
+ H5I_id_info_t *next_id; /*ptr to the next ID */
+ unsigned i; /*counter */
+
/* Start at the beginning of the array */
- for (i=0; i<type_ptr->hash_size; i++) {
+ for(i = 0; i < type_ptr->hash_size; i++) {
id_ptr = type_ptr->id_list[i];
- while (id_ptr) {
- next_id= id_ptr->next; /* Protect against ID being deleted in callback */
- if ((*func)(id_ptr->obj_ptr, id_ptr->id, key))
+ while(id_ptr) {
+ next_id = id_ptr->next; /* Protect against ID being deleted in callback */
+ if((!app_ref || id_ptr->app_count) && (*func)(id_ptr->obj_ptr, id_ptr->id, key))
HGOTO_DONE(id_ptr->obj_ptr); /*found the item*/
id_ptr = next_id;
} /* end while */
@@ -1903,7 +1994,7 @@ H5I_search(H5I_type_t type, H5I_search_func_t func, void *key)
} /* end if */
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I_search() */
@@ -1931,42 +2022,42 @@ H5I_find_id(hid_t id)
H5I_id_info_t *id_ptr; /*ptr to the new ID */
H5I_type_t type; /*ID's type */
unsigned hash_loc; /*bucket pointer */
- H5I_id_info_t *ret_value = NULL; /*return value */
+ H5I_id_info_t *ret_value; /*return value */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5I_find_id);
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5I_find_id)
/* Check arguments */
type = H5I_TYPE(id);
- assert(type > H5I_BADID && type < H5I_next_type);
+ HDassert(type > H5I_BADID && type < H5I_next_type);
type_ptr = H5I_id_type_list_g[type];
- assert(type_ptr && type_ptr->count > 0);
+ HDassert(type_ptr && type_ptr->count > 0);
/* Get the bucket in which the ID is located */
hash_loc = (unsigned)H5I_LOC(id, type_ptr->hash_size);
id_ptr = type_ptr->id_list[hash_loc];
/* Scan the bucket's linked list for a match */
- last_id=NULL;
- while (id_ptr) {
- if (id_ptr->id == id) {
+ last_id = NULL;
+ while(id_ptr) {
+ if(id_ptr->id == id) {
/* If we found an object, move it to the front of the list, if it isn't there already */
- if(last_id!=NULL) {
- last_id->next=id_ptr->next;
- id_ptr->next=type_ptr->id_list[hash_loc];
- type_ptr->id_list[hash_loc]=id_ptr;
+ if(last_id != NULL) {
+ last_id->next = id_ptr->next;
+ id_ptr->next = type_ptr->id_list[hash_loc];
+ type_ptr->id_list[hash_loc] = id_ptr;
} /* end if */
break;
} /* end if */
- last_id=id_ptr;
+ last_id = id_ptr;
id_ptr = id_ptr->next;
} /* end while */
/* Set the return value */
ret_value = id_ptr;
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5I_find_id() */
/*-------------------------------------------------------------------------
@@ -2031,17 +2122,17 @@ done:
hid_t
H5Iget_file_id(hid_t obj_id)
{
- hid_t ret_value;
+ hid_t ret_value; /* Return value */
- FUNC_ENTER_API(H5Iget_file_id, FAIL);
+ FUNC_ENTER_API(H5Iget_file_id, FAIL)
H5TRACE1("i", "i", obj_id);
- if((ret_value = H5I_get_file_id(obj_id))<0)
- HGOTO_ERROR (H5E_ATOM, H5E_CANTGET, FAIL, "can't retrieve file ID");
+ if((ret_value = H5I_get_file_id(obj_id, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't retrieve file ID")
done:
- FUNC_LEAVE_API(ret_value);
-}
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Iget_file_id() */
/*-------------------------------------------------------------------------
@@ -2060,7 +2151,7 @@ done:
*-------------------------------------------------------------------------
*/
hid_t
-H5I_get_file_id(hid_t obj_id)
+H5I_get_file_id(hid_t obj_id, hbool_t app_ref)
{
H5G_loc_t loc; /* Location of object */
H5I_type_t type; /* ID type */
@@ -2074,13 +2165,13 @@ H5I_get_file_id(hid_t obj_id)
ret_value = obj_id;
/* Increment reference count on atom. */
- if(H5I_inc_ref(ret_value) < 0)
+ if(H5I_inc_ref(ret_value, app_ref) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTSET, FAIL, "incrementing file ID failed")
}
else if(type == H5I_DATATYPE || type == H5I_GROUP || type == H5I_DATASET || type == H5I_ATTR) {
if(H5G_loc(obj_id, &loc) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't get object location")
- if((ret_value = H5F_get_id(loc.oloc->file)) < 0)
+ if((ret_value = H5F_get_id(loc.oloc->file, app_ref)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't get file ID")
}
else
@@ -2121,7 +2212,7 @@ H5I_debug(H5I_type_t type)
unsigned int iu;
herr_t ret_value; /* Return value */
- FUNC_ENTER_NOAPI(H5I_debug, FAIL);
+ FUNC_ENTER_NOAPI(H5I_debug, FAIL)
fprintf(stderr, "Dumping ID type %d\n", (int)type);
type_ptr = H5I_id_type_list_g[type];
@@ -2177,7 +2268,7 @@ H5I_debug(H5I_type_t type)
} /* end for */
done:
- FUNC_LEAVE_NOAPI(SUCCEED);
-}
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5I_debug() */
#endif /* H5I_DEBUG_OUTPUT */
diff --git a/src/H5Iprivate.h b/src/H5Iprivate.h
index 42575e4..0923af7 100644
--- a/src/H5Iprivate.h
+++ b/src/H5Iprivate.h
@@ -52,19 +52,19 @@
/* Private Functions in H5I.c */
H5_DLL H5I_type_t H5I_register_type(H5I_type_t type_id, size_t hash_size, unsigned reserved, H5I_free_t free_func);
H5_DLL int H5I_nmembers(H5I_type_t type);
-H5_DLL herr_t H5I_clear_type(H5I_type_t type, hbool_t force);
+H5_DLL herr_t H5I_clear_type(H5I_type_t type, hbool_t force, hbool_t app_ref);
H5_DLL int H5I_destroy_type(H5I_type_t type);
-H5_DLL hid_t H5I_register(H5I_type_t type, void *object);
+H5_DLL hid_t H5I_register(H5I_type_t type, void *object, hbool_t app_ref);
H5_DLL void *H5I_object(hid_t id);
H5_DLL void *H5I_object_verify(hid_t id, H5I_type_t id_type);
H5_DLL H5I_type_t H5I_get_type(hid_t id);
-H5_DLL hid_t H5I_get_file_id(hid_t);
+H5_DLL hid_t H5I_get_file_id(hid_t obj_id, hbool_t app_ref);
H5_DLL void *H5I_remove(hid_t id);
H5_DLL void *H5I_remove_verify(hid_t id, H5I_type_t id_type);
-H5_DLL void *H5I_search(H5I_type_t type, H5I_search_func_t func, void *key);
-H5_DLL int H5I_get_ref(hid_t id);
-H5_DLL int H5I_inc_ref(hid_t id);
-H5_DLL int H5I_dec_ref(hid_t id);
+H5_DLL void *H5I_search(H5I_type_t type, H5I_search_func_t func, void *key, hbool_t app_ref);
+H5_DLL int H5I_get_ref(hid_t id, hbool_t app_ref);
+H5_DLL int H5I_inc_ref(hid_t id, hbool_t app_ref);
+H5_DLL int H5I_dec_ref(hid_t id, hbool_t app_ref);
H5_DLL int H5I_inc_type_ref(H5I_type_t type);
H5_DLL herr_t H5I_dec_type_ref(H5I_type_t type);
H5_DLL int H5I_get_type_ref(H5I_type_t type);
diff --git a/src/H5Ipublic.h b/src/H5Ipublic.h
index 108f040..608bc9c 100644
--- a/src/H5Ipublic.h
+++ b/src/H5Ipublic.h
@@ -95,6 +95,7 @@ H5_DLL int H5Iget_type_ref(H5I_type_t type);
H5_DLL void *H5Isearch(H5I_type_t type, H5I_search_func_t func, void *key);
H5_DLL herr_t H5Inmembers(H5I_type_t type, hsize_t *num_members);
H5_DLL htri_t H5Itype_exists(H5I_type_t type);
+H5_DLL htri_t H5Iis_valid(hid_t id);
#ifdef __cplusplus
}
diff --git a/src/H5L.c b/src/H5L.c
index 020f7c2..4ad2f2d 100644
--- a/src/H5L.c
+++ b/src/H5L.c
@@ -151,7 +151,7 @@ static herr_t H5L_link_cb(H5G_loc_t *grp_loc/*in*/, const char *name,
const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/,
H5G_own_loc_t *own_loc/*out*/);
static herr_t H5L_create_real(const H5G_loc_t *link_loc, const char *link_name,
- H5G_name_t *obj_path, H5F_t *obj_file, H5O_link_t *lnk, H5O_obj_create_t *ocrt_info,
+ H5G_name_t *obj_path, H5F_t *obj_file, H5O_link_t *lnk, H5O_obj_create_t *ocrt_info,
hid_t lcpl_id, hid_t lapl_id, hid_t dxpl_id);
static herr_t H5L_get_val_real(const H5O_link_t *lnk, void *buf, size_t size);
static herr_t H5L_get_val_cb(H5G_loc_t *grp_loc/*in*/, const char *name,
@@ -345,7 +345,7 @@ H5Lmove(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id,
lapl_id, H5AC_dxpl_id) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTMOVE, FAIL, "unable to move link")
-done:
+done:
FUNC_LEAVE_API(ret_value)
} /* end H5Lmove() */
@@ -403,7 +403,7 @@ H5Lcopy(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id,
lapl_id, H5AC_dxpl_id) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTMOVE, FAIL, "unable to move link")
-done:
+done:
FUNC_LEAVE_API(ret_value)
} /* end H5Lcopy() */
@@ -1170,11 +1170,11 @@ H5Literate(hid_t grp_id, H5_index_t idx_type, H5_iter_order_t order,
last_lnk = 0;
/* Build link operator info */
- lnk_op.op_type = H5G_LINK_OP_APP;
- lnk_op.u.app_op = op;
+ lnk_op.op_type = H5G_LINK_OP_NEW;
+ lnk_op.op_func.op_new = op;
/* Iterate over the links */
- if((ret_value = H5G_obj_iterate(grp_id, ".", idx_type, order, idx, &last_lnk, &lnk_op, op_data, H5P_DEFAULT, H5AC_ind_dxpl_id)) < 0)
+ if((ret_value = H5G_iterate(grp_id, ".", idx_type, order, idx, &last_lnk, &lnk_op, op_data, H5P_DEFAULT, H5AC_ind_dxpl_id)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "link iteration failed")
/* Set the index we stopped at */
@@ -1242,11 +1242,11 @@ H5Literate_by_name(hid_t loc_id, const char *group_name,
last_lnk = 0;
/* Build link operator info */
- lnk_op.op_type = H5G_LINK_OP_APP;
- lnk_op.u.app_op = op;
+ lnk_op.op_type = H5G_LINK_OP_NEW;
+ lnk_op.op_func.op_new = op;
/* Iterate over the links */
- if((ret_value = H5G_obj_iterate(loc_id, group_name, idx_type, order, idx, &last_lnk, &lnk_op, op_data, lapl_id, H5AC_ind_dxpl_id)) < 0)
+ if((ret_value = H5G_iterate(loc_id, group_name, idx_type, order, idx, &last_lnk, &lnk_op, op_data, lapl_id, H5AC_ind_dxpl_id)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "link iteration failed")
/* Set the index we stopped at */
@@ -1257,6 +1257,126 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Literate_by_name() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5Lvisit
+ *
+ * Purpose: Recursively visit all the links in a group and all
+ * the groups that are linked to from that group. Links within
+ * each group are visited according to the order within the
+ * specified index (unless the specified index does not exist for
+ * a particular group, then the "name" index is used).
+ *
+ * NOTE: Each _link_ reachable from the initial group will only be
+ * visited once. However, because an object may be reached from
+ * more than one link, the visitation may call the application's
+ * callback with more than one link that points to a particular
+ * _object_.
+ *
+ * Return: Success: The return value of the first operator that
+ * returns non-zero, or zero if all members were
+ * processed with no operator returning non-zero.
+ *
+ * Failure: Negative if something goes wrong within the
+ * library, or the negative value returned by one
+ * of the operators.
+ *
+ * Programmer: Quincey Koziol
+ * November 24 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Lvisit(hid_t grp_id, H5_index_t idx_type, H5_iter_order_t order,
+ H5L_iterate_t op, void *op_data)
+{
+ H5I_type_t id_type; /* Type of ID */
+ herr_t ret_value; /* Return value */
+
+ FUNC_ENTER_API(H5Lvisit, FAIL)
+ H5TRACE5("e", "iIiIox*x", grp_id, idx_type, order, op, op_data);
+
+ /* Check args */
+ id_type = H5I_get_type(grp_id);
+ if(!(H5I_GROUP == id_type || H5I_FILE == id_type))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid argument")
+ if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified")
+ if(order <= H5_ITER_UNKNOWN || order >= H5_ITER_N)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified")
+ if(!op)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no callback operator specified")
+
+ /* Call internal group visitation routine */
+ if((ret_value = H5G_visit(grp_id, ".", idx_type, order, op, op_data, H5P_DEFAULT, H5AC_ind_dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "link visitation failed")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Lvisit() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Lvisit_by_name
+ *
+ * Purpose: Recursively visit all the links in a group and all
+ * the groups that are linked to from that group. Links within
+ * each group are visited according to the order within the
+ * specified index (unless the specified index does not exist for
+ * a particular group, then the "name" index is used).
+ *
+ * NOTE: Each _link_ reachable from the initial group will only be
+ * visited once. However, because an object may be reached from
+ * more than one link, the visitation may call the application's
+ * callback with more than one link that points to a particular
+ * _object_.
+ *
+ * Return: Success: The return value of the first operator that
+ * returns non-zero, or zero if all members were
+ * processed with no operator returning non-zero.
+ *
+ * Failure: Negative if something goes wrong within the
+ * library, or the negative value returned by one
+ * of the operators.
+ *
+ * Programmer: Quincey Koziol
+ * November 3 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Lvisit_by_name(hid_t loc_id, const char *group_name, H5_index_t idx_type,
+ H5_iter_order_t order, H5L_iterate_t op, void *op_data, hid_t lapl_id)
+{
+ herr_t ret_value; /* Return value */
+
+ FUNC_ENTER_API(H5Lvisit_by_name, FAIL)
+ H5TRACE7("e", "i*sIiIox*xi", loc_id, group_name, idx_type, order, op, op_data,
+ lapl_id);
+
+ /* Check args */
+ if(!group_name || !*group_name)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified")
+ if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified")
+ if(order <= H5_ITER_UNKNOWN || order >= H5_ITER_N)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified")
+ if(!op)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no callback operator specified")
+ if(H5P_DEFAULT == lapl_id)
+ lapl_id = H5P_LINK_ACCESS_DEFAULT;
+ else
+ if(TRUE != H5P_isa_class(lapl_id, H5P_LINK_ACCESS))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link access property list ID")
+
+ /* Call internal group visitation routine */
+ if((ret_value = H5G_visit(loc_id, group_name, idx_type, order, op, op_data, lapl_id, H5AC_ind_dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "link visitation failed")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Lvisit_by_name() */
+
/*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
@@ -1466,7 +1586,7 @@ H5L_link(const H5G_loc_t *new_loc, const char *new_name, H5G_loc_t *obj_loc,
lnk.u.hard.addr = obj_loc->oloc->addr;
/* Create the link */
- if(H5L_create_real(new_loc, new_name, obj_loc->path, obj_loc->oloc->file, &lnk, NULL, lcpl_id, lapl_id, dxpl_id) < 0)
+ if(H5L_create_real(new_loc, new_name, obj_loc->path, obj_loc->oloc->file, &lnk, NULL, lcpl_id, lapl_id, dxpl_id) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "unable to create new link to object")
done:
@@ -1509,7 +1629,7 @@ H5L_link_object(const H5G_loc_t *new_loc, const char *new_name,
lnk.type = H5L_TYPE_HARD;
/* Create the link */
- if(H5L_create_real(new_loc, new_name, NULL, NULL, &lnk, ocrt_info, lcpl_id, lapl_id, dxpl_id) < 0)
+ if(H5L_create_real(new_loc, new_name, NULL, NULL, &lnk, ocrt_info, lcpl_id, lapl_id, dxpl_id) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "unable to create new link to object")
done:
@@ -1623,7 +1743,7 @@ H5L_link_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t UNUSED
/* Set up location for user-defined callback */
if((grp = H5G_open(&temp_loc, udata->dxpl_id)) == NULL)
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group")
- if((grp_id = H5I_register(H5I_GROUP, grp)) < 0)
+ if((grp_id = H5I_register(H5I_GROUP, grp, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register ID for group")
/* Make callback */
@@ -1635,7 +1755,7 @@ H5L_link_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t UNUSED
done:
/* Close the location given to the user callback if it was created */
if(grp_id >= 0) {
- if(H5I_dec_ref(grp_id) < 0)
+ if(H5I_dec_ref(grp_id, TRUE) < 0)
HDONE_ERROR(H5E_ATOM, H5E_CANTRELEASE, FAIL, "unable to close atom from UD callback")
} /* end if */
else if(grp != NULL) {
@@ -1928,7 +2048,7 @@ done:
/*-------------------------------------------------------------------------
* Function: H5L_get_val_real
*
- * Purpose: Retrieve link value from a link object
+ * Purpose: Retrieve link value from a link object
*
* Return: Non-negative on success/Negative on failure
*
@@ -1951,7 +2071,7 @@ H5L_get_val_real(const H5O_link_t *lnk, void *buf, size_t size)
if(H5L_TYPE_SOFT == lnk->type) {
/* Copy to output buffer */
if(size > 0 && buf) {
- HDstrncpy(buf, lnk->u.soft.name, size);
+ HDstrncpy((char *)buf, lnk->u.soft.name, size);
if(HDstrlen(lnk->u.soft.name) >= size)
((char *)buf)[size - 1] = '\0';
} /* end if */
@@ -1960,7 +2080,7 @@ H5L_get_val_real(const H5O_link_t *lnk, void *buf, size_t size)
else if(lnk->type >= H5L_TYPE_UD_MIN) {
const H5L_class_t *link_class; /* User-defined link class */
- /* Get the link class for this type of link. It's okay if the class
+ /* Get the link class for this type of link. It's okay if the class
* isn't registered, though--we just can't give any more information
* about it
*/
@@ -2320,7 +2440,7 @@ H5L_move_dest_cb(H5G_loc_t *grp_loc/*in*/, const char *name,
/* Set up location for user-defined callback */
if((grp = H5G_open(&temp_loc, udata->dxpl_id)) == NULL)
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group")
- if((grp_id = H5I_register(H5I_GROUP, grp)) < 0)
+ if((grp_id = H5I_register(H5I_GROUP, grp, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register group ID")
if(udata->copy) {
@@ -2337,7 +2457,7 @@ H5L_move_dest_cb(H5G_loc_t *grp_loc/*in*/, const char *name,
done:
/* Close the location given to the user callback if it was created */
if(grp_id >= 0) {
- if(H5I_dec_ref(grp_id) < 0)
+ if(H5I_dec_ref(grp_id, TRUE) < 0)
HDONE_ERROR(H5E_ATOM, H5E_CANTRELEASE, FAIL, "unable to close atom from UD callback")
} /* end if */
else if(grp != NULL) {
@@ -2537,7 +2657,7 @@ H5L_move(H5G_loc_t *src_loc, const char *src_name, H5G_loc_t *dst_loc,
else {
if(NULL == (la_plist = (H5P_genplist_t *)H5I_object(lapl_id)))
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a valid access PL")
- if((lapl_copy = H5P_copy_plist(la_plist)) < 0)
+ if((lapl_copy = H5P_copy_plist(la_plist, FALSE)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "unable to copy access properties")
} /* end else */
@@ -2551,7 +2671,7 @@ H5L_move(H5G_loc_t *src_loc, const char *src_name, H5G_loc_t *dst_loc,
/* Do the move */
if(H5G_traverse(src_loc, src_name, target_flags, H5L_move_cb, &udata, lapl_id, dxpl_id) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to find link")
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to find link")
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5Lexternal.c b/src/H5Lexternal.c
index 5a8eb33..46ed467 100644
--- a/src/H5Lexternal.c
+++ b/src/H5Lexternal.c
@@ -76,6 +76,81 @@ H5L_init_extern_interface(void)
} /* H5L_init_extern_interface() */
+
+/*--------------------------------------------------------------------------
+ * Function: H5L_getenv_prefix_name --
+ *
+ * Purpose: Get the first pathname in the list of pathnames stored in ENV_PREFIX,
+ * which is separated by the environment delimiter.
+ * ENV_PREFIX is modified to point to the remaining pathnames
+ * in the list.
+ *
+ * Return: A pointer to a pathname
+ *
+ * Programmer: Vailin Choi, April 2, 2008
+ *
+--------------------------------------------------------------------------*/
+static char *
+H5L_getenv_prefix_name(char **env_prefix/*in,out*/)
+{
+ char *retptr=NULL;
+ char *strret=NULL;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5L_getenv_prefix_name)
+
+ strret = HDstrchr(*env_prefix, COLON_SEPC);
+ if (strret == NULL) {
+ retptr = *env_prefix;
+ *env_prefix = strret;
+ } else {
+ retptr = *env_prefix;
+ *env_prefix = strret + 1;
+ *strret = '\0';
+ }
+
+ FUNC_LEAVE_NOAPI(retptr)
+} /* end H5L_getenv_prefix_name() */
+
+
+/*--------------------------------------------------------------------------
+ * Function: H5L_build_name
+ *
+ * Purpose: Prepend PREFIX to FILE_NAME and store in FULL_NAME
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Vailin Choi, April 2, 2008
+ *
+--------------------------------------------------------------------------*/
+static herr_t
+H5L_build_name(char *prefix, char *file_name, char **full_name/*out*/)
+{
+ size_t prefix_len; /* length of prefix */
+ size_t fname_len; /* Length of external link file name */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5L_build_name)
+
+ prefix_len = HDstrlen(prefix);
+ fname_len = HDstrlen(file_name);
+
+ /* Allocate a buffer to hold the filename + prefix + possibly the delimiter + terminating null byte */
+ if(NULL == (*full_name = (char *)H5MM_malloc(prefix_len + fname_len + 2)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate filename buffer")
+
+ /* Copy the prefix into the buffer */
+ HDstrcpy(*full_name, prefix);
+ if (!CHECK_DELIMITER(prefix[prefix_len-1]))
+ HDstrcat(*full_name, DIR_SEPS);
+
+ /* Add the external link's filename to the prefix supplied */
+ HDstrcat(*full_name, file_name);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5L_build_name() */
+
+
/*-------------------------------------------------------------------------
* Function: H5L_extern_traverse
*
@@ -92,6 +167,18 @@ H5L_init_extern_interface(void)
*
* Programmer: James Laird
* Monday, July 10, 2006
+ * Modifications:
+ * Vailin Choi, April 2, 2008
+ * Add handling to search for the target file
+ * See description in RM: H5Lcreate_external
+ *
+ * Vailin Choi; Sept. 12th, 2008; bug #1247
+ * Retrieve the file access property list identifer that is set
+ * for link access property via H5Pget_elink_fapl().
+ * If the return value is H5P_DEFAULT, the parent's file access
+ * property is used to H5F_open() the target file;
+ * Otherwise, the file access property retrieved from H5Pget_elink_fapl()
+ * is used to H5F_open() the target file.
*
*-------------------------------------------------------------------------
*/
@@ -114,6 +201,13 @@ H5L_extern_traverse(const char UNUSED *link_name, hid_t cur_group,
hid_t ext_obj = -1; /* ID for external link's object */
hid_t ret_value; /* Return value */
+ char *tempname=NULL, *ptr=NULL, *extpath=NULL;
+ char *env_prefix=NULL, *tmp_env_prefix=NULL;
+ char *out_prefix_name=NULL, *pp=NULL;
+
+ H5P_genplist_t *fa_plist; /* File access property list pointer */
+ H5F_close_degree_t fc_degree = H5F_CLOSE_WEAK; /* File close degree for target file */
+
FUNC_ENTER_NOAPI(H5L_extern_traverse, FAIL)
/* Sanity checks */
@@ -135,58 +229,112 @@ H5L_extern_traverse(const char UNUSED *link_name, hid_t cur_group,
if(NULL == (plist = H5P_object_verify(lapl_id, H5P_LINK_ACCESS)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
- /* Get the current prefix */
- if(H5P_get(plist, H5L_ACS_ELINK_PREFIX_NAME, &my_prefix) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get external link prefix")
-
- /* Check for prefix being set, if so, prepend it to the filename */
- if(my_prefix) {
- size_t prefix_len = HDstrlen(my_prefix);
-
- /* Allocate a buffer to hold the filename plus prefix */
- if(NULL == (full_name = H5MM_malloc(prefix_len + fname_len + 1)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate filename buffer")
-
- /* Copy the prefix into the buffer */
- HDstrcpy(full_name, my_prefix);
-
- /* Add the external link's filename to the prefix supplied */
- HDstrcat(full_name, (const char *)p);
-
- /* Point to name w/prefix */
- file_name = full_name;
- } /* end if */
+ /* get the fapl_id set for lapl_id if any */
+ if(H5P_get(plist, H5L_ACS_ELINK_FAPL_NAME, &fapl_id) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get fapl for links")
/* Get the location for the group holding the external link */
if(H5G_loc(cur_group, &loc) < 0)
HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't get object location")
- /* Whatever access properties and intent the user used on the old file,
- * use the same ones to open the new file. If this is a bad default,
- * users can override this callback using H5Lregister.
- */
+ /* get the file access mode flags for the parent file */
intent = H5F_INTENT(loc.oloc->file);
- if((fapl_id = H5F_get_access_plist(loc.oloc->file)) < 0)
- HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't get file access property list")
-
- /* Check for non-"weak" file close degree for parent file */
- if(H5F_GET_FC_DEGREE(loc.oloc->file) != H5F_CLOSE_WEAK) {
- H5P_genplist_t *fa_plist; /* Property list pointer */
- H5F_close_degree_t fc_degree = H5F_CLOSE_WEAK; /* File close degree */
- /* Get the plist structure */
- if(NULL == (fa_plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS)))
- HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
+ if ((fapl_id == H5P_DEFAULT) && ((fapl_id = H5F_get_access_plist(loc.oloc->file, FALSE)) < 0))
+ HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't get parent's file access property list")
- /* Set file close degree for new file to "weak" */
- if(H5P_set(fa_plist, H5F_ACS_CLOSE_DEGREE_NAME, &fc_degree) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file close degree")
- } /* end if */
+ /* Set file close degree for new file to "weak" */
+ if(NULL == (fa_plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
+ if(H5P_set(fa_plist, H5F_ACS_CLOSE_DEGREE_NAME, &fc_degree) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file close degree")
- /* Open the external file */
- /* (extra work with file intent to mask off inappropriate flags) */
- if(NULL == (ext_file = H5F_open(file_name, ((intent & H5F_ACC_RDWR) ? H5F_ACC_RDWR : H5F_ACC_RDONLY), H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id)))
- HGOTO_ERROR(H5E_LINK, H5E_CANTOPENFILE, FAIL, "unable to open external file")
+ /*
+ * Start searching for the target file
+ */
+ if ((tempname=H5MM_strdup(file_name)) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* target file_name is an absolute pathname: see RM for detailed description */
+ if (CHECK_ABSOLUTE(file_name) || CHECK_ABS_PATH(file_name)) {
+ if(NULL == (ext_file = H5F_open(file_name, ((intent & H5F_ACC_RDWR) ? H5F_ACC_RDWR : H5F_ACC_RDONLY),
+ H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id))) {
+ H5E_clear_stack(NULL);
+ /* get last component of file_name */
+ GET_LAST_DELIMITER(file_name, ptr)
+ HDassert(ptr);
+ HDstrcpy(tempname, ++ptr);
+ }
+ } else if (CHECK_ABS_DRIVE(file_name)) {
+ if(NULL == (ext_file = H5F_open(file_name, ((intent & H5F_ACC_RDWR) ? H5F_ACC_RDWR : H5F_ACC_RDONLY),
+ H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id))) {
+ H5E_clear_stack(NULL);
+ /* strip "<drive-letter>:" */
+ HDstrcpy(tempname, &file_name[2]);
+ }
+ }
+
+ /* try searching from paths set in the environment variable */
+ if ((ext_file == NULL) && (env_prefix=HDgetenv("HDF5_EXT_PREFIX"))) {
+
+ tmp_env_prefix = H5MM_strdup(env_prefix);
+ pp = tmp_env_prefix;
+
+ while ((tmp_env_prefix) && (*tmp_env_prefix)) {
+ out_prefix_name = H5L_getenv_prefix_name(&tmp_env_prefix/*in,out*/);
+ if ((out_prefix_name) && (*out_prefix_name)) {
+
+ if (H5L_build_name(out_prefix_name, tempname, &full_name/*out*/) < 0)
+ HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't prepend prefix to filename")
+
+ ext_file = H5F_open(full_name, ((intent & H5F_ACC_RDWR) ? H5F_ACC_RDWR : H5F_ACC_RDONLY),
+ H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id);
+ if (full_name)
+ H5MM_xfree(full_name);
+ if (ext_file != NULL)
+ break;
+ H5E_clear_stack(NULL);
+ }
+ } /* end while */
+ if (pp)
+ H5MM_xfree(pp);
+ }
+
+ /* try searching from property list */
+ if (ext_file == NULL) {
+ if(H5P_get(plist, H5L_ACS_ELINK_PREFIX_NAME, &my_prefix) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get external link prefix")
+ if (my_prefix) {
+ if (H5L_build_name(my_prefix, tempname, &full_name/*out*/) < 0)
+ HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't prepend prefix to filename")
+ if ((ext_file=H5F_open(full_name, ((intent & H5F_ACC_RDWR) ? H5F_ACC_RDWR : H5F_ACC_RDONLY),
+ H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id)) == NULL)
+ H5E_clear_stack(NULL);
+ if (full_name)
+ H5MM_xfree(full_name);
+ }
+ }
+
+ /* try searching from main file's "extpath":see description in H5F_open() & H5_build_extpath() */
+ if ((ext_file == NULL) && (extpath=H5F_EXTPATH(loc.oloc->file))) {
+ if (H5L_build_name(extpath, tempname, &full_name/*out*/) < 0)
+ HGOTO_ERROR(H5E_LINK, H5E_CANTGET, FAIL, "can't prepend prefix to filename")
+ if ((ext_file = H5F_open(full_name, ((intent & H5F_ACC_RDWR) ? H5F_ACC_RDWR : H5F_ACC_RDONLY),
+ H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id)) == NULL)
+ H5E_clear_stack(NULL);
+ if (full_name)
+ H5MM_xfree(full_name);
+ }
+
+ /* try the relative file_name stored in tempname */
+ if (ext_file == NULL) {
+ if ((ext_file=H5F_open(tempname, ((intent & H5F_ACC_RDWR) ? H5F_ACC_RDWR : H5F_ACC_RDONLY),
+ H5P_FILE_CREATE_DEFAULT, fapl_id, H5AC_dxpl_id)) == NULL)
+ HGOTO_ERROR(H5E_LINK, H5E_CANTOPENFILE, FAIL, "unable to open external file")
+ }
+
+ if (tempname)
+ H5MM_xfree(tempname);
/* Increment the number of open objects, to hold the file open */
H5F_incr_nopen_objs(ext_file);
@@ -196,7 +344,7 @@ H5L_extern_traverse(const char UNUSED *link_name, hid_t cur_group,
HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "unable to create location for file")
/* Open the object referenced in the external file */
- if((ext_obj = H5O_open_name(&root_loc, obj_name, lapl_id)) < 0) {
+ if((ext_obj = H5O_open_name(&root_loc, obj_name, lapl_id, FALSE)) < 0) {
H5F_decr_nopen_objs(ext_file);
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open object")
} /* end if */
@@ -214,17 +362,13 @@ H5L_extern_traverse(const char UNUSED *link_name, hid_t cur_group,
done:
/* Release resources */
- if(fapl_id > 0 && H5I_dec_ref(fapl_id) < 0)
+ if(fapl_id > 0 && H5I_dec_ref(fapl_id, FALSE) < 0)
HDONE_ERROR(H5E_ATOM, H5E_CANTRELEASE, FAIL, "unable to close atom for file access property list")
if(ext_file && H5F_try_close(ext_file) < 0)
HDONE_ERROR(H5E_LINK, H5E_CANTCLOSEFILE, FAIL, "problem closing external file")
- /* Free full_name if it's been allocated */
- if(full_name)
- H5MM_xfree(full_name);
-
/* Close object if it's open and something failed */
- if(ret_value < 0 && ext_obj >= 0 && H5I_dec_ref(ext_obj) < 0)
+ if(ret_value < 0 && ext_obj >= 0 && H5I_dec_ref(ext_obj, FALSE) < 0)
HDONE_ERROR(H5E_ATOM, H5E_CANTRELEASE, FAIL, "unable to close atom for external object")
FUNC_LEAVE_NOAPI(ret_value)
@@ -331,7 +475,7 @@ H5Lcreate_external(const char *file_name, const char *obj_name,
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate udata buffer")
/* Encode the external link information */
- p = ext_link_buf;
+ p = (uint8_t *)ext_link_buf;
*p++ = (H5L_EXT_VERSION << 4) | H5L_EXT_FLAGS_ALL; /* External link version & flags */
HDstrcpy((char *)p, file_name); /* Name of file containing external link's object */
p += HDstrlen(file_name) + 1;
diff --git a/src/H5Lprivate.h b/src/H5Lprivate.h
index 6d3811e..cd17a87 100644
--- a/src/H5Lprivate.h
+++ b/src/H5Lprivate.h
@@ -39,8 +39,9 @@
#define H5L_CRT_INTERMEDIATE_GROUP_NAME "intermediate_group" /* Create intermediate groups flag */
/* ======== Link access property names ======== */
-#define H5L_ACS_NLINKS_NAME "max soft links" /* Number of soft links to traverse */
-#define H5L_ACS_ELINK_PREFIX_NAME "external link prefix" /* External link prefix */
+#define H5L_ACS_NLINKS_NAME "max soft links" /* Number of soft links to traverse */
+#define H5L_ACS_ELINK_PREFIX_NAME "external link prefix" /* External link prefix */
+#define H5L_ACS_ELINK_FAPL_NAME "external link fapl" /* file access property list for external link access */
/****************************/
diff --git a/src/H5Lpublic.h b/src/H5Lpublic.h
index 1645e4b..eba09b2 100644
--- a/src/H5Lpublic.h
+++ b/src/H5Lpublic.h
@@ -60,7 +60,7 @@ extern "C" {
* defined by HDF5 but their behavior can be overridden by users.
* Users who want to create new classes of links should contact the HDF5
* development team at hdfhelp@ncsa.uiuc.edu .
- * These values can never change because they appear in HDF5 files.
+ * These values can never change because they appear in HDF5 files.
*/
typedef enum {
H5L_TYPE_ERROR = (-1), /* Invalid link type id */
@@ -170,6 +170,11 @@ H5_DLL herr_t H5Literate(hid_t grp_id, H5_index_t idx_type,
H5_DLL herr_t H5Literate_by_name(hid_t loc_id, const char *group_name,
H5_index_t idx_type, H5_iter_order_t order, hsize_t *idx,
H5L_iterate_t op, void *op_data, hid_t lapl_id);
+H5_DLL herr_t H5Lvisit(hid_t grp_id, H5_index_t idx_type, H5_iter_order_t order,
+ H5L_iterate_t op, void *op_data);
+H5_DLL herr_t H5Lvisit_by_name(hid_t loc_id, const char *group_name,
+ H5_index_t idx_type, H5_iter_order_t order, H5L_iterate_t op,
+ void *op_data, hid_t lapl_id);
/* UD link functions */
H5_DLL herr_t H5Lcreate_ud(hid_t link_loc_id, const char *link_name,
diff --git a/src/H5MF.c b/src/H5MF.c
index 6d44c69..3fc7af0 100644
--- a/src/H5MF.c
+++ b/src/H5MF.c
@@ -21,25 +21,255 @@
*
* Purpose: File memory management functions.
*
- * Modifications:
- * Robb Matzke, 5 Aug 1997
- * Added calls to H5E.
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5F_PACKAGE /*suppress error about including H5Fpkg */
+#define H5MF_PACKAGE /*suppress error about including H5MFpkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fpkg.h" /* File access */
+#include "H5MFpkg.h" /* File memory management */
+#include "H5Vprivate.h" /* Vectors and arrays */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+#define H5MF_FSPACE_SHRINK 80 /* Percent of "normal" size to shrink serialized free space size */
+#define H5MF_FSPACE_EXPAND 120 /* Percent of "normal" size to expand serialized free space size */
+
+/* Map an allocation request type to a free list */
+#define H5MF_ALLOC_TO_FS_TYPE(F, T) ((H5FD_MEM_DEFAULT == (F)->shared->fs_type_map[T]) \
+ ? (T) : (F)->shared->fs_type_map[T])
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+/* Enum for kind of free space section+aggregator merging allowed for a file */
+typedef enum {
+ H5MF_AGGR_MERGE_SEPARATE, /* Everything in separate free list */
+ H5MF_AGGR_MERGE_DICHOTOMY, /* Metadata in one free list and raw data in another */
+ H5MF_AGGR_MERGE_TOGETHER /* Metadata & raw data in one free list */
+} H5MF_aggr_merge_t;
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_init_merge_flags
*
- * Robb Matzke, 8 Jun 1998
- * Implemented a very simple free list which is not persistent and which
- * is lossy.
+ * Purpose: Initialize the free space section+aggregator merge flags
+ * for the file.
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Friday, February 1, 2008
*
*-------------------------------------------------------------------------
*/
-#define H5F_PACKAGE /*suppress error about including H5Fpkg */
+herr_t
+H5MF_init_merge_flags(H5F_t *f)
+{
+ H5MF_aggr_merge_t mapping_type; /* Type of free list mapping */
+ H5FD_mem_t type; /* Memory type for iteration */
+ hbool_t all_same; /* Whether all the types map to the same value */
+ FUNC_ENTER_NOAPI_NOFUNC(H5MF_init_merge_flags)
-#include "H5private.h"
-#include "H5Eprivate.h"
-#include "H5Fpkg.h"
-#include "H5FDprivate.h"
-#include "H5MFprivate.h"
-#include "H5FDmulti.h" /*multiple files partitioned by mem usage */
+ /* check args */
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(f->shared->lf);
+
+ /* Iterate over all the free space types to determine if sections of that type
+ * can merge with the metadata or small 'raw' data aggregator
+ */
+ all_same = TRUE;
+ for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type))
+ /* Check for any different type mappings */
+ if(f->shared->fs_type_map[type] != f->shared->fs_type_map[H5FD_MEM_DEFAULT]) {
+ all_same = FALSE;
+ break;
+ } /* end if */
+
+ /* Check for all allocation types mapping to the same free list type */
+ if(all_same) {
+ if(f->shared->fs_type_map[H5FD_MEM_DEFAULT] == H5FD_MEM_DEFAULT)
+ mapping_type = H5MF_AGGR_MERGE_SEPARATE;
+ else
+ mapping_type = H5MF_AGGR_MERGE_TOGETHER;
+ } /* end if */
+ else {
+ /* Check for raw data mapping into same list as metadata */
+ if(f->shared->fs_type_map[H5FD_MEM_DRAW] == f->shared->fs_type_map[H5FD_MEM_SUPER])
+ mapping_type = H5MF_AGGR_MERGE_SEPARATE;
+ else {
+ hbool_t all_metadata_same; /* Whether all metadata go in same free list */
+
+ /* One or more allocation type don't map to the same free list type */
+ /* Check if all the metadata allocation types map to the same type */
+ all_metadata_same = TRUE;
+ for(type = H5FD_MEM_SUPER; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type))
+ /* Skip checking raw data free list mapping */
+ if(type != H5FD_MEM_DRAW) {
+ /* Check for any different type mappings */
+ if(f->shared->fs_type_map[type] != f->shared->fs_type_map[H5FD_MEM_SUPER]) {
+ all_metadata_same = FALSE;
+ break;
+ } /* end if */
+ } /* end if */
+
+ /* Check for all metadata on same free list */
+ if(all_metadata_same)
+ mapping_type = H5MF_AGGR_MERGE_DICHOTOMY;
+ else
+ mapping_type = H5MF_AGGR_MERGE_SEPARATE;
+ } /* end else */
+ } /* end else */
+
+ /* Based on mapping type, initialize merging flags for each free list type */
+ switch(mapping_type) {
+ case H5MF_AGGR_MERGE_SEPARATE:
+ /* Don't merge any metadata together */
+ HDmemset(f->shared->fs_aggr_merge, 0, sizeof(f->shared->fs_aggr_merge));
+
+ /* Check if merging raw data should be allowed */
+ if(H5FD_MEM_DRAW == f->shared->fs_type_map[H5FD_MEM_DRAW] ||
+ H5FD_MEM_DEFAULT == f->shared->fs_type_map[H5FD_MEM_DRAW])
+ f->shared->fs_aggr_merge[H5FD_MEM_DRAW] = H5F_FS_MERGE_RAWDATA;
+ break;
+
+ case H5MF_AGGR_MERGE_DICHOTOMY:
+ /* Merge all metadata together (but not raw data) */
+ HDmemset(f->shared->fs_aggr_merge, H5F_FS_MERGE_METADATA, sizeof(f->shared->fs_aggr_merge));
+
+ /* Allow merging raw data allocations together */
+ f->shared->fs_aggr_merge[H5FD_MEM_DRAW] = H5F_FS_MERGE_RAWDATA;
+ break;
+
+ case H5MF_AGGR_MERGE_TOGETHER:
+ /* Merge all allocation types together */
+ HDmemset(f->shared->fs_aggr_merge, (H5F_FS_MERGE_METADATA | H5F_FS_MERGE_RAWDATA), sizeof(f->shared->fs_aggr_merge));
+ break;
+ } /* end switch */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5MF_init_merge_flags() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_alloc_start
+ *
+ * Purpose: "Start up" free space for file - open existing free space
+ * structure if one exists, otherwise create a new free space
+ * structure
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jan 8 2008
+ *
+ * Modifications:
+ * Vailin Choi, July 29th, 2008
+ * Pass values of alignment and threshold to FS_create() for handling alignment
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5MF_alloc_start(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type, hbool_t may_create)
+{
+ const H5FS_section_class_t *classes[] = { /* Free space section classes implemented for file */
+ H5MF_FSPACE_SECT_CLS_SIMPLE};
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5MF_alloc_start)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(f->shared);
+
+ /* Check for creating free space info for the file */
+ if(H5F_addr_defined(f->shared->fs_addr[type])) {
+ /* Open an existing free space structure for the file */
+ HDassert(f->shared->fs_state[type] == H5F_FS_STATE_CLOSED);
+ if(NULL == (f->shared->fs_man[type] = H5FS_open(f, dxpl_id, f->shared->fs_addr[type],
+ NELMTS(classes), classes, f, f->shared->alignment, f->shared->threshold)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space info")
+ } /* end if */
+ else {
+ /* Check if we are allowed to create the free space manager */
+ if(may_create) {
+ H5FS_create_t fs_create; /* Free space creation parameters */
+
+ /* Set the free space creation parameters */
+ fs_create.client = H5FS_CLIENT_FILE_ID;
+ fs_create.shrink_percent = H5MF_FSPACE_SHRINK;
+ fs_create.expand_percent = H5MF_FSPACE_EXPAND;
+ fs_create.max_sect_addr = 1 + H5V_log2_gen((uint64_t)f->shared->maxaddr);
+ fs_create.max_sect_size = f->shared->maxaddr;
+
+ /* Create the free space structure for the heap */
+ HDassert(f->shared->fs_state[type] == H5F_FS_STATE_CLOSED);
+#ifdef LATER
+ if(NULL == (f->shared->fs_man[type] = H5FS_create(f, dxpl_id, &f->shared->fs_addr[type],
+ &fs_create, NELMTS(classes), classes, f, f->shared->alignment, f->shared->threshold)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space info")
+#else /* LATER */
+ if(NULL == (f->shared->fs_man[type] = H5FS_create(f, dxpl_id, NULL,
+ &fs_create, NELMTS(classes), classes, f, f->shared->alignment, f->shared->threshold)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space info")
+#endif /* LATER */
+ } /* end if */
+ } /* end else */
+
+ /* Set the state for the free space manager to "open", if it is now */
+ if(f->shared->fs_man[type])
+ f->shared->fs_state[type] = H5F_FS_STATE_OPEN;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MF_alloc_start() */
/*-------------------------------------------------------------------------
@@ -51,50 +281,116 @@
* is being requested.
*
* Return: Success: The file address of new chunk.
- *
* Failure: HADDR_UNDEF
*
* Programmer: Robb Matzke
* matzke@llnl.gov
* Jul 11 1997
*
- * Modifications:
- * Robb Matzke, 1999-08-04
- * Modified to work with the virtual file layer.
*-------------------------------------------------------------------------
*/
haddr_t
-H5MF_alloc(H5F_t *f, H5FD_mem_t type, hid_t dxpl_id, hsize_t size)
+H5MF_alloc(H5F_t *f, H5FD_mem_t alloc_type, hid_t dxpl_id, hsize_t size)
{
- haddr_t ret_value;
+ H5FD_mem_t fs_type; /* Free space type (mapped from allocation type) */
+ haddr_t ret_value; /* Return value */
- FUNC_ENTER_NOAPI(H5MF_alloc, HADDR_UNDEF);
+ FUNC_ENTER_NOAPI(H5MF_alloc, HADDR_UNDEF)
+#ifdef H5MF_ALLOC_DEBUG
+HDfprintf(stderr, "%s: alloc_type = %u, size = %Hu\n", FUNC, (unsigned)alloc_type, size);
+#endif /* H5MF_ALLOC_DEBUG */
/* check arguments */
- assert(f);
- assert(size > 0);
-
- /* Fail if we don't have write access */
- if (0==(f->intent & H5F_ACC_RDWR))
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, HADDR_UNDEF, "file is read-only");
-
- /* Check that the file can address the new space */
- if( H5MF_alloc_overflow(f, size) )
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, "not enough address space in file");
-
- /* Allocate space from the virtual file layer */
- if (HADDR_UNDEF==(ret_value=H5FD_alloc(f->shared->lf, type, dxpl_id, size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, "file allocation failed");
-
- /* Convert absolute file address to relative file address */
- assert(ret_value>=f->shared->base_addr);
-
- /* Set return value */
- ret_value -= f->shared->base_addr;
+ HDassert(f);
+ HDassert(size > 0);
+
+ /* Get free space type from allocation type */
+ fs_type = H5MF_ALLOC_TO_FS_TYPE(f, alloc_type);
+
+ /* Check if the free space manager for the file has been initialized */
+ if(!f->shared->fs_man[fs_type])
+ if(H5MF_alloc_start(f, dxpl_id, fs_type, FALSE) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, HADDR_UNDEF, "can't initialize file free space")
+
+ /* Search for large enough space in the free space manager */
+ if(f->shared->fs_man[fs_type]) {
+ H5MF_free_section_t *node; /* Free space section pointer */
+ htri_t node_found = FALSE; /* Whether an existing free list node was found */
+
+ /* Try to get a section from the free space manager */
+ if((node_found = H5FS_sect_find(f, dxpl_id, f->shared->fs_man[fs_type], size, (H5FS_section_info_t **)&node)) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, HADDR_UNDEF, "error locating free space in file")
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: Check 1.5, node_found = %t\n", FUNC, node_found);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+
+ /* Check for actually finding section */
+ if(node_found) {
+ /* Sanity check */
+ HDassert(node);
+
+ /* Retrieve return value */
+ ret_value = node->sect_info.addr;
+
+ /* Check for eliminating the section */
+ if(node->sect_info.size == size) {
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: Check 1.6, freeing node\n", FUNC);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+ /* Free section node */
+ if(H5MF_sect_simple_free((H5FS_section_info_t *)node) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, HADDR_UNDEF, "can't free simple section node")
+ } /* end if */
+ else {
+ H5MF_sect_ud_t udata; /* User data for callback */
+
+ /* Adjust information for section */
+ node->sect_info.addr += size;
+ node->sect_info.size -= size;
+
+ /* Construct user data for callbacks */
+ udata.f = f;
+ udata.dxpl_id = dxpl_id;
+ udata.alloc_type = alloc_type;
+ udata.allow_sect_absorb = TRUE;
+
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: Check 1.7, re-adding node, node->sect_info.size = %Hu\n", FUNC, node->sect_info.size);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+ /* Re-insert section node into file's free space */
+ if(H5FS_sect_add(f, dxpl_id, f->shared->fs_man[fs_type], (H5FS_section_info_t *)node, H5FS_ADD_RETURNED_SPACE, &udata) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINSERT, HADDR_UNDEF, "can't re-add section to file free space")
+ } /* end else */
+
+ /* Leave now */
+ HGOTO_DONE(ret_value)
+ } /* end if */
+ } /* end if */
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: Check 2.0\n", FUNC);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+
+ /* Couldn't find anything from the free space manager, go allocate some */
+ if(alloc_type != H5FD_MEM_DRAW) {
+ /* Handle metadata differently from "raw" data */
+ if(HADDR_UNDEF == (ret_value = H5MF_aggr_alloc(f, dxpl_id, &(f->shared->meta_aggr), &(f->shared->sdata_aggr), alloc_type, size)))
+ HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate metadata")
+ } /* end if */
+ else {
+ /* Allocate "raw" data */
+ if(HADDR_UNDEF == (ret_value = H5MF_aggr_alloc(f, dxpl_id, &(f->shared->sdata_aggr), &(f->shared->meta_aggr), alloc_type, size)))
+ HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate raw data")
+ } /* end else */
done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
+#ifdef H5MF_ALLOC_DEBUG
+HDfprintf(stderr, "%s: Leaving: ret_value = %a, size = %Hu\n", FUNC, ret_value, size);
+#endif /* H5MF_ALLOC_DEBUG */
+#ifdef H5MF_ALLOC_DEBUG_DUMP
+H5MF_sects_dump(f, dxpl_id, stderr);
+#endif /* H5MF_ALLOC_DEBUG_DUMP */
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MF_alloc() */
/*-------------------------------------------------------------------------
@@ -109,245 +405,461 @@ done:
* matzke@llnl.gov
* Jul 17 1997
*
- * Modifications:
- * Robb Matzke, 1999-07-28
- * The ADDR argument is passed by value
- *
- * Robb Matzke, 1999-08-03
- * Modified to use the virtual file layer.
*-------------------------------------------------------------------------
*/
herr_t
-H5MF_xfree(H5F_t *f, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t size)
+H5MF_xfree(H5F_t *f, H5FD_mem_t alloc_type, hid_t dxpl_id, haddr_t addr,
+ hsize_t size)
{
- herr_t ret_value=SUCCEED; /* Return value */
+ H5MF_free_section_t *node = NULL; /* Free space section pointer */
+ H5MF_sect_ud_t udata; /* User data for callback */
+ H5FD_mem_t fs_type; /* Free space type (mapped from allocation type) */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOFUNC(H5MF_xfree);
+ FUNC_ENTER_NOAPI(H5MF_xfree, FAIL)
+#ifdef H5MF_ALLOC_DEBUG
+HDfprintf(stderr, "%s: Entering - alloc_type = %u, addr = %a, size = %Hu\n", FUNC, (unsigned)alloc_type, addr, size);
+#endif /* H5MF_ALLOC_DEBUG */
/* check arguments */
- assert(f);
- if (!H5F_addr_defined(addr) || 0 == size)
+ HDassert(f);
+ if(!H5F_addr_defined(addr) || 0 == size)
HGOTO_DONE(SUCCEED);
- assert(addr!=0);
-
- /* Convert relative address to absolute address */
- addr += f->shared->base_addr;
-
- /* Allow virtual file layer to free block */
- if (H5FD_free(f->shared->lf, type, dxpl_id, addr, size)<0) {
-#ifdef H5MF_DEBUG
- if (H5DEBUG(MF)) {
- fprintf(H5DEBUG(MF),
- "H5MF_free: lost %lu bytes of file storage\n",
- (unsigned long)size);
- }
-#endif
- }
+ HDassert(addr != 0); /* Can't deallocate the superblock :-) */
+
+ /* Check if the space to free intersects with the file's metadata accumulator */
+ if(H5F_accum_free(f, dxpl_id, alloc_type, addr, size) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "can't check free space intersection w/metadata accumulator")
+
+ /* Get free space type from allocation type */
+ fs_type = H5MF_ALLOC_TO_FS_TYPE(f, alloc_type);
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: fs_type = %u\n", FUNC, (unsigned)fs_type);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+
+ /* Check if the free space manager for the file has been initialized */
+ if(!f->shared->fs_man[fs_type]) {
+ /* If there's no free space manager for objects of this type,
+ * see if we can avoid creating one by checking if the freed
+ * space is at the end of the file
+ */
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: f->shared->fs_addr[%u] = %a\n", FUNC, (unsigned)fs_type, f->shared->fs_addr[fs_type]);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+ if(!H5F_addr_defined(f->shared->fs_addr[fs_type])) {
+ htri_t status; /* "can absorb" status for section into */
+
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: Trying to avoid starting up free space manager\n", FUNC);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+ /* Try to shrink the file or absorb the block into a block aggregator */
+ if((status = H5MF_try_shrink(f, alloc_type, dxpl_id, addr, size)) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTMERGE, FAIL, "can't check for absorbing block")
+ else if(status > 0)
+ /* Indicate success */
+ HGOTO_DONE(SUCCEED)
+ } /* end if */
+
+ /* If we are deleting the free space manager, leave now, to avoid
+ * [re-]starting it.
+ *
+ * Note: this drops the space to free on the floor...
+ *
+ */
+ if(f->shared->fs_state[fs_type] == H5F_FS_STATE_DELETING)
+{
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: dropping addr = %a, size = %Hu, on the floor!\n", FUNC, addr, size);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+ HGOTO_DONE(SUCCEED)
+}
+
+ /* There's either already a free space manager, or the freed
+ * space isn't at the end of the file, so start up (or create)
+ * the file space manager
+ */
+ if(H5MF_alloc_start(f, dxpl_id, fs_type, TRUE) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space")
+ } /* end if */
+ HDassert(f->shared->fs_man[fs_type]);
+
+ /* Create free space section for block */
+ if(NULL == (node = H5MF_sect_simple_new(addr, size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space section")
+
+ /* Construct user data for callbacks */
+ udata.f = f;
+ udata.dxpl_id = dxpl_id;
+ udata.alloc_type = alloc_type;
+ udata.allow_sect_absorb = TRUE;
+
+ /* Add to the free space for the file */
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: Before H5FS_sect_add()\n", FUNC);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+ if(H5FS_sect_add(f, dxpl_id, f->shared->fs_man[fs_type], (H5FS_section_info_t *)node, H5FS_ADD_RETURNED_SPACE, &udata) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINSERT, FAIL, "can't add section to file free space")
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: After H5FS_sect_add()\n", FUNC);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+ node = NULL;
done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ if(ret_value < 0 && node)
+ /* On error, free section node allocated */
+ if(H5MF_sect_simple_free((H5FS_section_info_t *)node) < 0)
+ HDONE_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free simple section node")
+
+#ifdef H5MF_ALLOC_DEBUG
+HDfprintf(stderr, "%s: Leaving, ret_value = %d\n", FUNC, ret_value);
+#endif /* H5MF_ALLOC_DEBUG */
+#ifdef H5MF_ALLOC_DEBUG_DUMP
+H5MF_sects_dump(f, dxpl_id, stderr);
+#endif /* H5MF_ALLOC_DEBUG_DUMP */
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MF_xfree() */
/*-------------------------------------------------------------------------
- * Function: H5MF_realloc
- *
- * Purpose: Changes the size of an allocated chunk, possibly moving it to
- * a new address. The chunk to change is at address OLD_ADDR
- * and is exactly OLD_SIZE bytes (if these are H5F_ADDR_UNDEF
- * and zero then this function acts like H5MF_alloc). The new
- * size will be NEW_SIZE and its address is the return value (if
- * NEW_SIZE is zero then this function acts like H5MF_free and
- * an undefined address is returned).
- *
- * If the new size is less than the old size then the new
- * address will be the same as the old address (except for the
- * special case where the new size is zero).
- *
- * If the new size is more than the old size then most likely a
- * new address will be returned. However, under certain
- * circumstances the library may return the same address.
+ * Function: H5MF_try_extend
*
- * Return: Success: The relative file address of the new block.
+ * Purpose: Extend a block in the file if possible.
*
- * Failure: HADDR_UNDEF
- *
- * Programmer: Robb Matzke
- * Thursday, April 16, 1998
+ * Return: Success: TRUE(1) - Block was extended
+ * FALSE(0) - Block could not be extended
+ * Failure: FAIL
*
- * Modifications:
- * Robb Matzke, 1999-07-28
- * The ORIG_ADDR is passed by value. The name of NEW_ADDR has
- * been changed to NEW_ADDR_P
+ * Programmer: Quincey Koziol
+ * Friday, June 11, 2004
*
- * Robb Matzke, 1999-08-04
- * Modified to work with the virtual file layer.
*-------------------------------------------------------------------------
*/
-haddr_t
-H5MF_realloc(H5F_t *f, H5FD_mem_t type, hid_t dxpl_id, haddr_t old_addr, hsize_t old_size,
- hsize_t new_size)
+htri_t
+H5MF_try_extend(H5F_t *f, hid_t dxpl_id, H5FD_mem_t alloc_type, haddr_t addr,
+ hsize_t size, hsize_t extra_requested)
{
- haddr_t ret_value;
-
- FUNC_ENTER_NOAPI(H5MF_realloc, HADDR_UNDEF);
-
- /* Convert old relative address to absolute address */
- old_addr += f->shared->base_addr;
-
- /* Check that the file can address the new space. */
- /* In the worst case, this means adding new_size bytes to the end of the file. */
- if( H5MF_alloc_overflow(f, new_size) )
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, "not enough address space in file");
-
- /* Reallocate memory from the virtual file layer */
- ret_value = H5FD_realloc(f->shared->lf, type, dxpl_id, old_addr, old_size,
- new_size);
- if (HADDR_UNDEF==ret_value)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, HADDR_UNDEF, "unable to allocate new file memory");
-
- /* Convert return value to relative address */
- assert(ret_value>=f->shared->base_addr);
+ haddr_t end; /* End of block to extend */
+ htri_t ret_value; /* Return value */
- /* Set return value */
- ret_value -= f->shared->base_addr;
+ FUNC_ENTER_NOAPI(H5MF_try_extend, FAIL)
+#ifdef H5MF_ALLOC_DEBUG
+HDfprintf(stderr, "%s: Entering: alloc_type = %u, addr = %a, size = %Hu, extra_requested = %Hu\n", FUNC, (unsigned)alloc_type, addr, size, extra_requested);
+#endif /* H5MF_ALLOC_DEBUG */
+
+ /* Compute end of block to extend */
+ end = addr + size;
+
+ /* Check if the block is exactly at the end of the file */
+ if((ret_value = H5FD_try_extend(f->shared->lf, alloc_type, end, extra_requested)) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTEXTEND, FAIL, "error extending file")
+ else if(ret_value == FALSE) {
+ H5F_blk_aggr_t *aggr; /* Aggregator to use */
+
+ /* Check for test block able to extend aggregation block */
+ aggr = (alloc_type == H5FD_MEM_DRAW) ? &(f->shared->sdata_aggr) : &(f->shared->meta_aggr);
+ if((ret_value = H5MF_aggr_try_extend(f, aggr, alloc_type, end, extra_requested)) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTEXTEND, FAIL, "error extending aggregation block")
+ else if(ret_value == FALSE) {
+ H5FD_mem_t fs_type; /* Free space type (mapped from allocation type) */
+
+ /* Get free space type from allocation type */
+ fs_type = H5MF_ALLOC_TO_FS_TYPE(f, alloc_type);
+
+ /* Check if the free space for the file has been initialized */
+ if(!f->shared->fs_man[fs_type])
+ if(H5MF_alloc_start(f, dxpl_id, fs_type, FALSE) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space")
+
+ /* Check for test block able to block in free space manager */
+ if(f->shared->fs_man[fs_type])
+ if((ret_value = H5FS_sect_try_extend(f, dxpl_id, f->shared->fs_man[fs_type], addr, size, extra_requested)) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTEXTEND, FAIL, "error extending block in free space manager")
+ } /* end if */
+ } /* end if */
done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
+#ifdef H5MF_ALLOC_DEBUG
+HDfprintf(stderr, "%s: Leaving: ret_value = %t\n", FUNC, ret_value);
+#endif /* H5MF_ALLOC_DEBUG */
+#ifdef H5MF_ALLOC_DEBUG_DUMP
+H5MF_sects_dump(f, dxpl_id, stderr);
+#endif /* H5MF_ALLOC_DEBUG_DUMP */
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MF_try_extend() */
/*-------------------------------------------------------------------------
- * Function: H5MF_alloc_overflow
+ * Function: H5MF_get_freespace
*
- * Purpose: Checks if an allocation of file space would cause an overflow.
- * F is the file whose space is being allocated, SIZE is the amount
- * of space needed.
+ * Purpose: Retrieve the amount of free space in a file.
*
- * Return: 0 if no overflow would result
- * 1 if overflow would result (the allocation should not be allowed)
+ * Return: Success: Amount of free space in file
+ * Failure: Negative
*
- * Programmer: James Laird
- * Nat Furrer
- * Tuesday, June 1, 2004
+ * Programmer: Quincey Koziol
+ * Monday, October 6, 2003
*
*-------------------------------------------------------------------------
*/
-hbool_t
-H5MF_alloc_overflow(H5F_t *f, hsize_t size)
+hssize_t
+H5MF_get_freespace(H5F_t *f, hid_t dxpl_id)
{
- hsize_t space_needed = 0; /* Accumulator variable */
- size_t c; /* Local index variable */
- hbool_t ret_value; /* Return value */
-
- FUNC_ENTER_NOAPI_NOFUNC(H5MF_alloc_overflow)
-
- /* Start with the current end of the file's address. */
- space_needed = (hsize_t)H5F_get_eoa(f);
-
- HDassert(H5F_addr_defined(space_needed));
-
- /* Subtract the file's base address to get the actual amount of
- * space being used:
- * (end of allocated space - beginning of allocated space)
- */
- HDassert(H5F_BASE_ADDR(f) < space_needed);
- space_needed -= (hsize_t)H5F_BASE_ADDR(f);
-
- /* Add the amount of space requested for this allocation */
- space_needed += size;
-
- /* Ensure that this final number is less than the file's
- * address space. We do this by shifting in multiples
- * of 16 bits because some systems will do nothing if
- * we shift by 64 bits all at once (<cough> Linux <cough>).
- * Thus, we break one shift into several smaller shifts.
- */
- for(c=0; c < H5F_SIZEOF_ADDR(f); c += 2)
- space_needed = space_needed >> 16;
-
- if(space_needed != 0)
- ret_value = TRUE;
- else
- ret_value = FALSE;
+ haddr_t eoa; /* End of allocated space in the file */
+ haddr_t ma_addr = HADDR_UNDEF; /* Base "metadata aggregator" address */
+ hsize_t ma_size = 0; /* Size of "metadata aggregator" */
+ haddr_t sda_addr = HADDR_UNDEF; /* Base "small data aggregator" address */
+ hsize_t sda_size = 0; /* Size of "small data aggregator" */
+ hsize_t tot_fs_size = 0; /* Amount of all free space managed */
+ H5FD_mem_t type; /* Memory type for iteration */
+ hssize_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5MF_get_freespace, FAIL)
+
+ /* check args */
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(f->shared->lf);
+
+ /* Retrieve the 'eoa' for the file */
+ if(HADDR_UNDEF == (eoa = H5FD_get_eoa(f->shared->lf, H5FD_MEM_DEFAULT)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "driver get_eoa request failed")
+
+ /* Retrieve metadata aggregator info, if available */
+ H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size);
+
+ /* Retrieve 'small data' aggregator info, if available */
+ H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sda_addr, &sda_size);
+
+ /* Iterate over all the free space types that have managers and get each free list's space */
+ for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type)) {
+ hsize_t type_fs_size = 0; /* Amount of free space managed for each type */
+
+ /* Check if the free space for the file has been initialized */
+ if(!f->shared->fs_man[type])
+ if(H5MF_alloc_start(f, dxpl_id, type, FALSE) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space")
+
+ /* Retrieve free space size from free space manager */
+ if(f->shared->fs_man[type])
+ if((ret_value = H5FS_sect_stats(f->shared->fs_man[type], &type_fs_size, NULL)) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't query free space stats")
+
+ /* Increment total free space for types */
+ tot_fs_size += type_fs_size;
+ } /* end for */
+
+ /* Start computing value to return */
+ ret_value = tot_fs_size;
+
+ /* Check for aggregating metadata allocations */
+ if(ma_size > 0) {
+ /* Add in the reserved space for metadata to the available free space */
+ /* (if it's not at the tail of the file) */
+ if(H5F_addr_ne(ma_addr + ma_size, eoa))
+ ret_value += ma_size;
+ } /* end if */
+
+ /* Check for aggregating small data allocations */
+ if(sda_size > 0) {
+ /* Add in the reserved space for metadata to the available free space */
+ /* (if it's not at the tail of the file) */
+ if(H5F_addr_ne(sda_addr + sda_size, eoa))
+ ret_value += sda_size;
+ } /* end if */
+done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5MF_get_freespace() */
/*-------------------------------------------------------------------------
- * Function: H5MF_can_extend
- *
- * Purpose: Check if a block in the file can be extended.
+ * Function: H5MF_can_shrink
*
- * Return: Success: TRUE(1)/FALSE(0)
+ * Purpose: Try to shrink the size of a file with a block or absorb it
+ * into a block aggregator.
*
- * Failure: FAIL
- *
- * Programmer: Quincey Koziol
- * Friday, June 11, 2004
+ * Return: Non-negative on success/Negative on failure
*
- * Modifications:
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Feb 14 2008
*
*-------------------------------------------------------------------------
*/
htri_t
-H5MF_can_extend(H5F_t *f, H5FD_mem_t type, haddr_t addr, hsize_t size, hsize_t extra_requested)
+H5MF_try_shrink(H5F_t *f, H5FD_mem_t alloc_type, hid_t dxpl_id, haddr_t addr,
+ hsize_t size)
{
- htri_t ret_value; /* Return value */
+ H5MF_free_section_t *node = NULL; /* Free space section pointer */
+ H5MF_sect_ud_t udata; /* User data for callback */
+ htri_t ret_value; /* Return value */
- FUNC_ENTER_NOAPI(H5MF_can_extend, FAIL);
+ FUNC_ENTER_NOAPI(H5MF_try_shrink, FAIL)
+#ifdef H5MF_ALLOC_DEBUG
+HDfprintf(stderr, "%s: Entering - alloc_type = %u, addr = %a, size = %Hu\n", FUNC, (unsigned)alloc_type, addr, size);
+#endif /* H5MF_ALLOC_DEBUG */
- /* Convert old relative address to absolute address */
- addr += H5F_BASE_ADDR(f);
-
- /* Pass the request down to the virtual file layer */
- if((ret_value=H5FD_can_extend(f->shared->lf, type, addr, size, extra_requested))<0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate new file memory");
-
- /* Make sure there is enough addressable space to satisfy the request */
- if (ret_value == TRUE)
- ret_value = !H5MF_alloc_overflow(f, extra_requested);
+ /* check arguments */
+ HDassert(f);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(size > 0);
+
+ /* Create free space section for block */
+ if(NULL == (node = H5MF_sect_simple_new(addr, size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space section")
+
+ /* Construct user data for callbacks */
+ udata.f = f;
+ udata.dxpl_id = dxpl_id;
+ udata.alloc_type = alloc_type;
+ udata.allow_sect_absorb = FALSE; /* Force section to be absorbed into aggregator */
+
+ /* Call the "can shrink" callback for the section */
+ if((ret_value = H5MF_sect_simple_can_shrink((const H5FS_section_info_t *)node, &udata)) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTMERGE, FAIL, "can't check if section can shrink container")
+ else if(ret_value > 0) {
+ /* Shrink or absorb the section */
+ if(H5MF_sect_simple_shrink((H5FS_section_info_t **)&node, &udata) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSHRINK, FAIL, "can't shrink container")
+ } /* end if */
done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5MF_can_extend() */
+ /* Free section node allocated */
+ if(node && H5MF_sect_simple_free((H5FS_section_info_t *)node) < 0)
+ HDONE_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free simple section node")
+
+#ifdef H5MF_ALLOC_DEBUG
+HDfprintf(stderr, "%s: Leaving, ret_value = %d\n", FUNC, ret_value);
+#endif /* H5MF_ALLOC_DEBUG */
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MF_try_shrink() */
/*-------------------------------------------------------------------------
- * Function: H5MF_extend
- *
- * Purpose: Extend a block in the file.
+ * Function: H5MF_close
*
- * Return: Success: Non-negative
+ * Purpose: Close the free space tracker(s) for a file
*
- * Failure: Negative
+ * Return: SUCCEED/FAIL
*
- * Programmer: Quincey Koziol
- * Saturday, June 12, 2004
- *
- * Modifications:
+ * Programmer: Quincey Koziol
+ * Tuesday, January 22, 2008
*
*-------------------------------------------------------------------------
*/
herr_t
-H5MF_extend(H5F_t *f, H5FD_mem_t type, haddr_t addr, hsize_t size, hsize_t extra_requested)
+H5MF_close(H5F_t *f, hid_t dxpl_id)
{
- herr_t ret_value; /* Return value */
-
- FUNC_ENTER_NOAPI(H5MF_extend, FAIL);
-
- /* Make sure there is enough addressable space to satisfy the request */
- if ( H5MF_alloc_overflow(f, extra_requested) )
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate new file memory: out of address space");
-
- /* Convert old relative address to absolute address */
- addr += H5F_BASE_ADDR(f);
-
- /* Pass the request down to the virtual file layer */
- if((ret_value=H5FD_extend(f->shared->lf, type, addr, size, extra_requested))<0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate new file memory");
+ H5FD_mem_t type; /* Memory type for iteration */
+ H5F_blk_aggr_t *first_aggr; /* First aggregator to reset */
+ H5F_blk_aggr_t *second_aggr; /* Second aggregator to reset */
+ haddr_t ma_addr = HADDR_UNDEF; /* Base "metadata aggregator" address */
+ hsize_t ma_size = 0; /* Size of "metadata aggregator" */
+ haddr_t sda_addr = HADDR_UNDEF; /* Base "small data aggregator" address */
+ hsize_t sda_size = 0; /* Size of "small data aggregator" */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5MF_close, FAIL)
+#ifdef H5MF_ALLOC_DEBUG
+HDfprintf(stderr, "%s: Entering\n", FUNC);
+#endif /* H5MF_ALLOC_DEBUG */
+
+ /* check args */
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(f->shared->lf);
+
+ /* Iterate over all the free space types that have managers and get each free list's space */
+ for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type)) {
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: Check 1.0 - f->shared->fs_man[%u] = %p, f->shared->fs_addr[%u] = %a\n", FUNC, (unsigned)type, f->shared->fs_man[type], (unsigned)type, f->shared->fs_addr[type]);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+ /* If the free space manager for this type is open, close it */
+ if(f->shared->fs_man[type]) {
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: Before closing free space manager\n", FUNC);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+ if(H5FS_close(f, dxpl_id, f->shared->fs_man[type]) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release free space info")
+ f->shared->fs_man[type] = NULL;
+ f->shared->fs_state[type] = H5F_FS_STATE_CLOSED;
+ } /* end if */
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: Check 2.0 - f->shared->fs_man[%u] = %p, f->shared->fs_addr[%u] = %a\n", FUNC, (unsigned)type, f->shared->fs_man[type], (unsigned)type, f->shared->fs_addr[type]);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+
+ /* If there is free space manager info for this type, delete it */
+ /* (XXX: Make this optional when free space for a file can be persistant) */
+ if(H5F_addr_defined(f->shared->fs_addr[type])) {
+ haddr_t tmp_fs_addr; /* Temporary holder for free space manager address */
+
+ /* Put address into temporary variable and reset it */
+ /* (Avoids loopback in file space freeing routine) */
+ tmp_fs_addr = f->shared->fs_addr[type];
+ f->shared->fs_addr[type] = HADDR_UNDEF;
+
+ /* Shift to "deleting" state, to make certain we don't track any
+ * file space freed as a result of deleting the free space manager.
+ */
+ f->shared->fs_state[type] = H5F_FS_STATE_DELETING;
+
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: Before deleting free space manager\n", FUNC);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+ /* Delete free space manager for this type */
+ if(H5FS_delete(f, dxpl_id, tmp_fs_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "can't delete free space manager")
+
+ /* Shift [back] to closed state */
+ HDassert(f->shared->fs_state[type] == H5F_FS_STATE_DELETING);
+ f->shared->fs_state[type] = H5F_FS_STATE_CLOSED;
+
+ /* Sanity check that the free space manager for this type wasn't started up again */
+ HDassert(!H5F_addr_defined(f->shared->fs_addr[type]));
+ } /* end if */
+ } /* end for */
+
+ /* Retrieve metadata aggregator info, if available */
+ H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size);
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: ma_addr = %a, ma_size = %Hu, end of ma = %a\n", FUNC, ma_addr, ma_size, (haddr_t)((ma_addr + ma_size) - 1));
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+
+ /* Retrieve 'small data' aggregator info, if available */
+ H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sda_addr, &sda_size);
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: sda_addr = %a, sda_size = %Hu, end of sda = %a\n", FUNC, sda_addr, sda_size, (haddr_t)((sda_addr + sda_size) - 1));
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+
+ /* Make certain we release the aggregator that's later in the file first */
+ /* (so the file shrinks properly) */
+ if(H5F_addr_defined(ma_addr) && H5F_addr_defined(sda_addr)) {
+ if(H5F_addr_lt(ma_addr, sda_addr)) {
+ first_aggr = &(f->shared->sdata_aggr);
+ second_aggr = &(f->shared->meta_aggr);
+ } /* end if */
+ else {
+ first_aggr = &(f->shared->meta_aggr);
+ second_aggr = &(f->shared->sdata_aggr);
+ } /* end else */
+ } /* end if */
+ else {
+ first_aggr = &(f->shared->meta_aggr);
+ second_aggr = &(f->shared->sdata_aggr);
+ } /* end else */
+
+ /* Release the unused portion of the metadata and "small data" blocks back
+ * to the free lists in the file.
+ */
+ if(H5MF_aggr_reset(f, dxpl_id, first_aggr) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "can't reset metadata block")
+ if(H5MF_aggr_reset(f, dxpl_id, second_aggr) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTFREE, FAIL, "can't reset 'small data' block")
done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5MF_extend() */
+#ifdef H5MF_ALLOC_DEBUG
+HDfprintf(stderr, "%s: Leaving\n", FUNC);
+#endif /* H5MF_ALLOC_DEBUG */
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MF_close() */
+
diff --git a/src/H5MFaggr.c b/src/H5MFaggr.c
new file mode 100644
index 0000000..f383e23
--- /dev/null
+++ b/src/H5MFaggr.c
@@ -0,0 +1,568 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Programmer: Quincey Koziol <koziol@hdfgroup.org>
+ * Tuesday, January 8, 2008
+ *
+ * Purpose: Routines for aggregating free space allocations
+ *
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5F_PACKAGE /*suppress error about including H5Fpkg */
+#define H5MF_PACKAGE /*suppress error about including H5MFpkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fpkg.h" /* File access */
+#include "H5MFpkg.h" /* File memory management */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_aggr_alloc
+ *
+ * Purpose: Try to allocate SIZE bytes of memory from an aggregator
+ * block if possible.
+ *
+ * Return: Success: The format address of the new file memory.
+ * Failure: The undefined address HADDR_UNDEF
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, December 13, 2007
+ *
+ * Modifications:
+ * Vailin Choi, July 29th, 2008
+ * The whole routine is modified to handle alignment
+ *
+ *-------------------------------------------------------------------------
+ */
+haddr_t
+H5MF_aggr_alloc(H5F_t *f, hid_t dxpl_id, H5F_blk_aggr_t *aggr,
+ H5F_blk_aggr_t *other_aggr, H5FD_mem_t type, hsize_t size)
+{
+ haddr_t ret_value;
+ hsize_t alignment = 0, mis_align = 0;
+ haddr_t frag_addr = 0, eoa_frag_addr = 0;
+ hsize_t frag_size = 0, eoa_frag_size = 0;
+ haddr_t eoa = 0, new_space = 0;
+ htri_t extended = 0;
+ H5FD_mem_t alloc_type, other_alloc_type;
+
+ FUNC_ENTER_NOAPI(H5MF_aggr_alloc, HADDR_UNDEF)
+#ifdef H5MF_AGGR_DEBUG
+HDfprintf(stderr, "%s: type = %u, size = %Hu\n", FUNC, (unsigned)type, size);
+#endif /* H5MF_AGGR_DEBUG */
+
+ /* check args */
+ HDassert(f);
+ HDassert(aggr);
+ HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA);
+ HDassert(other_aggr);
+ HDassert(other_aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || other_aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA);
+ HDassert(other_aggr->feature_flag != aggr->feature_flag);
+ HDassert(type >= H5FD_MEM_DEFAULT && type < H5FD_MEM_NTYPES);
+ HDassert(size > 0);
+
+ /*
+ * If the aggregation feature is enabled for this file, allocate "generic"
+ * space and sub-allocate out of that, if possible. Otherwise just allocate
+ * through H5FD_alloc()
+ */
+ if(f->shared->feature_flags & aggr->feature_flag) {
+#ifdef H5MF_AGGR_DEBUG
+HDfprintf(stderr, "%s: aggr = {%a, %Hu, %Hu}\n", FUNC, aggr->addr, aggr->tot_size, aggr->size);
+#endif /* H5MF_AGGR_DEBUG */
+
+ alignment = f->shared->alignment;
+ if (!((alignment > 1) && (size >= f->shared->threshold)))
+ alignment = 0; /* no alignment */
+
+ if (alignment && aggr->addr > 0 && aggr->size > 0 && (mis_align = aggr->addr % alignment)) {
+ frag_addr = aggr->addr;
+ frag_size = alignment - mis_align;
+ }
+
+ if (HADDR_UNDEF == (eoa = H5F_get_eoa(f, type)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, HADDR_UNDEF, "Unable to get eoa")
+
+ alloc_type = aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA ? H5FD_MEM_DEFAULT : H5FD_MEM_DRAW;
+ other_alloc_type = other_aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA ? H5FD_MEM_DEFAULT : H5FD_MEM_DRAW;
+
+ /* Check if the space requested is larger than the space left in the block */
+ if((size + frag_size) > aggr->size) {
+
+ /* Check if the block asked for is too large for 'normal' aggregator block */
+ if(size >= aggr->alloc_size) {
+
+ hsize_t ext_size = size + frag_size;
+
+ if ((aggr->addr > 0) && (extended=H5FD_try_extend(f->shared->lf, alloc_type, aggr->addr + aggr->size, ext_size)) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, HADDR_UNDEF, "can't extending space")
+ else if (extended) {
+ /* aggr->size is unchanged */
+ ret_value = aggr->addr + frag_size;
+ aggr->addr += ext_size;
+ aggr->tot_size += ext_size;
+ } else {
+ if ((other_aggr->size > 0) && (H5F_addr_eq((other_aggr->addr + other_aggr->size), eoa)) &&
+ ((other_aggr->tot_size - other_aggr->size) >= other_aggr->alloc_size)) {
+
+ if(H5FD_free(f->shared->lf, dxpl_id, other_alloc_type, other_aggr->addr, other_aggr->size) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free aggregation block")
+
+ other_aggr->addr = 0;
+ other_aggr->tot_size = 0;
+ other_aggr->size = 0;
+ }
+
+ if(HADDR_UNDEF == (new_space = H5FD_alloc(f->shared->lf, dxpl_id, type, size, &eoa_frag_addr, &eoa_frag_size)))
+ HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate aggregation block")
+
+ /* Use the new space allocated, leaving the old block */
+ ret_value = new_space;
+ } /* end else */
+ } /* end if */
+ else {
+ hsize_t ext_size = aggr->alloc_size;
+
+ /* Allocate another block */
+#ifdef H5MF_AGGR_DEBUG
+HDfprintf(stderr, "%s: Allocating block\n", FUNC);
+#endif /* H5MF_AGGR_DEBUG */
+
+ if (frag_size > (ext_size - size))
+ ext_size += (frag_size - (ext_size - size));
+
+ if ((aggr->addr > 0) && (extended = H5FD_try_extend(f->shared->lf, alloc_type, aggr->addr + aggr->size, ext_size)) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, HADDR_UNDEF, "can't extending space")
+ else if (extended) {
+ aggr->addr += frag_size;
+ aggr->size += (ext_size - frag_size);
+ aggr->tot_size += ext_size;
+ } else {
+ if ((other_aggr->size > 0) && (H5F_addr_eq((other_aggr->addr + other_aggr->size), eoa)) &&
+ ((other_aggr->tot_size - other_aggr->size) >= other_aggr->alloc_size)) {
+
+ if(H5FD_free(f->shared->lf, dxpl_id, other_alloc_type, other_aggr->addr, other_aggr->size) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free aggregation block")
+ other_aggr->addr = 0;
+ other_aggr->tot_size = 0;
+ other_aggr->size = 0;
+ }
+
+ if(HADDR_UNDEF == (new_space = H5FD_alloc(f->shared->lf, dxpl_id, alloc_type, aggr->alloc_size, &eoa_frag_addr, &eoa_frag_size)))
+ HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate aggregation block")
+
+ /* Return the unused portion of the block to a free list */
+ if(aggr->size > 0)
+ if(H5MF_xfree(f, alloc_type, dxpl_id, aggr->addr, aggr->size) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free aggregation block")
+
+ /* Point the aggregator at the newly allocated block */
+ aggr->addr = new_space;
+ aggr->size = aggr->alloc_size;
+ aggr->tot_size = aggr->alloc_size;
+
+ } /* end else */
+
+ /* Allocate space out of the metadata block */
+ ret_value = aggr->addr;
+ aggr->size -= size;
+ aggr->addr += size;
+ } /* end else */
+
+ /* freeing any possible fragment due to file allocation */
+ if (eoa_frag_size)
+ if(H5MF_xfree(f, type, dxpl_id, eoa_frag_addr, eoa_frag_size) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free eoa fragment")
+
+ /* freeing any possible fragment due to alignment in the block after extension */
+ if (extended && frag_size)
+ if(H5MF_xfree(f, type, dxpl_id, frag_addr, frag_size) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free aggregation fragment")
+ } /* end if */
+ else {
+ /* Allocate space out of the block */
+ ret_value = aggr->addr + frag_size;
+ aggr->size -= (size + frag_size);
+ aggr->addr += (size + frag_size);
+
+ /* free any possible fragment */
+ if (frag_size)
+ if(H5MF_xfree(f, type, dxpl_id, frag_addr, frag_size) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free aggregation fragment")
+ }
+ } /* end if */
+ else {
+ /* Allocate data from the file */
+ if(HADDR_UNDEF == (ret_value = H5FD_alloc(f->shared->lf, dxpl_id, type, size, &eoa_frag_addr, &eoa_frag_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, HADDR_UNDEF, "can't allocate file space")
+ if (eoa_frag_size)
+ if(H5MF_xfree(f, type, dxpl_id, eoa_frag_addr, eoa_frag_size) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, HADDR_UNDEF, "can't free eoa fragment")
+ } /* end else */
+
+done:
+#ifdef H5MF_AGGR_DEBUG
+HDfprintf(stderr, "%s: ret_value = %a\n", FUNC, ret_value);
+#endif /* H5MF_AGGR_DEBUG */
+ if (alignment)
+ HDassert(!(ret_value % alignment));
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MF_aggr_alloc() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_aggr_try_extend
+ *
+ * Purpose: Check if a block is inside an aggregator block and extend it
+ * if possible.
+ *
+ * Return: Success: TRUE(1) - Block was extended
+ * FALSE(0) - Block could not be extended
+ * Failure: FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, December 13, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5MF_aggr_try_extend(const H5F_t *f, H5F_blk_aggr_t *aggr, H5FD_mem_t type,
+ haddr_t blk_end, hsize_t extra_requested)
+{
+ htri_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5MF_aggr_try_extend, FAIL)
+
+ /* Check args */
+ HDassert(f);
+ HDassert(aggr);
+ HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA);
+
+ /* Check if this aggregator is active */
+ if(f->shared->feature_flags & aggr->feature_flag) {
+ /* If the block being tested adjoins the beginning of the aggregator
+ * block, check if the aggregator can accomodate the extension.
+ */
+ if(H5F_addr_eq(blk_end, aggr->addr)) {
+ /* If the aggregator block is at the end of the file, extend the
+ * file and "bubble" the aggregator up
+ */
+ if((ret_value = H5FD_try_extend(f->shared->lf, type, (aggr->addr + aggr->size), extra_requested)) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTEXTEND, FAIL, "error extending file")
+ else if(ret_value == TRUE) {
+ /* Shift the aggregator block by the extra requested */
+ aggr->addr += extra_requested;
+
+ /* Add extra requested to the aggregator block's total amount allocated */
+ aggr->tot_size += extra_requested;
+ } /* end if */
+ else {
+ /* Check if the aggregator block has enough internal space to satisfy
+ * extending the block.
+ */
+ if(aggr->size >= extra_requested) {
+ /* Extend block into aggregator */
+ aggr->size -= extra_requested;
+ aggr->addr += extra_requested;
+
+ /* Indicate success */
+ HGOTO_DONE(TRUE);
+ } /* end if */
+ } /* end else */
+ } /* end if */
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MF_aggr_try_extend() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_aggr_can_absorb
+ *
+ * Purpose: Check if a section adjoins an aggregator block and one can
+ * absorb the other.
+ *
+ * Return: Success: TRUE(1) - Section or aggregator can be absorbed
+ * FALSE(0) - Section and aggregator can not be absorbed
+ * Failure: FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Friday, February 1, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5MF_aggr_can_absorb(const H5F_t *f, const H5F_blk_aggr_t *aggr,
+ const H5MF_free_section_t *sect, H5MF_shrink_type_t *shrink)
+{
+ htri_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOFUNC(H5MF_aggr_can_absorb)
+
+ /* Check args */
+ HDassert(f);
+ HDassert(aggr);
+ HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA);
+ HDassert(sect);
+ HDassert(shrink);
+
+ /* Check if this aggregator is active */
+ if(f->shared->feature_flags & aggr->feature_flag) {
+ /* Check if the block adjoins the beginning or end of the aggregator */
+ if(H5F_addr_eq((sect->sect_info.addr + sect->sect_info.size), aggr->addr)
+ || H5F_addr_eq((aggr->addr + aggr->size), sect->sect_info.addr)) {
+#ifdef H5MF_AGGR_DEBUG
+HDfprintf(stderr, "%s: section {%a, %Hu} adjoins aggr = {%a, %Hu}\n", "H5MF_aggr_can_absorb", sect->sect_info.addr, sect->sect_info.size, aggr->addr, aggr->size);
+#endif /* H5MF_AGGR_DBEUG */
+ /* Check if aggregator would get too large and should be absorbed into section */
+ if((aggr->size + sect->sect_info.size) >= aggr->alloc_size)
+ *shrink = H5MF_SHRINK_SECT_ABSORB_AGGR;
+ else
+ *shrink = H5MF_SHRINK_AGGR_ABSORB_SECT;
+
+ /* Indicate success */
+ HGOTO_DONE(TRUE)
+ } /* end if */
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MF_aggr_can_absorb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_aggr_absorb
+ *
+ * Purpose: Absorb a free space section into an aggregator block or
+ * vice versa.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Friday, February 1, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5MF_aggr_absorb(const H5F_t *f, H5F_blk_aggr_t *aggr, H5MF_free_section_t *sect,
+ hbool_t allow_sect_absorb)
+{
+ FUNC_ENTER_NOAPI_NOFUNC(H5MF_aggr_absorb)
+
+ /* Check args */
+ HDassert(f);
+ HDassert(aggr);
+ HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA);
+ HDassert(f->shared->feature_flags & aggr->feature_flag);
+ HDassert(sect);
+
+ /* Check if aggregator would get too large and should be absorbed into section */
+ if((aggr->size + sect->sect_info.size) >= aggr->alloc_size && allow_sect_absorb) {
+ /* Check if the section adjoins the beginning or end of the aggregator */
+ if(H5F_addr_eq((sect->sect_info.addr + sect->sect_info.size), aggr->addr)) {
+#ifdef H5MF_AGGR_DBEUG
+HDfprintf(stderr, "%s: aggr {%a, %Hu} adjoins front of section = {%a, %Hu}\n", "H5MF_aggr_absorb", aggr->addr, aggr->size, sect->sect_info.addr, sect->sect_info.size);
+#endif /* H5MF_AGGR_DBEUG */
+ /* Absorb aggregator onto end of section */
+ sect->sect_info.size += aggr->size;
+ } /* end if */
+ else {
+ /* Sanity check */
+ HDassert(H5F_addr_eq((aggr->addr + aggr->size), sect->sect_info.addr));
+
+#ifdef H5MF_AGGR_DBEUG
+HDfprintf(stderr, "%s: aggr {%a, %Hu} adjoins end of section = {%a, %Hu}\n", "H5MF_aggr_absorb", aggr->addr, aggr->size, sect->sect_info.addr, sect->sect_info.size);
+#endif /* H5MF_AGGR_DBEUG */
+ /* Absorb aggregator onto beginning of section */
+ sect->sect_info.addr -= aggr->size;
+ sect->sect_info.size += aggr->size;
+ } /* end if */
+
+ /* Reset aggregator */
+ aggr->tot_size = 0;
+ aggr->addr = 0;
+ aggr->size = 0;
+ } /* end if */
+ else {
+ /* Check if the section adjoins the beginning or end of the aggregator */
+ if(H5F_addr_eq((sect->sect_info.addr + sect->sect_info.size), aggr->addr)) {
+#ifdef H5MF_AGGR_DBEUG
+HDfprintf(stderr, "%s: section {%a, %Hu} adjoins front of aggr = {%a, %Hu}\n", "H5MF_aggr_absorb", sect->sect_info.addr, sect->sect_info.size, aggr->addr, aggr->size);
+#endif /* H5MF_AGGR_DBEUG */
+ /* Absorb section onto front of aggregator */
+ aggr->addr -= sect->sect_info.size;
+ aggr->size += sect->sect_info.size;
+
+ /* Sections absorbed onto front of aggregator count against the total
+ * amount of space aggregated together.
+ */
+ aggr->tot_size -= MIN(aggr->tot_size, sect->sect_info.size);
+ } /* end if */
+ else {
+ /* Sanity check */
+ HDassert(H5F_addr_eq((aggr->addr + aggr->size), sect->sect_info.addr));
+
+#ifdef H5MF_AGGR_DBEUG
+HDfprintf(stderr, "%s: section {%a, %Hu} adjoins end of aggr = {%a, %Hu}\n", "H5MF_aggr_absorb", sect->sect_info.addr, sect->sect_info.size, aggr->addr, aggr->size);
+#endif /* H5MF_AGGR_DBEUG */
+ /* Absorb section onto end of aggregator */
+ aggr->size += sect->sect_info.size;
+ } /* end if */
+ /* Sanity check */
+ HDassert(!allow_sect_absorb || (aggr->size < aggr->alloc_size));
+ } /* end else */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5MF_aggr_absorb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_aggr_query
+ *
+ * Purpose: Query a block aggregator's current address & size info
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, December 13, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5MF_aggr_query(const H5F_t *f, const H5F_blk_aggr_t *aggr, haddr_t *addr,
+ hsize_t *size)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5MF_aggr_query)
+
+ /* Check args */
+ HDassert(f);
+ HDassert(aggr);
+ HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA);
+
+ /* Check if this aggregator is active */
+ if(f->shared->feature_flags & aggr->feature_flag) {
+ *addr = aggr->addr;
+ *size = aggr->size;
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5MF_aggr_query() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_aggr_reset
+ *
+ * Purpose: Reset a block aggregator, returning any space back to file
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, December 13, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5MF_aggr_reset(H5F_t *f, hid_t dxpl_id, H5F_blk_aggr_t *aggr)
+{
+ H5FD_mem_t alloc_type; /* Type of file memory to work with */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5MF_aggr_reset, FAIL)
+
+ /* Check args */
+ HDassert(f);
+ HDassert(aggr);
+ HDassert(aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA || aggr->feature_flag == H5FD_FEAT_AGGREGATE_SMALLDATA);
+
+ /* Set the type of memory in the file */
+ alloc_type = (aggr->feature_flag == H5FD_FEAT_AGGREGATE_METADATA ? H5FD_MEM_DEFAULT : H5FD_MEM_DRAW); /* Type of file memory to work with */
+
+ /* Check if this aggregator is active */
+ if(f->shared->feature_flags & aggr->feature_flag) {
+ haddr_t tmp_addr; /* Temporary holder for aggregator address */
+ hsize_t tmp_size; /* Temporary holder for aggregator size */
+
+ /* Retain aggregator info */
+ tmp_addr = aggr->addr;
+ tmp_size = aggr->size;
+#ifdef H5MF_AGGR_DBEUG
+HDfprintf(stderr, "%s: tmp_addr = %a, tmp_size = %Hu\n", FUNC, tmp_addr, tmp_size);
+#endif /* H5MF_AGGR_DBEUG */
+
+ /* Reset aggregator block information */
+ aggr->tot_size = 0;
+ aggr->addr = 0;
+ aggr->size = 0;
+
+ /* Return the unused portion of the metadata block to the file */
+ if(tmp_size > 0)
+ if(H5FD_free(f->shared->lf, dxpl_id, alloc_type, tmp_addr, tmp_size) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "can't free space")
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MF_aggr_reset() */
+
diff --git a/src/H5MFdbg.c b/src/H5MFdbg.c
new file mode 100644
index 0000000..ca87c83
--- /dev/null
+++ b/src/H5MFdbg.c
@@ -0,0 +1,246 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5MFdbg.c
+ * Jan 31 2008
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: File memory management debugging functions.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5F_PACKAGE /*suppress error about including H5Fpkg */
+#define H5MF_PACKAGE /*suppress error about including H5MFpkg */
+#define H5MF_DEBUGGING /* Need access to file space debugging routines */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fpkg.h" /* File access */
+#include "H5MFpkg.h" /* File memory management */
+
+#ifdef H5MF_ALLOC_DEBUG_DUMP
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+/* User data for free space section iterator callback */
+typedef struct {
+ H5FS_t *fspace; /* Free space manager */
+ FILE *stream; /* Stream for output */
+ int indent; /* Indention amount */
+ int fwidth; /* Field width amount */
+} H5MF_debug_iter_ud_t;
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_sects_debug_cb
+ *
+ * Purpose: Prints debugging info about a free space section for a file
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * January 31 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5MF_sects_debug_cb(const H5FS_section_info_t *_sect, void *_udata)
+{
+ const H5MF_free_section_t *sect = (const H5MF_free_section_t *)_sect; /* Section to dump info */
+ H5MF_debug_iter_ud_t *udata = (H5MF_debug_iter_ud_t *)_udata; /* User data for callbacks */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5MF_sects_debug_cb)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(sect);
+ HDassert(udata);
+
+ /* Print generic section information */
+ HDfprintf(udata->stream, "%*s%-*s %s\n", udata->indent, "", udata->fwidth,
+ "Section type:",
+ (sect->sect_info.type == H5MF_FSPACE_SECT_SIMPLE ? "simple" : "unknown"));
+ HDfprintf(udata->stream, "%*s%-*s %a\n", udata->indent, "", udata->fwidth,
+ "Section address:",
+ sect->sect_info.addr);
+ HDfprintf(udata->stream, "%*s%-*s %Hu\n", udata->indent, "", udata->fwidth,
+ "Section size:",
+ sect->sect_info.size);
+ HDfprintf(udata->stream, "%*s%-*s %Hu\n", udata->indent, "", udata->fwidth,
+ "End of section:",
+ (haddr_t)((sect->sect_info.addr + sect->sect_info.size) - 1));
+ HDfprintf(udata->stream, "%*s%-*s %s\n", udata->indent, "", udata->fwidth,
+ "Section state:",
+ (sect->sect_info.state == H5FS_SECT_LIVE ? "live" : "serialized"));
+
+ /* Dump section-specific debugging information */
+ if(H5FS_sect_debug(udata->fspace, _sect, udata->stream, udata->indent + 3, MAX(0, udata->fwidth - 3)) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_BADITER, FAIL, "can't dump section's debugging info")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MF_sects_debug_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_sects_dump
+ *
+ * Purpose: Prints debugging info about free space sections for a file.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Jan 31 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5MF_sects_dump(H5F_t *f, hid_t dxpl_id, FILE *stream)
+{
+ haddr_t eoa; /* End of allocated space in the file */
+ haddr_t ma_addr = HADDR_UNDEF; /* Base "metadata aggregator" address */
+ hsize_t ma_size = 0; /* Size of "metadata aggregator" */
+ haddr_t sda_addr = HADDR_UNDEF; /* Base "small data aggregator" address */
+ hsize_t sda_size = 0; /* Size of "small data aggregator" */
+ H5FD_mem_t type; /* Memory type for iteration */
+ int indent = 0; /* Amount to indent */
+ int fwidth = 50; /* Field width */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5MF_sects_dump, FAIL)
+#ifdef H5MF_ALLOC_DEBUG
+HDfprintf(stderr, "%s: Dumping file free space sections\n", FUNC);
+#endif /* H5MF_ALLOC_DEBUG */
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(stream);
+
+ /* Retrieve the 'eoa' for the file */
+ if(HADDR_UNDEF == (eoa = H5FD_get_eoa(f->shared->lf, H5FD_MEM_DEFAULT)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "driver get_eoa request failed")
+#ifdef H5MF_ALLOC_DEBUG
+HDfprintf(stderr, "%s: for type = H5FD_MEM_DEFAULT, eoa = %a\n", FUNC, eoa);
+#endif /* H5MF_ALLOC_DEBUG */
+
+ /* Retrieve metadata aggregator info, if available */
+ H5MF_aggr_query(f, &(f->shared->meta_aggr), &ma_addr, &ma_size);
+#ifdef H5MF_ALLOC_DEBUG
+HDfprintf(stderr, "%s: ma_addr = %a, ma_size = %Hu, end of ma = %a\n", FUNC, ma_addr, ma_size, (haddr_t)((ma_addr + ma_size) - 1));
+#endif /* H5MF_ALLOC_DEBUG */
+
+ /* Retrieve 'small data' aggregator info, if available */
+ H5MF_aggr_query(f, &(f->shared->sdata_aggr), &sda_addr, &sda_size);
+#ifdef H5MF_ALLOC_DEBUG
+HDfprintf(stderr, "%s: sda_addr = %a, sda_size = %Hu, end of sda = %a\n", FUNC, sda_addr, sda_size, (haddr_t)((sda_addr + sda_size) - 1));
+#endif /* H5MF_ALLOC_DEBUG */
+
+ /* Iterate over all the free space types that have managers and dump each free list's space */
+ for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type)) {
+ /* Print header for type */
+ HDfprintf(stream, "%*sFile Free Space Info for type = %u:\n", indent, "", (unsigned)type);
+
+ /* Check for this type being mapped to another type */
+ if(H5FD_MEM_DEFAULT == f->shared->fs_type_map[type] ||
+ type == f->shared->fs_type_map[type]) {
+ /* Retrieve the 'eoa' for this file memory type */
+ if(HADDR_UNDEF == (eoa = H5FD_get_eoa(f->shared->lf, type)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "driver get_eoa request failed")
+ HDfprintf(stream, "%*s%-*s %a\n", indent + 3, "", MAX(0, fwidth - 3),
+ "eoa:",
+ eoa);
+
+ /* Print header for sections */
+ HDfprintf(stream, "%*sSections:\n", indent + 3, "");
+
+ /* If there is a free space manager for this type, iterate over them */
+ if(f->shared->fs_man[type]) {
+ H5MF_debug_iter_ud_t udata; /* User data for callbacks */
+
+ /* Prepare user data for section iteration callback */
+ udata.fspace = f->shared->fs_man[type];
+ udata.stream = stream;
+ udata.indent = indent + 6;
+ udata.fwidth = MAX(0, fwidth - 6);
+
+ /* Iterate over all the free space sections */
+ if(H5FS_sect_iterate(f, dxpl_id, f->shared->fs_man[type], H5MF_sects_debug_cb, &udata) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_BADITER, FAIL, "can't iterate over heap's free space")
+ } /* end if */
+ else {
+ /* No sections of this type */
+ HDfprintf(stream, "%*s<none>\n", indent + 6, "");
+ } /* end else */
+ } /* end if */
+ else {
+ HDfprintf(stream, "%*sMapped to type = %u\n", indent, "", (unsigned)f->shared->fs_type_map[type]);
+ } /* end else */
+ } /* end for */
+
+done:
+HDfprintf(stderr, "%s: Done dumping file free space sections\n", FUNC);
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MF_sects_dump() */
+#endif /* H5MF_ALLOC_DEBUG_DUMP */
+
diff --git a/src/H5MFpkg.h b/src/H5MFpkg.h
new file mode 100644
index 0000000..0e69fd0
--- /dev/null
+++ b/src/H5MFpkg.h
@@ -0,0 +1,175 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Programmer: Quincey Koziol <koziol@hdfgroup.org>
+ * Tuesday, January 8, 2008
+ *
+ * Purpose: This file contains declarations which are visible only within
+ * the H5MF package. Source files outside the H5MF package should
+ * include H5MFprivate.h instead.
+ */
+#ifndef H5MF_PACKAGE
+#error "Do not include this file outside the H5MF package!"
+#endif
+
+#ifndef _H5MFpkg_H
+#define _H5MFpkg_H
+
+/* Get package's private header */
+#include "H5MFprivate.h"
+
+/* Other private headers needed by this file */
+#include "H5FSprivate.h" /* File free space */
+
+
+/**************************/
+/* Package Private Macros */
+/**************************/
+
+/* Define this to display information about file allocations */
+/* #define H5MF_ALLOC_DEBUG */
+
+/* Define this to display more information about file allocations */
+/* #define H5MF_ALLOC_DEBUG_MORE */
+
+/* Define this to display more information about block aggregator actions */
+/* #define H5MF_AGGR_DEBUG */
+
+/* Define this to dump free space tracker contents after they've been modified */
+/* #define H5MF_ALLOC_DEBUG_DUMP */
+
+/* Free space section types for file */
+/* (values stored in free space data structures in file) */
+#define H5MF_FSPACE_SECT_SIMPLE 0 /* Section is a range of actual bytes in file */
+
+
+/****************************/
+/* Package Private Typedefs */
+/****************************/
+
+/* File free space section info */
+typedef struct H5MF_free_section_t {
+ H5FS_section_info_t sect_info; /* Free space section information (must be first in struct) */
+#ifdef NOT_YET
+ union {
+ struct {
+ H5HF_indirect_t *parent; /* Indirect block parent for free section's direct block */
+ unsigned par_entry; /* Entry of free section's direct block in parent indirect block */
+ } single;
+ struct {
+ struct H5HF_free_section_t *under; /* Pointer to indirect block underlying row section */
+ unsigned row; /* Row for range of blocks */
+ unsigned col; /* Column for range of blocks */
+ unsigned num_entries; /* Number of entries covered */
+
+ /* Fields that aren't stored */
+ hbool_t checked_out; /* Flag to indicate that a row section is temporarily out of the free space manager */
+ } row;
+ struct {
+ /* Holds either a pointer to an indirect block (if its "live") or
+ * the block offset of it's indirect block (if its "serialized")
+ * (This allows the indirect block that the section is within to
+ * be compared with other sections, whether it's serialized
+ * or not)
+ */
+ union {
+ H5HF_indirect_t *iblock; /* Indirect block for free section */
+ hsize_t iblock_off; /* Indirect block offset in "heap space" */
+ } u;
+ unsigned row; /* Row for range of blocks */
+ unsigned col; /* Column for range of blocks */
+ unsigned num_entries; /* Number of entries covered */
+
+ /* Fields that aren't stored */
+ struct H5HF_free_section_t *parent; /* Pointer to "parent" indirect section */
+ unsigned par_entry; /* Entry within parent indirect section */
+ hsize_t span_size; /* Size of space tracked, in "heap space" */
+ unsigned iblock_entries; /* Number of entries in indirect block where section is located */
+ unsigned rc; /* Reference count of outstanding row & child indirect sections */
+ unsigned dir_nrows; /* Number of direct rows in section */
+ struct H5HF_free_section_t **dir_rows; /* Array of pointers to outstanding row sections */
+ unsigned indir_nents; /* Number of indirect entries in section */
+ struct H5HF_free_section_t **indir_ents; /* Array of pointers to outstanding child indirect sections */
+ } indirect;
+ } u;
+#endif /* NOT_YET */
+} H5MF_free_section_t;
+
+/* Type of "container shrink" operation to perform */
+typedef enum {
+ H5MF_SHRINK_EOA, /* Section should shrink the EOA value */
+ H5MF_SHRINK_AGGR_ABSORB_SECT, /* Section should merge into the aggregator block */
+ H5MF_SHRINK_SECT_ABSORB_AGGR /* Aggregator block should merge into the section */
+} H5MF_shrink_type_t;
+
+/* User data for free space manager section callbacks */
+typedef struct H5MF_sect_ud_t {
+ /* Down */
+ H5F_t *f; /* Pointer to file to operate on */
+ hid_t dxpl_id; /* DXPL for VFD operations */
+ H5FD_mem_t alloc_type; /* Type of memory being allocated */
+ hbool_t allow_sect_absorb; /* Whether sections are allowed to absorb a block aggregator */
+
+ /* Up */
+ H5MF_shrink_type_t shrink; /* Type of shrink operation to perform */
+ H5F_blk_aggr_t *aggr; /* Aggregator block to operate on */
+} H5MF_sect_ud_t;
+
+
+/*****************************/
+/* Package Private Variables */
+/*****************************/
+
+/* H5MF single section inherits serializable properties from H5FS_section_class_t */
+H5_DLLVAR H5FS_section_class_t H5MF_FSPACE_SECT_CLS_SIMPLE[1];
+
+
+/******************************/
+/* Package Private Prototypes */
+/******************************/
+
+/* Allocator routines */
+H5_DLL herr_t H5MF_alloc_start(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type,
+ hbool_t may_create);
+H5_DLL herr_t H5MF_sects_dump(H5F_t *f, hid_t dxpl_id, FILE *stream);
+
+/* 'simple' section routines */
+H5_DLL H5MF_free_section_t *H5MF_sect_simple_new(haddr_t sect_off,
+ hsize_t sect_size);
+H5_DLL htri_t H5MF_sect_simple_can_shrink(const H5FS_section_info_t *_sect,
+ void *udata);
+H5_DLL herr_t H5MF_sect_simple_shrink(H5FS_section_info_t **_sect,
+ void *udata);
+H5_DLL herr_t H5MF_sect_simple_free(H5FS_section_info_t *sect);
+
+/* Block aggregator routines */
+H5_DLL haddr_t H5MF_aggr_alloc(H5F_t *f, hid_t dxpl_id, H5F_blk_aggr_t *aggr,
+ H5F_blk_aggr_t *other_aggr, H5FD_mem_t type, hsize_t size);
+H5_DLL htri_t H5MF_aggr_try_extend(const H5F_t *f, H5F_blk_aggr_t *aggr,
+ H5FD_mem_t type, haddr_t abs_blk_end, hsize_t extra_requested);
+H5_DLL htri_t H5MF_aggr_can_absorb(const H5F_t *f, const H5F_blk_aggr_t *aggr,
+ const H5MF_free_section_t *sect, H5MF_shrink_type_t *shrink);
+H5_DLL herr_t H5MF_aggr_absorb(const H5F_t *f, H5F_blk_aggr_t *aggr,
+ H5MF_free_section_t *sect, hbool_t allow_sect_absorb);
+H5_DLL herr_t H5MF_aggr_query(const H5F_t *f, const H5F_blk_aggr_t *aggr,
+ haddr_t *addr, hsize_t *size);
+
+/* Testing routines */
+#ifdef H5MF_TESTING
+#endif /* H5MF_TESTING */
+
+#endif /* _H5MFpkg_H */
+
diff --git a/src/H5MFprivate.h b/src/H5MFprivate.h
index 09ed582..0d1da8a 100644
--- a/src/H5MFprivate.h
+++ b/src/H5MFprivate.h
@@ -29,9 +29,12 @@
#define _H5MFprivate_H
/* Private headers needed by this file */
-#include "H5private.h"
-#include "H5Fprivate.h"
-#include "H5FDprivate.h" /*file driver */
+#include "H5Fprivate.h" /* File access */
+#include "H5FDprivate.h" /* File Drivers */
+
+/**************************/
+/* Library Private Macros */
+/**************************/
/*
* Feature: Define H5MF_DEBUG on the compiler command line if you want to
@@ -41,18 +44,44 @@
# undef H5MF_DEBUG
#endif
-/*
- * Library prototypes...
- */
+/****************************/
+/* Library Private Typedefs */
+/****************************/
+
+
+/*****************************/
+/* Library-private Variables */
+/*****************************/
+
+
+/***************************************/
+/* Library-private Function Prototypes */
+/***************************************/
+
+/* File space manager routines */
+H5_DLL herr_t H5MF_init_merge_flags(H5F_t *f);
+H5_DLL hssize_t H5MF_get_freespace(H5F_t *f, hid_t dxpl_id);
+H5_DLL herr_t H5MF_close(H5F_t *f, hid_t dxpl_id);
+
+/* File space allocation routines */
H5_DLL haddr_t H5MF_alloc(H5F_t *f, H5FD_mem_t type, hid_t dxpl_id, hsize_t size);
H5_DLL herr_t H5MF_xfree(H5F_t *f, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr,
hsize_t size);
-H5_DLL haddr_t H5MF_realloc(H5F_t *f, H5FD_mem_t type, hid_t dxpl_id, haddr_t old_addr,
- hsize_t old_size, hsize_t new_size);
-H5_DLL hbool_t H5MF_alloc_overflow(H5F_t *f, hsize_t size);
-H5_DLL htri_t H5MF_can_extend(H5F_t *f, H5FD_mem_t type, haddr_t addr,
- hsize_t size, hsize_t extra_requested);
-H5_DLL herr_t H5MF_extend(H5F_t *f, H5FD_mem_t type, haddr_t addr, hsize_t size,
- hsize_t extra_requested);
+H5_DLL herr_t H5MF_try_extend(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type,
+ haddr_t addr, hsize_t size, hsize_t extra_requested);
+H5_DLL htri_t H5MF_try_shrink(H5F_t *f, H5FD_mem_t alloc_type, hid_t dxpl_id,
+ haddr_t addr, hsize_t size);
+
+/* 'block aggregator' routines */
+H5_DLL herr_t H5MF_aggr_reset(H5F_t *file, hid_t dxpl_id, H5F_blk_aggr_t *aggr);
+
+/* Debugging routines */
+#ifdef H5MF_DEBUGGING
+#ifdef NOT_YET
+H5_DLL herr_t H5MF_sects_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr,
+ FILE *stream, int indent, int fwidth);
+#endif /* NOT_YET */
+#endif /* H5MF_DEBUGGING */
+
+#endif /* end _H5MFprivate_H */
-#endif
diff --git a/src/H5MFsection.c b/src/H5MFsection.c
new file mode 100644
index 0000000..200195a
--- /dev/null
+++ b/src/H5MFsection.c
@@ -0,0 +1,531 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Programmer: Quincey Koziol <koziol@hdfgroup.org>
+ * Tuesday, January 8, 2008
+ *
+ * Purpose: Free space section callbacks for file.
+ *
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5F_PACKAGE /*suppress error about including H5Fpkg */
+#define H5MF_PACKAGE /*suppress error about including H5MFpkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fpkg.h" /* File access */
+#include "H5MFpkg.h" /* File memory management */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+/* 'simple' section callbacks */
+static H5FS_section_info_t *H5MF_sect_simple_deserialize(const H5FS_section_class_t *cls,
+ hid_t dxpl_id, const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size,
+ unsigned *des_flags);
+static htri_t H5MF_sect_simple_can_merge(const H5FS_section_info_t *sect1,
+ const H5FS_section_info_t *sect2, void *udata);
+static herr_t H5MF_sect_simple_merge(H5FS_section_info_t *sect1,
+ H5FS_section_info_t *sect2, void *udata);
+static herr_t H5MF_sect_simple_valid(const H5FS_section_class_t *cls,
+ const H5FS_section_info_t *sect);
+static H5FS_section_info_t *H5MF_sect_simple_split(H5FS_section_info_t *sect,
+ hsize_t frag_size);
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+/* Class info for "simple" free space sections */
+H5FS_section_class_t H5MF_FSPACE_SECT_CLS_SIMPLE[1] = {{
+ /* Class variables */
+ H5MF_FSPACE_SECT_SIMPLE, /* Section type */
+ 0, /* Extra serialized size */
+ H5FS_CLS_MERGE_SYM | H5FS_CLS_ADJUST_OK, /* Class flags */
+ NULL, /* Class private info */
+
+ /* Class methods */
+ NULL, /* Initialize section class */
+ NULL, /* Terminate section class */
+
+ /* Object methods */
+ NULL, /* Add section */
+ NULL, /* Serialize section */
+ H5MF_sect_simple_deserialize, /* Deserialize section */
+ H5MF_sect_simple_can_merge, /* Can sections merge? */
+ H5MF_sect_simple_merge, /* Merge sections */
+ H5MF_sect_simple_can_shrink, /* Can section shrink container?*/
+ H5MF_sect_simple_shrink, /* Shrink container w/section */
+ H5MF_sect_simple_free, /* Free section */
+ H5MF_sect_simple_valid, /* Check validity of section */
+ H5MF_sect_simple_split, /* Split section node for alignment */
+ NULL, /* Dump debugging for section */
+}};
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* Declare a free list to manage the H5MF_free_section_t struct */
+H5FL_DEFINE(H5MF_free_section_t);
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_sect_simple_new
+ *
+ * Purpose: Create a new 'simple' section and return it to the caller
+ *
+ * Return: Pointer to new section on success/NULL on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * January 8 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+H5MF_free_section_t *
+H5MF_sect_simple_new(haddr_t sect_off, hsize_t sect_size)
+{
+ H5MF_free_section_t *sect = NULL; /* 'Simple' free space section to add */
+ H5MF_free_section_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5MF_sect_simple_new)
+
+ /* Check arguments. */
+ HDassert(sect_size);
+
+ /* Create free space section node */
+ if(NULL == (sect = H5FL_MALLOC(H5MF_free_section_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for direct block free list section")
+
+ /* Set the information passed in */
+ sect->sect_info.addr = sect_off;
+ sect->sect_info.size = sect_size;
+
+ /* Set the section's class & state */
+ sect->sect_info.type = H5MF_FSPACE_SECT_SIMPLE;
+ sect->sect_info.state = H5FS_SECT_LIVE;
+
+ /* Set return value */
+ ret_value = sect;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MF_sect_simple_new() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_sect_simple_deserialize
+ *
+ * Purpose: Deserialize a buffer into a "live" single section
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, January 8, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5FS_section_info_t *
+H5MF_sect_simple_deserialize(const H5FS_section_class_t UNUSED *cls,
+ hid_t UNUSED dxpl_id, const uint8_t UNUSED *buf, haddr_t sect_addr,
+ hsize_t sect_size, unsigned UNUSED *des_flags)
+{
+ H5MF_free_section_t *sect; /* New section */
+ H5FS_section_info_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5MF_sect_simple_deserialize)
+
+ /* Check arguments. */
+ HDassert(H5F_addr_defined(sect_addr));
+ HDassert(sect_size);
+
+ /* Create free space section for block */
+ if(NULL == (sect = H5MF_sect_simple_new(sect_addr, sect_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, NULL, "can't initialize free space section")
+
+ /* Set return value */
+ ret_value = (H5FS_section_info_t *)sect;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5MF_sect_simple_deserialize() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_sect_simple_can_merge
+ *
+ * Purpose: Can two sections of this type merge?
+ *
+ * Note: Second section must be "after" first section
+ *
+ * Return: Success: non-negative (TRUE/FALSE)
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, January 8, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static htri_t
+H5MF_sect_simple_can_merge(const H5FS_section_info_t *_sect1,
+ const H5FS_section_info_t *_sect2, void UNUSED *_udata)
+{
+ const H5MF_free_section_t *sect1 = (const H5MF_free_section_t *)_sect1; /* File free section */
+ const H5MF_free_section_t *sect2 = (const H5MF_free_section_t *)_sect2; /* File free section */
+ htri_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5MF_sect_simple_can_merge)
+
+ /* Check arguments. */
+ HDassert(sect1);
+ HDassert(sect2);
+ HDassert(sect1->sect_info.type == sect2->sect_info.type); /* Checks "MERGE_SYM" flag */
+ HDassert(H5F_addr_lt(sect1->sect_info.addr, sect2->sect_info.addr));
+
+ /* Check if second section adjoins first section */
+ ret_value = H5F_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5MF_sect_simple_can_merge() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_sect_simple_merge
+ *
+ * Purpose: Merge two sections of this type
+ *
+ * Note: Second section always merges into first node
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, January 8, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5MF_sect_simple_merge(H5FS_section_info_t *_sect1, H5FS_section_info_t *_sect2,
+ void UNUSED *_udata)
+{
+ H5MF_free_section_t *sect1 = (H5MF_free_section_t *)_sect1; /* File free section */
+ H5MF_free_section_t *sect2 = (H5MF_free_section_t *)_sect2; /* File free section */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5MF_sect_simple_merge)
+
+ /* Check arguments. */
+ HDassert(sect1);
+ HDassert(sect1->sect_info.type == H5MF_FSPACE_SECT_SIMPLE);
+ HDassert(sect2);
+ HDassert(sect2->sect_info.type == H5MF_FSPACE_SECT_SIMPLE);
+ HDassert(H5F_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr));
+
+ /* Add second section's size to first section */
+ sect1->sect_info.size += sect2->sect_info.size;
+
+ /* Get rid of second section */
+ if(H5MF_sect_simple_free((H5FS_section_info_t *)sect2) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free section node")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5MF_sect_simple_merge() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_sect_simple_can_shrink
+ *
+ * Purpose: Can this section shrink the container?
+ *
+ * Return: Success: non-negative (TRUE/FALSE)
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, January 8, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5MF_sect_simple_can_shrink(const H5FS_section_info_t *_sect, void *_udata)
+{
+ const H5MF_free_section_t *sect = (const H5MF_free_section_t *)_sect; /* File free section */
+ H5MF_sect_ud_t *udata = (H5MF_sect_ud_t *)_udata; /* User data for callback */
+ haddr_t eoa; /* End of address space in the file */
+ haddr_t end; /* End of section to extend */
+ htri_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5MF_sect_simple_can_shrink)
+
+ /* Check arguments. */
+ HDassert(sect);
+ HDassert(udata);
+ HDassert(udata->f);
+
+ /* Retrieve the end of the file's address space */
+ if(HADDR_UNDEF == (eoa = H5FD_get_eoa(udata->f->shared->lf, udata->alloc_type)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "driver get_eoa request failed")
+
+ /* Compute address of end of section to check */
+ end = sect->sect_info.addr + sect->sect_info.size;
+
+ /* Check if the section is exactly at the end of the allocated space in the file */
+ if(H5F_addr_eq(end, eoa)) {
+ /* Set the shrinking type */
+ udata->shrink = H5MF_SHRINK_EOA;
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: section {%a, %Hu}, shrinks file, eoa = %a\n", FUNC, sect->sect_info.addr, sect->sect_info.size, eoa);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+
+ /* Indicate shrinking can occur */
+ HGOTO_DONE(TRUE)
+ } /* end if */
+ else {
+ /* Check if this section is allowed to merge with metadata aggregation block */
+ if(udata->f->shared->fs_aggr_merge[udata->alloc_type] & H5F_FS_MERGE_METADATA) {
+ htri_t status; /* Status from aggregator adjoin */
+
+ /* See if section can absorb the aggregator & vice versa */
+ if((status = H5MF_aggr_can_absorb(udata->f, &(udata->f->shared->meta_aggr), sect, &(udata->shrink))) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTMERGE, FAIL, "error merging section with aggregation block")
+ else if(status > 0) {
+ /* Set the aggregator to operate on */
+ udata->aggr = &(udata->f->shared->meta_aggr);
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: section {%a, %Hu}, adjoins metadata aggregator\n", FUNC, sect->sect_info.addr, sect->sect_info.size);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+
+ /* Indicate shrinking can occur */
+ HGOTO_DONE(TRUE)
+ } /* end if */
+ } /* end if */
+
+ /* Check if this section is allowed to merge with small 'raw' aggregation block */
+ if(udata->f->shared->fs_aggr_merge[udata->alloc_type] & H5F_FS_MERGE_RAWDATA) {
+ htri_t status; /* Status from aggregator adjoin */
+
+ /* See if section can absorb the aggregator & vice versa */
+ if((status = H5MF_aggr_can_absorb(udata->f, &(udata->f->shared->sdata_aggr), sect, &(udata->shrink))) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTMERGE, FAIL, "error merging section with aggregation block")
+ else if(status > 0) {
+ /* Set the aggregator to operate on */
+ udata->aggr = &(udata->f->shared->sdata_aggr);
+#ifdef H5MF_ALLOC_DEBUG_MORE
+HDfprintf(stderr, "%s: section {%a, %Hu}, adjoins small data aggregator\n", FUNC, sect->sect_info.addr, sect->sect_info.size);
+#endif /* H5MF_ALLOC_DEBUG_MORE */
+
+ /* Indicate shrinking can occur */
+ HGOTO_DONE(TRUE)
+ } /* end if */
+ } /* end if */
+ } /* end else */
+
+ /* Set return value */
+ ret_value = FALSE;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5MF_sect_simple_can_shrink() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_sect_simple_shrink
+ *
+ * Purpose: Shrink container with section
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, January 8, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5MF_sect_simple_shrink(H5FS_section_info_t **_sect, void *_udata)
+{
+ H5MF_free_section_t **sect = (H5MF_free_section_t **)_sect; /* File free section */
+ H5MF_sect_ud_t *udata = (H5MF_sect_ud_t *)_udata; /* User data for callback */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5MF_sect_simple_shrink)
+
+ /* Check arguments. */
+ HDassert(sect);
+ HDassert(udata);
+ HDassert(udata->f);
+
+ /* Check for shrinking file */
+ if(H5MF_SHRINK_EOA == udata->shrink) {
+ /* Release section's space at EOA with file driver */
+ if(H5FD_free(udata->f->shared->lf, udata->dxpl_id, udata->alloc_type, (*sect)->sect_info.addr, (*sect)->sect_info.size) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "driver free request failed")
+ } /* end if */
+ else {
+ /* Sanity check */
+ HDassert(udata->aggr);
+
+ /* Absorb the section into the aggregator or vice versa */
+ if(H5MF_aggr_absorb(udata->f, udata->aggr, *sect, udata->allow_sect_absorb) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTMERGE, FAIL, "can't absorb section into aggregator or vice versa")
+ } /* end else */
+
+ /* Check for freeing section */
+ if(udata->shrink != H5MF_SHRINK_SECT_ABSORB_AGGR) {
+ /* Free section */
+ if(H5MF_sect_simple_free((H5FS_section_info_t *)*sect) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free simple section node")
+
+ /* Mark section as freed, for free space manager */
+ *sect = NULL;
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5MF_sect_simple_shrink() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_sect_simple_free
+ *
+ * Purpose: Free a 'single' section node
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, January 8, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5MF_sect_simple_free(H5FS_section_info_t *_sect)
+{
+ H5MF_free_section_t *sect = (H5MF_free_section_t *)_sect; /* File free section */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5MF_sect_simple_free)
+
+ /* Check arguments. */
+ HDassert(sect);
+
+ /* Release the section */
+ (void)H5FL_FREE(H5MF_free_section_t, sect);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5MF_sect_simple_free() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_sect_simple_valid
+ *
+ * Purpose: Check the validity of a section
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, January 8, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5MF_sect_simple_valid(const H5FS_section_class_t UNUSED *cls,
+ const H5FS_section_info_t
+#ifdef NDEBUG
+ UNUSED
+#endif /* NDEBUG */
+ *_sect)
+{
+#ifndef NDEBUG
+ const H5MF_free_section_t *sect = (const H5MF_free_section_t *)_sect; /* File free section */
+#endif /* NDEBUG */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5MF_sect_simple_valid)
+
+ /* Check arguments. */
+ HDassert(sect);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5MF_sect_simple_valid() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MF_sect_simple_split
+ *
+ * Purpose: Split SECT into 2 sections: fragment for alignment & the aligned section
+ * SECT's addr and size are updated to point to the aligned section
+ *
+ * Return: Success: the fragment for aligning sect
+ * Failure: null
+ *
+ * Programmer: Vailin Choi, July 29, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5FS_section_info_t *
+H5MF_sect_simple_split(H5FS_section_info_t *sect, hsize_t frag_size)
+{
+ H5MF_free_section_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5MF_sect_simple_split)
+
+ /* Allocate space for new section */
+ if(NULL == (ret_value = H5MF_sect_simple_new(sect->addr, frag_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, NULL, "can't initialize free space section")
+
+ /* Set new section's info */
+ sect->addr += frag_size;
+ sect->size -= frag_size;
+
+done:
+ FUNC_LEAVE_NOAPI((H5FS_section_info_t *)ret_value)
+} /* end H5MF_sect_simple_split() */
+
+
diff --git a/src/H5MM.c b/src/H5MM.c
index cd246e5..14e847b 100644
--- a/src/H5MM.c
+++ b/src/H5MM.c
@@ -177,7 +177,7 @@ H5MM_xstrdup(const char *s)
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5MM_xstrdup)
if(s) {
- ret_value = H5MM_malloc(HDstrlen(s) + 1);
+ ret_value = (char *)H5MM_malloc(HDstrlen(s) + 1);
HDassert(ret_value);
HDstrcpy(ret_value, s);
} /* end if */
@@ -210,17 +210,17 @@ H5MM_strdup(const char *s)
{
char *ret_value;
- FUNC_ENTER_NOAPI(H5MM_strdup, NULL);
+ FUNC_ENTER_NOAPI(H5MM_strdup, NULL)
- if (!s)
- HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, NULL, "null string");
- if (NULL==(ret_value = H5MM_malloc(HDstrlen(s) + 1)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
+ if(!s)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "null string")
+ if(NULL == (ret_value = (char *)H5MM_malloc(HDstrlen(s) + 1)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
HDstrcpy(ret_value, s);
done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MM_strdup() */
/*-------------------------------------------------------------------------
diff --git a/src/H5MP.c b/src/H5MP.c
index e7be06f..63a65ae 100644
--- a/src/H5MP.c
+++ b/src/H5MP.c
@@ -147,14 +147,14 @@ H5MP_new_page(H5MP_pool_t *mp, size_t page_size)
/* Allocate page */
if(page_size > mp->page_size) {
- if(NULL == (new_page = H5MM_malloc(page_size)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for page")
+ if(NULL == (new_page = (H5MP_page_t *)H5MM_malloc(page_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for page")
new_page->free_size = page_size - H5MP_BLOCK_ALIGN(sizeof(H5MP_page_t));
new_page->fac_alloc = FALSE;
} /* end if */
else {
- if((new_page = H5FL_FAC_MALLOC(mp->page_fac)) == NULL)
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for page")
+ if(NULL == (new_page = (H5MP_page_t *)H5FL_FAC_MALLOC(mp->page_fac)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for page")
new_page->free_size = mp->max_size;
new_page->fac_alloc = TRUE;
} /* end else */
@@ -461,7 +461,7 @@ H5MP_close (H5MP_pool_t *mp)
HGOTO_ERROR (H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't destroy page factory")
/* Free the memory pool itself */
- H5FL_FREE(H5MP_pool_t, mp);
+ (void)H5FL_FREE(H5MP_pool_t, mp);
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5O.c b/src/H5O.c
index 94435f5..52338cc 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -57,6 +57,17 @@
/* Local Typedefs */
/******************/
+/* User data for recursive traversal over objects from a group */
+typedef struct {
+ hid_t obj_id; /* The ID for the starting group */
+ H5G_loc_t *start_loc; /* Location of starting group */
+ hid_t lapl_id; /* LAPL for walking across links */
+ hid_t dxpl_id; /* DXPL for operations */
+ H5SL_t *visited; /* Skip list for tracking visited nodes */
+ H5O_iterate_t op; /* Application callback */
+ void *op_data; /* Application's op data */
+} H5O_iter_visit_ud_t;
+
/********************/
/* Package Typedefs */
@@ -70,6 +81,9 @@
static herr_t H5O_delete_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh);
static const H5O_obj_class_t *H5O_obj_class(const H5O_loc_t *loc, hid_t dxpl_id);
static herr_t H5O_obj_type_real(H5O_t *oh, H5O_type_t *obj_type);
+static herr_t H5O_visit(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
+ H5_iter_order_t order, H5O_iterate_t op, void *op_data, hid_t lapl_id,
+ hid_t dxpl_id);
/*********************/
@@ -77,6 +91,11 @@ static herr_t H5O_obj_type_real(H5O_t *oh, H5O_type_t *obj_type);
/*********************/
/* Header message ID to class mapping */
+
+/* Remember to increment H5O_MSG_TYPES in H5Opkg.h when adding a new
+ * message.
+ */
+
const H5O_msg_class_t *const H5O_msg_class_g[] = {
H5O_MSG_NULL, /*0x0000 Null */
H5O_MSG_SDSPACE, /*0x0001 Dataspace */
@@ -140,6 +159,9 @@ H5FL_BLK_DEFINE(chunk_image);
/* Declare external the free list for time_t's */
H5FL_EXTERN(time_t);
+/* Declare external the free list for H5_obj_t's */
+H5FL_EXTERN(H5_obj_t);
+
/*******************/
/* Local Variables */
@@ -157,6 +179,10 @@ H5FL_EXTERN(time_t);
* Programmer: Quincey Koziol
* Thursday, January 18, 2007
*
+ * Changes: JRM -- 12/12/07
+ * Added santity check verifying that H5O_msg_class_g
+ * is big enough.
+ *
*-------------------------------------------------------------------------
*/
static herr_t
@@ -168,6 +194,8 @@ H5O_init_interface(void)
HDassert(H5O_MSG_TYPES == NELMTS(H5O_msg_class_g));
HDassert(sizeof(H5O_fheap_id_t) == H5O_FHEAP_ID_LEN);
+ HDassert(H5O_UNKNOWN_ID < H5O_MSG_TYPES);
+
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_init_interface() */
@@ -210,7 +238,7 @@ H5Oopen(hid_t loc_id, const char *name, hid_t lapl_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name")
/* Open the object */
- if((ret_value = H5O_open_name(&loc, name, lapl_id)) < 0)
+ if((ret_value = H5O_open_name(&loc, name, lapl_id, TRUE)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open object")
done:
@@ -281,7 +309,7 @@ H5Oopen_by_idx(hid_t loc_id, const char *group_name, H5_index_t idx_type,
loc_found = TRUE;
/* Open the object */
- if((ret_value = H5O_open_by_loc(&obj_loc, H5AC_dxpl_id)) < 0)
+ if((ret_value = H5O_open_by_loc(&obj_loc, lapl_id, H5AC_dxpl_id, TRUE)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open object")
done:
@@ -314,7 +342,7 @@ done:
* H5Odecr_refcount() should be used when the object is
* no longer being referenced by address (e.g. when the UD link
* is deleted).
- *
+ *
* The address of the HDF5 file on disk has no effect on
* H5Oopen_by_addr(), nor does the use of any unusual file
* drivers. The "address" is really the offset within the
@@ -337,6 +365,7 @@ H5Oopen_by_addr(hid_t loc_id, haddr_t addr)
H5G_name_t obj_path; /* Opened object group hier. path */
H5O_loc_t obj_oloc; /* Opened object object location */
hbool_t loc_found = FALSE; /* Location at 'name' found */
+ hid_t lapl_id = H5P_LINK_ACCESS_DEFAULT; /* lapl to use to open this object */
hid_t ret_value = FAIL;
FUNC_ENTER_API(H5Oopen_by_addr, FAIL)
@@ -357,7 +386,7 @@ H5Oopen_by_addr(hid_t loc_id, haddr_t addr)
H5G_name_reset(obj_loc.path); /* objects opened through this routine don't have a path name */
/* Open the object */
- if((ret_value = H5O_open_by_loc(&obj_loc, H5AC_dxpl_id)) < 0)
+ if((ret_value = H5O_open_by_loc(&obj_loc, lapl_id, H5AC_dxpl_id, TRUE)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open object")
done:
@@ -827,6 +856,130 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5Ovisit
+ *
+ * Purpose: Recursively visit an object and all the objects reachable
+ * from it. If the starting object is a group, all the objects
+ * linked to from that group will be visited. Links within
+ * each group are visited according to the order within the
+ * specified index (unless the specified index does not exist for
+ * a particular group, then the "name" index is used).
+ *
+ * NOTE: Soft links and user-defined links are ignored during
+ * this operation.
+ *
+ * NOTE: Each _object_ reachable from the initial group will only
+ * be visited once. If multiple hard links point to the same
+ * object, the first link to the object's path (according to the
+ * iteration index and iteration order given) will be used to in
+ * the callback about the object.
+ *
+ * Return: Success: The return value of the first operator that
+ * returns non-zero, or zero if all members were
+ * processed with no operator returning non-zero.
+ *
+ * Failure: Negative if something goes wrong within the
+ * library, or the negative value returned by one
+ * of the operators.
+ *
+ * Programmer: Quincey Koziol
+ * November 25 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Ovisit(hid_t obj_id, H5_index_t idx_type, H5_iter_order_t order,
+ H5O_iterate_t op, void *op_data)
+{
+ herr_t ret_value; /* Return value */
+
+ FUNC_ENTER_API(H5Ovisit, FAIL)
+ H5TRACE5("e", "iIiIox*x", obj_id, idx_type, order, op, op_data);
+
+ /* Check args */
+ if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified")
+ if(order <= H5_ITER_UNKNOWN || order >= H5_ITER_N)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified")
+ if(!op)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no callback operator specified")
+
+ /* Call internal object visitation routine */
+ if((ret_value = H5O_visit(obj_id, ".", idx_type, order, op, op_data, H5P_LINK_ACCESS_DEFAULT, H5AC_ind_dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "object visitation failed")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Ovisit() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Ovisit_by_name
+ *
+ * Purpose: Recursively visit an object and all the objects reachable
+ * from it. If the starting object is a group, all the objects
+ * linked to from that group will be visited. Links within
+ * each group are visited according to the order within the
+ * specified index (unless the specified index does not exist for
+ * a particular group, then the "name" index is used).
+ *
+ * NOTE: Soft links and user-defined links are ignored during
+ * this operation.
+ *
+ * NOTE: Each _object_ reachable from the initial group will only
+ * be visited once. If multiple hard links point to the same
+ * object, the first link to the object's path (according to the
+ * iteration index and iteration order given) will be used to in
+ * the callback about the object.
+ *
+ * Return: Success: The return value of the first operator that
+ * returns non-zero, or zero if all members were
+ * processed with no operator returning non-zero.
+ *
+ * Failure: Negative if something goes wrong within the
+ * library, or the negative value returned by one
+ * of the operators.
+ *
+ * Programmer: Quincey Koziol
+ * November 24 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Ovisit_by_name(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
+ H5_iter_order_t order, H5O_iterate_t op, void *op_data, hid_t lapl_id)
+{
+ herr_t ret_value; /* Return value */
+
+ FUNC_ENTER_API(H5Ovisit_by_name, FAIL)
+ H5TRACE7("e", "i*sIiIox*xi", loc_id, obj_name, idx_type, order, op, op_data,
+ lapl_id);
+
+ /* Check args */
+ if(!obj_name || !*obj_name)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name")
+ if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified")
+ if(order <= H5_ITER_UNKNOWN || order >= H5_ITER_N)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified")
+ if(!op)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no callback operator specified")
+ if(H5P_DEFAULT == lapl_id)
+ lapl_id = H5P_LINK_ACCESS_DEFAULT;
+ else
+ if(TRUE != H5P_isa_class(lapl_id, H5P_LINK_ACCESS))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link access property list ID")
+
+ /* Call internal object visitation routine */
+ if((ret_value = H5O_visit(loc_id, obj_name, idx_type, order, op, op_data, lapl_id, H5AC_ind_dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "object visitation failed")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Ovisit_by_name() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5Oclose
*
* Purpose: Close an open file object.
@@ -860,7 +1013,7 @@ H5Oclose(hid_t object_id)
case(H5I_DATASET):
if(H5I_object(object_id) == NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a valid object")
- if(H5I_dec_ref(object_id) < 0)
+ if(H5I_dec_ref(object_id, TRUE) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to close object")
break;
@@ -910,14 +1063,16 @@ H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, hid_t ocpl_id,
/* check args */
HDassert(f);
+ HDassert(f->intent & H5F_ACC_RDWR);
HDassert(loc);
HDassert(TRUE == H5P_isa_class(ocpl_id, H5P_OBJECT_CREATE));
+
/* Make certain we allocate at least a reasonable size for the object header */
size_hint = H5O_ALIGN_F(f, MAX(H5O_MIN_SIZE, size_hint));
/* Get the property list */
- if(NULL == (oc_plist = H5I_object(ocpl_id)))
+ if(NULL == (oc_plist = (H5P_genplist_t *)H5I_object(ocpl_id)))
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a property list")
/* Get any object header status flags set by properties */
@@ -936,6 +1091,14 @@ H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, hid_t ocpl_id,
oh->version = H5O_VERSION_1;
oh->sizeof_size = H5F_SIZEOF_SIZE(f);
oh->sizeof_addr = H5F_SIZEOF_ADDR(f);
+#ifdef H5O_ENABLE_BAD_MESG_COUNT
+ /* Check whether the "bad message count" property is set */
+ if(H5P_exist_plist(oc_plist, H5O_BAD_MESG_COUNT_NAME) > 0) {
+ /* Retrieve bad message count flag */
+ if(H5P_get(oc_plist, H5O_BAD_MESG_COUNT_NAME, &oh->store_bad_mesg_count) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't get bad message count flag")
+ } /* end if */
+#endif /* H5O_ENABLE_BAD_MESG_COUNT */
/* Set initial status flags */
oh->flags = oh_flags;
@@ -1003,7 +1166,7 @@ H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, hid_t ocpl_id,
/* Put magic # for object header in first chunk */
if(oh->version > H5O_VERSION_1)
- HDmemcpy(oh->chunk[0].image, H5O_HDR_MAGIC, (size_t)H5O_SIZEOF_MAGIC);
+ HDmemcpy(oh->chunk[0].image, H5O_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
/* Create the message list */
oh->nmesgs = 1;
@@ -1054,7 +1217,7 @@ done:
* Modification:
* Raymond Lu
* 5 November 2007
- * Turn off the holding file variable if it's on. When it's
+ * Turn off the holding file variable if it's on. When it's
* needed, the caller will turn it on again.
*-------------------------------------------------------------------------
*/
@@ -1099,7 +1262,7 @@ done:
*-------------------------------------------------------------------------
*/
hid_t
-H5O_open_name(H5G_loc_t *loc, const char *name, hid_t lapl_id)
+H5O_open_name(H5G_loc_t *loc, const char *name, hid_t lapl_id, hbool_t app_ref)
{
H5G_loc_t obj_loc; /* Location used to open group */
H5G_name_t obj_path; /* Opened object group hier. path */
@@ -1124,7 +1287,7 @@ H5O_open_name(H5G_loc_t *loc, const char *name, hid_t lapl_id)
loc_found = TRUE;
/* Open the object */
- if((ret_value = H5O_open_by_loc(&obj_loc, H5AC_dxpl_id)) < 0)
+ if((ret_value = H5O_open_by_loc(&obj_loc, lapl_id, H5AC_ind_dxpl_id, app_ref)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open object")
done:
@@ -1150,7 +1313,7 @@ done:
*-------------------------------------------------------------------------
*/
hid_t
-H5O_open_by_loc(const H5G_loc_t *obj_loc, hid_t dxpl_id)
+H5O_open_by_loc(const H5G_loc_t *obj_loc, hid_t lapl_id, hid_t dxpl_id, hbool_t app_ref)
{
const H5O_obj_class_t *obj_class; /* Class of object for location */
hid_t ret_value; /* Return value */
@@ -1165,7 +1328,7 @@ H5O_open_by_loc(const H5G_loc_t *obj_loc, hid_t dxpl_id)
/* Call the object class's 'open' routine */
HDassert(obj_class->open);
- if((ret_value = obj_class->open(obj_loc, dxpl_id)) < 0)
+ if((ret_value = obj_class->open(obj_loc, lapl_id, dxpl_id, app_ref)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open object")
done:
@@ -1215,7 +1378,7 @@ H5O_close(H5O_loc_t *loc)
* If the file open object count has reached the number of open mount points
* (each of which has a group open in the file) attempt to close the file.
*/
- if(loc->file->nopen_objs == loc->file->mtab.nmounts)
+ if(loc->file->nopen_objs == loc->file->nmounts)
/* Attempt to close down the file hierarchy */
if(H5F_try_close(loc->file) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTCLOSEFILE, FAIL, "problem attempting file close")
@@ -1262,7 +1425,7 @@ H5O_link(const H5O_loc_t *loc, int adjust, hid_t dxpl_id)
/* get header */
oh_acc = adjust ? H5AC_WRITE : H5AC_READ;
- if(NULL == (oh = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, oh_acc)))
+ if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, oh_acc)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
/* Check for adjusting link count */
@@ -1288,7 +1451,7 @@ H5O_link(const H5O_loc_t *loc, int adjust, hid_t dxpl_id)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't delete object from file")
/* Mark the object header as deleted */
- oh_flags = H5C__DELETED_FLAG;
+ oh_flags = H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
} /* end else */
} /* end if */
} else {
@@ -1383,7 +1546,7 @@ H5O_protect(H5O_loc_t *loc, hid_t dxpl_id)
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, NULL, "no write intent on file")
/* Lock the object header into the cache */
- if(NULL == (ret_value = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
+ if(NULL == (ret_value = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "unable to load object header")
/* Mark object header as un-evictable */
@@ -1556,7 +1719,7 @@ H5O_touch(H5O_loc_t *loc, hbool_t force, hid_t dxpl_id)
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "no write intent on file")
/* Get the object header */
- if(NULL == (oh = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
+ if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_WRITE)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
/* Create/Update the modification time message */
@@ -1665,7 +1828,7 @@ H5O_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr)
HDassert(H5F_addr_defined(addr));
/* Get the object header information */
- if(NULL == (oh = H5AC_protect(f, dxpl_id, H5AC_OHDR, addr, NULL, NULL, H5AC_WRITE)))
+ if(NULL == (oh = (H5O_t *)H5AC_protect(f, dxpl_id, H5AC_OHDR, addr, NULL, NULL, H5AC_WRITE)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
/* Delete object */
@@ -1673,7 +1836,7 @@ H5O_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't delete object from file")
done:
- if(oh && H5AC_unprotect(f, dxpl_id, H5AC_OHDR, addr, oh, H5AC__DIRTIED_FLAG | H5C__DELETED_FLAG) < 0)
+ if(oh && H5AC_unprotect(f, dxpl_id, H5AC_OHDR, addr, oh, H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0)
HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header")
FUNC_LEAVE_NOAPI(ret_value)
@@ -1719,10 +1882,6 @@ H5O_delete_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete file space for object header message")
} /* end for */
- /* Free main (first) object header "chunk" */
- if(H5MF_xfree(f, H5FD_MEM_OHDR, dxpl_id, oh->chunk[0].addr, (hsize_t)oh->chunk[0].size) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free object header")
-
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_delete_oh() */
@@ -1750,7 +1909,7 @@ H5O_obj_type(const H5O_loc_t *loc, H5O_type_t *obj_type, hid_t dxpl_id)
FUNC_ENTER_NOAPI(H5O_obj_type, FAIL)
/* Load the object header */
- if(NULL == (oh = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
/* Retrieve the type of the object */
@@ -1828,7 +1987,7 @@ H5O_obj_class(const H5O_loc_t *loc, hid_t dxpl_id)
FUNC_ENTER_NOAPI_NOINIT(H5O_obj_class)
/* Load the object header */
- if(NULL == (oh = H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "unable to load object header")
/* Test whether entry qualifies as a particular type of object */
@@ -2114,15 +2273,15 @@ H5O_get_info(H5O_loc_t *oloc, hid_t dxpl_id, hbool_t want_ih_info, H5O_info_t *o
HDassert(oinfo);
/* Get the object header */
- if(NULL == (oh = H5AC_protect(oloc->file, dxpl_id, H5AC_OHDR, oloc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = (H5O_t *)H5AC_protect(oloc->file, dxpl_id, H5AC_OHDR, oloc->addr, NULL, NULL,
+ (H5F_get_intent(oloc->file) & H5F_ACC_RDWR) ? H5AC_WRITE : H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
/* Reset the object info structure */
HDmemset(oinfo, 0, sizeof(*oinfo));
/* Retrieve the file's fileno */
- if(H5F_get_fileno(oloc->file, &oinfo->fileno) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unable to read fileno")
+ H5F_GET_FILENO(oloc->file, oinfo->fileno);
/* Set the object's address */
oinfo->addr = oloc->addr;
@@ -2266,7 +2425,7 @@ H5O_get_create_plist(const H5O_loc_t *oloc, hid_t dxpl_id, H5P_genplist_t *oc_pl
HDassert(oc_plist);
/* Get the object header */
- if(NULL == (oh = H5AC_protect(oloc->file, dxpl_id, H5AC_OHDR, oloc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = (H5O_t *)H5AC_protect(oloc->file, dxpl_id, H5AC_OHDR, oloc->addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
/* Set property values, if they were used for the object */
@@ -2321,7 +2480,7 @@ H5O_get_nlinks(const H5O_loc_t *oloc, hid_t dxpl_id, hsize_t *nlinks)
HDassert(nlinks);
/* Get the object header */
- if(NULL == (oh = H5AC_protect(oloc->file, dxpl_id, H5AC_OHDR, oloc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = (H5O_t *)H5AC_protect(oloc->file, dxpl_id, H5AC_OHDR, oloc->addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
/* Retrieve the # of link messages seen when the object header was loaded */
@@ -2412,3 +2571,304 @@ H5O_get_oh_addr(const H5O_t *oh)
FUNC_LEAVE_NOAPI(oh->chunk[0].addr)
} /* end H5O_get_oh_addr() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_get_rc_and_type
+ *
+ * Purpose: Retrieve an object's reference count and type
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * November 4 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O_get_rc_and_type(const H5O_loc_t *oloc, hid_t dxpl_id, unsigned *rc, H5O_type_t *otype)
+{
+ H5O_t *oh = NULL; /* Object header */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5O_get_rc_and_type, FAIL)
+
+ /* Check args */
+ HDassert(oloc);
+ HDassert(rc);
+ HDassert(otype);
+
+ /* Get the object header */
+ if(NULL == (oh = (H5O_t *)H5AC_protect(oloc->file, dxpl_id, H5AC_OHDR, oloc->addr, NULL, NULL, H5AC_READ)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
+
+ /* Set the object's reference count */
+ *rc = oh->nlink;
+
+ /* Retrieve the type of the object */
+ if(H5O_obj_type_real(oh, otype) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to determine object type")
+
+done:
+ if(oh && H5AC_unprotect(oloc->file, dxpl_id, H5AC_OHDR, oloc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_get_rc_and_type() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_free_visit_visited
+ *
+ * Purpose: Free the key for an object visited during a group traversal
+ *
+ * Return: Non-negative on success, negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Nov 25, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_free_visit_visited(void *item, void UNUSED *key, void UNUSED *operator_data/*in,out*/)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_free_visit_visited)
+
+ (void)H5FL_FREE(H5_obj_t, item);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5O_free_visit_visited() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_visit_cb
+ *
+ * Purpose: Callback function for recursively visiting objects from a group
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Nov 25, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_visit_cb(hid_t UNUSED group, const char *name, const H5L_info_t *linfo,
+ void *_udata)
+{
+ H5O_iter_visit_ud_t *udata = (H5O_iter_visit_ud_t *)_udata; /* User data for callback */
+ H5G_loc_t obj_loc; /* Location of object */
+ H5G_name_t obj_path; /* Object's group hier. path */
+ H5O_loc_t obj_oloc; /* Object's object location */
+ hbool_t obj_found = FALSE; /* Object at 'name' found */
+ herr_t ret_value = H5_ITER_CONT; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5O_visit_cb)
+
+ /* Sanity check */
+ HDassert(name);
+ HDassert(linfo);
+ HDassert(udata);
+
+ /* Check if this is a hard link */
+ if(linfo->type == H5L_TYPE_HARD) {
+ H5_obj_t obj_pos; /* Object "position" for this object */
+
+ /* Set up opened group location to fill in */
+ obj_loc.oloc = &obj_oloc;
+ obj_loc.path = &obj_path;
+ H5G_loc_reset(&obj_loc);
+
+ /* Find the object using the LAPL passed in */
+ /* (Correctly handles mounted files) */
+ if(H5G_loc_find(udata->start_loc, name, &obj_loc/*out*/, udata->lapl_id, udata->dxpl_id) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, H5_ITER_ERROR, "object not found")
+ obj_found = TRUE;
+
+ /* Construct unique "position" for this object */
+ H5F_GET_FILENO(obj_oloc.file, obj_pos.fileno);
+ obj_pos.addr = obj_oloc.addr;
+
+ /* Check if we've seen the object the link references before */
+ if(NULL == H5SL_search(udata->visited, &obj_pos)) {
+ H5O_info_t oinfo; /* Object info */
+
+ /* Get the object's info */
+ if(H5O_get_info(&obj_oloc, udata->dxpl_id, TRUE, &oinfo) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, H5_ITER_ERROR, "unable to get object info")
+
+ /* Make the application callback */
+ ret_value = (udata->op)(udata->obj_id, name, &oinfo, udata->op_data);
+
+ /* Check for continuing to visit objects */
+ if(ret_value == H5_ITER_CONT) {
+ /* If its ref count is > 1, we add it to the list of visited objects */
+ /* (because it could come up again during traversal) */
+ if(oinfo.rc > 1) {
+ H5_obj_t *new_node; /* New object node for visited list */
+
+ /* Allocate new object "position" node */
+ if((new_node = H5FL_MALLOC(H5_obj_t)) == NULL)
+ HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, H5_ITER_ERROR, "can't allocate object node")
+
+ /* Set node information */
+ *new_node = obj_pos;
+
+ /* Add to list of visited objects */
+ if(H5SL_insert(udata->visited, new_node, new_node) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, H5_ITER_ERROR, "can't insert object node into visited list")
+ } /* end if */
+ } /* end if */
+ } /* end if */
+ } /* end if */
+
+done:
+ /* Release resources */
+ if(obj_found && H5G_loc_free(&obj_loc) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, H5_ITER_ERROR, "can't free location")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_visit_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_visit
+ *
+ * Purpose: Recursively visit an object and all the objects reachable
+ * from it. If the starting object is a group, all the objects
+ * linked to from that group will be visited. Links within
+ * each group are visited according to the order within the
+ * specified index (unless the specified index does not exist for
+ * a particular group, then the "name" index is used).
+ *
+ * NOTE: Soft links and user-defined links are ignored during
+ * this operation.
+ *
+ * NOTE: Each _object_ reachable from the initial group will only
+ * be visited once. If multiple hard links point to the same
+ * object, the first link to the object's path (according to the
+ * iteration index and iteration order given) will be used to in
+ * the callback about the object.
+ *
+ * Return: Success: The return value of the first operator that
+ * returns non-zero, or zero if all members were
+ * processed with no operator returning non-zero.
+ *
+ * Failure: Negative if something goes wrong within the
+ * library, or the negative value returned by one
+ * of the operators.
+ *
+ * Programmer: Quincey Koziol
+ * November 24 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_visit(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
+ H5_iter_order_t order, H5O_iterate_t op, void *op_data, hid_t lapl_id,
+ hid_t dxpl_id)
+{
+ H5O_iter_visit_ud_t udata; /* User data for callback */
+ H5G_loc_t loc; /* Location of reference object */
+ H5G_loc_t obj_loc; /* Location used to open object */
+ H5G_name_t obj_path; /* Opened object group hier. path */
+ H5O_loc_t obj_oloc; /* Opened object object location */
+ hbool_t loc_found = FALSE; /* Entry at 'name' found */
+ H5O_info_t oinfo; /* Object info struct */
+ hid_t obj_id = (-1); /* ID of object */
+ herr_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5O_visit, FAIL)
+
+ /* Portably initialize user data struct to zeros */
+ HDmemset(&udata, 0, sizeof(udata));
+
+ /* Check args */
+ if(H5G_loc(loc_id, &loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
+
+ /* Set up opened group location to fill in */
+ obj_loc.oloc = &obj_oloc;
+ obj_loc.path = &obj_path;
+ H5G_loc_reset(&obj_loc);
+
+ /* Find the object's location */
+ if(H5G_loc_find(&loc, obj_name, &obj_loc/*out*/, lapl_id, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "object not found")
+ loc_found = TRUE;
+
+ /* Get the object's info */
+ if(H5O_get_info(&obj_oloc, dxpl_id, TRUE, &oinfo) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to get object info")
+
+ /* Open the object */
+ /* (Takes ownership of the obj_loc information) */
+ if((obj_id = H5O_open_by_loc(&obj_loc, lapl_id, dxpl_id, TRUE)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open object")
+
+ /* Make callback for starting object */
+ if((ret_value = op(obj_id, ".", &oinfo, op_data)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "can't visit objects")
+
+ /* Check return value of first callback */
+ if(ret_value != H5_ITER_CONT)
+ HGOTO_DONE(ret_value);
+
+ /* Check for object being a group */
+ if(oinfo.type == H5O_TYPE_GROUP) {
+ H5G_loc_t start_loc; /* Location of starting group */
+
+ /* Get the location of the starting group */
+ if(H5G_loc(obj_id, &start_loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
+
+ /* Set up user data for visiting links */
+ udata.obj_id = obj_id;
+ udata.start_loc = &start_loc;
+ udata.lapl_id = lapl_id;
+ udata.dxpl_id = dxpl_id;
+ udata.op = op;
+ udata.op_data = op_data;
+
+ /* Create skip list to store visited object information */
+ if((udata.visited = H5SL_create(H5SL_TYPE_OBJ, 0.5, (size_t)16)) == NULL)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTCREATE, FAIL, "can't create skip list for visited objects")
+
+ /* If its ref count is > 1, we add it to the list of visited objects */
+ /* (because it could come up again during traversal) */
+ if(oinfo.rc > 1) {
+ H5_obj_t *obj_pos; /* New object node for visited list */
+
+ /* Allocate new object "position" node */
+ if((obj_pos = H5FL_MALLOC(H5_obj_t)) == NULL)
+ HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, FAIL, "can't allocate object node")
+
+ /* Construct unique "position" for this object */
+ obj_pos->fileno = oinfo.fileno;
+ obj_pos->addr = oinfo.addr;
+
+ /* Add to list of visited objects */
+ if(H5SL_insert(udata.visited, obj_pos, obj_pos) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert object node into visited list")
+ } /* end if */
+
+ /* Call internal group visitation routine */
+ if((ret_value = H5G_visit(obj_id, ".", idx_type, order, H5O_visit_cb, &udata, lapl_id, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "object visitation failed")
+ } /* end if */
+
+done:
+ if(obj_id > 0) {
+ if(H5I_dec_ref(obj_id, TRUE) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to close object")
+ } /* end if */
+ else if(loc_found && H5G_loc_free(&obj_loc) < 0)
+ HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "can't free location")
+ if(udata.visited)
+ H5SL_destroy(udata.visited, H5O_free_visit_visited, NULL);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_visit() */
+
+
diff --git a/src/H5Oainfo.c b/src/H5Oainfo.c
index 968b165..2a9d403 100644
--- a/src/H5Oainfo.c
+++ b/src/H5Oainfo.c
@@ -35,7 +35,8 @@
/* PRIVATE PROTOTYPES */
-static void *H5O_ainfo_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags, const uint8_t *p);
+static void *H5O_ainfo_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags,
+ unsigned *ioflags, const uint8_t *p);
static herr_t H5O_ainfo_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
static void *H5O_ainfo_copy(const void *_mesg, void *_dest);
static size_t H5O_ainfo_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
@@ -102,7 +103,7 @@ H5FL_DEFINE_STATIC(H5O_ainfo_t);
*/
static void *
H5O_ainfo_decode(H5F_t *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
- const uint8_t *p)
+ unsigned UNUSED *ioflags, const uint8_t *p)
{
H5O_ainfo_t *ainfo = NULL; /* Attribute info */
unsigned char flags; /* Flags for encoding attribute info */
@@ -155,7 +156,7 @@ H5O_ainfo_decode(H5F_t *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
done:
if(ret_value == NULL && ainfo != NULL)
- H5FL_FREE(H5O_ainfo_t, ainfo);
+ (void)H5FL_FREE(H5O_ainfo_t, ainfo);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_ainfo_decode() */
@@ -310,7 +311,7 @@ H5O_ainfo_free(void *mesg)
HDassert(mesg);
- H5FL_FREE(H5O_ainfo_t, mesg);
+ (void)H5FL_FREE(H5O_ainfo_t, mesg);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_ainfo_free() */
@@ -432,7 +433,7 @@ H5O_ainfo_copy_file(H5F_t UNUSED *file_src, void *mesg_src,
done:
/* Release destination attribute information on failure */
if(ret_value == NULL && ainfo_dst != NULL)
- H5FL_FREE(H5O_ainfo_t, ainfo_dst);
+ (void)H5FL_FREE(H5O_ainfo_t, ainfo_dst);
FUNC_LEAVE_NOAPI(ret_value)
} /* H5O_ainfo_copy_file() */
diff --git a/src/H5Oalloc.c b/src/H5Oalloc.c
index 03eb956..7c6cf9d 100644
--- a/src/H5Oalloc.c
+++ b/src/H5Oalloc.c
@@ -64,13 +64,14 @@ static herr_t H5O_eliminate_gap(H5O_t *oh, H5O_mesg_t *mesg,
uint8_t *new_gap_loc, size_t new_gap_size);
static herr_t H5O_alloc_null(H5O_t *oh, unsigned null_idx,
const H5O_msg_class_t *new_type, void *new_native, size_t new_size);
-static htri_t H5O_alloc_extend_chunk(H5F_t *f, H5O_t *oh, unsigned chunkno,
- size_t size, unsigned * msg_idx);
+static htri_t H5O_alloc_extend_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
+ unsigned chunkno, size_t size, unsigned * msg_idx);
static unsigned H5O_alloc_new_chunk(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
size_t size);
static htri_t H5O_move_msgs_forward(H5O_t *oh);
-static htri_t H5O_merge_null(H5O_t *oh);
+static htri_t H5O_merge_null(H5F_t *f, H5O_t *oh, hid_t dxpl_id);
static htri_t H5O_remove_empty_chunks(H5F_t *f, H5O_t *oh, hid_t dxpl_id);
+static herr_t H5O_alloc_shrink_chunk(H5F_t *f, H5O_t *oh, hid_t dxpl_id, unsigned chunkno);
/*********************/
@@ -148,7 +149,7 @@ H5O_add_gap(H5O_t *oh, unsigned chunkno, unsigned idx,
oh->mesg[u].raw -= new_gap_size;
/* Slide raw message info forward in chunk image */
- HDmemmove(new_gap_loc, new_gap_loc + new_gap_size,
+ HDmemmove(new_gap_loc, new_gap_loc + new_gap_size,
(size_t)((oh->chunk[chunkno].image + (oh->chunk[chunkno].size - H5O_SIZEOF_CHKSUM_OH(oh))) - (new_gap_loc + new_gap_size)));
/* Add existing gap size to new gap size */
@@ -457,6 +458,7 @@ done:
*/
static htri_t
H5O_alloc_extend_chunk(H5F_t *f,
+ hid_t dxpl_id,
H5O_t *oh,
unsigned chunkno,
size_t size,
@@ -466,7 +468,7 @@ H5O_alloc_extend_chunk(H5F_t *f,
size_t aligned_size = H5O_ALIGN_OH(oh, size);
uint8_t *old_image; /* Old address of chunk's image in memory */
size_t old_size; /* Old size of chunk */
- htri_t tri_result; /* Result from checking if chunk can be extended */
+ htri_t extended; /* If chunk can be extended */
int extend_msg = -1;/* Index of null message to extend */
uint8_t new_size_flags = 0; /* New chunk #0 size flags */
hbool_t adjust_size_flags = FALSE; /* Whether to adjust the chunk #0 size flags */
@@ -534,16 +536,12 @@ H5O_alloc_extend_chunk(H5F_t *f,
} /* end if */
/* Determine whether the chunk can be extended */
- tri_result = H5MF_can_extend(f, H5FD_MEM_OHDR, oh->chunk[chunkno].addr,
+ extended = H5MF_try_extend(f, dxpl_id, H5FD_MEM_OHDR, oh->chunk[chunkno].addr,
(hsize_t)(oh->chunk[chunkno].size), (hsize_t)(delta + extra_prfx_size));
- if(tri_result == FALSE) /* can't extend -- we are done */
+ if(extended < 0) /* error */
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTEXTEND, FAIL, "can't tell if we can extend chunk")
+ else if(extended == FALSE) /* can't extend -- we are done */
HGOTO_DONE(FALSE)
- else if(tri_result < 0) /* error */
- HGOTO_ERROR(H5E_RESOURCE, H5E_SYSTEM, FAIL, "can't tell if we can extend chunk")
-
- /* If we get this far, we should be able to extend the chunk */
- if(H5MF_extend(f, H5FD_MEM_OHDR, oh->chunk[chunkno].addr, (hsize_t)(oh->chunk[chunkno].size), (hsize_t)(delta + extra_prfx_size)) < 0 )
- HGOTO_ERROR(H5E_RESOURCE, H5E_SYSTEM, FAIL, "can't extend chunk")
/* Adjust object header prefix flags */
if(adjust_size_flags) {
@@ -837,8 +835,8 @@ H5O_alloc_new_chunk(H5F_t *f,
* # at the beginning of the chunk image.
*/
if(oh->version > H5O_VERSION_1) {
- HDmemcpy(p, H5O_CHK_MAGIC, (size_t)H5O_SIZEOF_MAGIC);
- p += H5O_SIZEOF_MAGIC;
+ HDmemcpy(p, H5O_CHK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ p += H5_SIZEOF_MAGIC;
} /* end if */
/*
@@ -849,7 +847,7 @@ H5O_alloc_new_chunk(H5F_t *f,
if(H5O_alloc_msgs(oh, (size_t)3) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, "can't allocate more space for messages")
- /* Move message (that will be replaced with continuation message)
+ /* Move message (that will be replaced with continuation message)
* to new chunk, if necessary.
*/
if(found_null < 0) {
@@ -994,13 +992,13 @@ H5O_alloc(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_msg_class_t *type,
HDassert(H5F_addr_defined(oh->chunk[chunkno].addr));
- tri_result = H5O_alloc_extend_chunk(f, oh, chunkno, raw_size, &idx);
+ tri_result = H5O_alloc_extend_chunk(f, dxpl_id, oh, chunkno, raw_size, &idx);
if(tri_result == TRUE)
break;
else if(tri_result == FALSE)
idx = UFAIL;
else
- HGOTO_ERROR(H5E_OHDR, H5E_SYSTEM, UFAIL, "H5O_alloc_extend_chunk failed unexpectedly")
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTEXTEND, UFAIL, "H5O_alloc_extend_chunk failed unexpectedly")
} /* end for */
/* If idx is still UFAIL, we were not able to extend a chunk,
@@ -1078,7 +1076,7 @@ H5O_release_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5O_mesg_t *mesg,
/* Check if chunk has a gap currently */
if(oh->chunk[mesg->chunkno].gap) {
/* Eliminate the gap in the chunk */
- if(H5O_eliminate_gap(oh, mesg,
+ if(H5O_eliminate_gap(oh, mesg,
((oh->chunk[mesg->chunkno].image + oh->chunk[mesg->chunkno].size) - (H5O_SIZEOF_CHKSUM_OH(oh) + oh->chunk[mesg->chunkno].gap)),
oh->chunk[mesg->chunkno].gap) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTREMOVE, FAIL, "can't eliminate gap in chunk")
@@ -1136,7 +1134,7 @@ H5O_move_msgs_forward(H5O_t *oh)
/* Check if null message is not last in chunk */
chunk = &(oh->chunk[curr_msg->chunkno]);
- if((curr_msg->raw + curr_msg->raw_size)
+ if((curr_msg->raw + curr_msg->raw_size)
!= ((chunk->image + chunk->size) - (H5O_SIZEOF_CHKSUM_OH(oh) + chunk->gap))) {
H5O_mesg_t *nonnull_msg; /* Pointer to current message to operate on */
unsigned v; /* Local index variable */
@@ -1220,7 +1218,7 @@ H5O_move_msgs_forward(H5O_t *oh)
/* Check for gap in null message's chunk */
if(oh->chunk[old_chunkno].gap > 0) {
/* Eliminate the gap in the chunk */
- if(H5O_eliminate_gap(oh, null_msg,
+ if(H5O_eliminate_gap(oh, null_msg,
((oh->chunk[old_chunkno].image + oh->chunk[old_chunkno].size) - (H5O_SIZEOF_CHKSUM_OH(oh) + oh->chunk[old_chunkno].gap)),
oh->chunk[old_chunkno].gap) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTREMOVE, FAIL, "can't eliminate gap in chunk")
@@ -1278,7 +1276,7 @@ H5O_move_msgs_forward(H5O_t *oh)
/* Check for gap in new null message's chunk */
if(oh->chunk[old_chunkno].gap > 0) {
/* Eliminate the gap in the chunk */
- if(H5O_eliminate_gap(oh, &oh->mesg[new_null_msg],
+ if(H5O_eliminate_gap(oh, &oh->mesg[new_null_msg],
((oh->chunk[old_chunkno].image + oh->chunk[old_chunkno].size) - (H5O_SIZEOF_CHKSUM_OH(oh) + oh->chunk[old_chunkno].gap)),
oh->chunk[old_chunkno].gap) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTREMOVE, FAIL, "can't eliminate gap in chunk")
@@ -1334,13 +1332,13 @@ done:
*-------------------------------------------------------------------------
*/
static htri_t
-H5O_merge_null(H5O_t *oh)
+H5O_merge_null(H5F_t *f, H5O_t *oh, hid_t dxpl_id)
{
hbool_t merged_msg; /* Flag to indicate that messages were merged */
hbool_t did_merging = FALSE; /* Whether any messages were merged */
htri_t ret_value; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_merge_null)
+ FUNC_ENTER_NOAPI_NOINIT(H5O_merge_null)
/* check args */
HDassert(oh != NULL);
@@ -1403,6 +1401,11 @@ H5O_merge_null(H5O_t *oh)
/* (Don't bother reducing size of message array for now -QAK) */
oh->nmesgs--;
+ /* If the merged message is too large, shrink the chunk */
+ if(curr_msg->raw_size >= H5O_MESG_MAX_SIZE)
+ if(H5O_alloc_shrink_chunk(f, oh, dxpl_id, curr_msg->chunkno) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTPACK, FAIL, "unable to shrink chunk")
+
/* Get out of loop */
break;
} /* end if */
@@ -1423,6 +1426,7 @@ H5O_merge_null(H5O_t *oh)
/* Set return value */
ret_value = did_merging;
+done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5O_merge_null() */
@@ -1482,12 +1486,7 @@ H5O_remove_empty_chunks(H5F_t *f, H5O_t *oh, hid_t dxpl_id)
for(v = 0, cont_msg = &oh->mesg[0]; v < oh->nmesgs; v++, cont_msg++) {
if(H5O_CONT_ID == cont_msg->type->id) {
/* Decode current continuation message if necessary */
- if(NULL == cont_msg->native) {
- HDassert(H5O_MSG_CONT->decode);
- cont_msg->native = (H5O_MSG_CONT->decode)(f, dxpl_id, 0, cont_msg->raw);
- if(NULL == cont_msg->native)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "unable to decode message")
- } /* end if */
+ H5O_LOAD_NATIVE(f, dxpl_id, 0, oh, cont_msg, FAIL)
/* Check for correct chunk to delete */
if(oh->chunk[null_msg->chunkno].addr == ((H5O_cont_t *)(cont_msg->native))->addr)
@@ -1511,7 +1510,7 @@ H5O_remove_empty_chunks(H5F_t *f, H5O_t *oh, hid_t dxpl_id)
*/
/* Free memory for chunk image */
- H5FL_BLK_FREE(chunk_image, oh->chunk[null_msg->chunkno].image);
+ (void)H5FL_BLK_FREE(chunk_image, oh->chunk[null_msg->chunkno].image);
/* Remove chunk from list of chunks */
if(null_msg->chunkno < (oh->nchunks - 1))
@@ -1545,12 +1544,7 @@ H5O_remove_empty_chunks(H5F_t *f, H5O_t *oh, hid_t dxpl_id)
/* Check for continuation message */
if(H5O_CONT_ID == curr_msg->type->id) {
/* Decode current continuation message if necessary */
- if(NULL == curr_msg->native) {
- HDassert(H5O_MSG_CONT->decode);
- curr_msg->native = (H5O_MSG_CONT->decode)(f, dxpl_id, 0, curr_msg->raw);
- if(NULL == curr_msg->native)
- HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "unable to decode message")
- } /* end if */
+ H5O_LOAD_NATIVE(f, dxpl_id, 0, oh, curr_msg, FAIL)
/* Check for pointer to chunk after deleted chunk */
if(((H5O_cont_t *)(curr_msg->native))->chunkno > deleted_chunkno)
@@ -1616,7 +1610,7 @@ H5O_condense_header(H5F_t *f, H5O_t *oh, hid_t dxpl_id)
rescan_header = TRUE;
/* Scan for adjacent null messages & merge them */
- result = H5O_merge_null(oh);
+ result = H5O_merge_null(f, oh, dxpl_id);
if(result < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTPACK, FAIL, "can't pack null header messages")
if(result > 0)
@@ -1637,3 +1631,174 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5O_condense_header() */
+
+/*-------------------------------------------------------------------------
+ *
+ * Function: H5O_alloc_shrink_chunk
+ *
+ * Purpose: Shrinks a chunk, removing all null messages and any gap.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * nfortne2@hdfgroup.org
+ * Oct 20 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_alloc_shrink_chunk(H5F_t *f,
+ H5O_t *oh,
+ hid_t dxpl_id,
+ unsigned chunkno)
+{
+ H5O_chunk_t *chunk = &oh->chunk[chunkno]; /* Chunk to shrink */
+ H5O_mesg_t *curr_msg;
+ uint8_t *old_image = chunk->image; /* Old address of chunk's image in memory */
+ size_t old_size = chunk->size; /* Old size of chunk */
+ size_t new_size = chunk->size - chunk->gap; /* Size of shrunk chunk */
+ size_t sizeof_chksum = H5O_SIZEOF_CHKSUM_OH(oh); /* Size of chunk checksum */
+ size_t sizeof_msghdr = H5O_SIZEOF_MSGHDR_OH(oh); /* Size of message header */
+ size_t sizeof_chkhdr = H5O_SIZEOF_CHKHDR_OH(oh); /* Size of chunk header */
+ uint8_t new_size_flags = 0; /* New chunk #0 size flags */
+ hbool_t adjust_size_flags = FALSE; /* Whether to adjust the chunk #0 size flags */
+ size_t less_prfx_size = 0; /* Bytes removed from object header prefix */
+ herr_t ret_value = SUCCEED; /* Return value */
+ unsigned u; /* Index */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5O_alloc_shrink_chunk)
+
+ /* check args */
+ HDassert(f != NULL);
+
+ /* Loop backwards to increase the chance of seeing more null messages at the
+ * end of the chunk. Note that we rely on unsigned u wrapping around at the
+ * end.
+ */
+ for (u = oh->nmesgs - 1, curr_msg = &oh->mesg[u]; u < oh->nmesgs; u--, curr_msg--) {
+ if ((H5O_NULL_ID == curr_msg->type->id) && (chunkno == curr_msg->chunkno)) {
+ /* Check if the message is the only one in the chunk */
+ if (chunkno > 0 && (sizeof_msghdr + curr_msg->raw_size) == (new_size - sizeof_chkhdr)) {
+ /* Shrink the message to the minimum size */
+ new_size -= curr_msg->raw_size;
+ curr_msg->raw_size = 0;
+ curr_msg->dirty = TRUE;
+ HDassert(new_size == sizeof_msghdr + sizeof_chkhdr);
+
+ /* There are no more messages in this chunk, so we can exit the loop */
+ break;
+ } /* end if */
+ else {
+ /* Remove the message entirely */
+ size_t shrink_size = curr_msg->raw_size + sizeof_msghdr; /* Amount to shrink the chunk by */
+ /* If the current message is not at the end of the chunk, copy the
+ * data after it (except the checksum).
+ */
+ if (curr_msg->raw + curr_msg->raw_size
+ < old_image + new_size - sizeof_chksum) {
+ unsigned v; /* Index */
+ H5O_mesg_t *curr_msg2;
+ uint8_t *src = curr_msg->raw + curr_msg->raw_size; /* Source location */
+
+ /* Slide down the raw data */
+ HDmemmove(curr_msg->raw - sizeof_msghdr, src,
+ (size_t)(old_image + new_size - sizeof_chksum - src));
+
+ /* Update the raw data pointers for messages after this one */
+ for (v = 0, curr_msg2 = &oh->mesg[0]; v < oh->nmesgs; v++, curr_msg2++)
+ if ((chunkno == curr_msg2->chunkno) && (curr_msg2->raw > curr_msg->raw))
+ curr_msg2->raw -= shrink_size;
+ } /* end if */
+
+ /* Adjust the new chunk size */
+ new_size -= shrink_size;
+
+ /* Release any information/memory for the message */
+ H5O_msg_free_mesg(curr_msg);
+
+ /* Remove the deleted null message from list of messages */
+ if (u < (oh->nmesgs - 1))
+ HDmemmove(&oh->mesg[u], &oh->mesg[u+1], ((oh->nmesgs - 1) - u) * sizeof(H5O_mesg_t));
+
+ /* Decrement # of messages */
+ /* (Don't bother reducing size of message array for now) */
+ oh->nmesgs--;
+ } /* end else */
+ } /* end if */
+ } /* end for */
+
+ /* Check for changing the chunk #0 data size enough to need adjusting the flags */
+ if(oh->version > H5O_VERSION_1 && chunkno == 0) {
+ uint64_t chunk0_newsize = new_size - H5O_SIZEOF_HDR(oh); /* New size of chunk 0's data */
+ size_t orig_prfx_size = 1 << (oh->flags & H5O_HDR_CHUNK0_SIZE); /* Original prefix size */
+
+ /* Check for moving to a 1-byte size encoding */
+ if (orig_prfx_size > 1 && chunk0_newsize <= 255) {
+ less_prfx_size = orig_prfx_size - 1;
+ new_size_flags = H5O_HDR_CHUNK0_1;
+ adjust_size_flags = TRUE;
+ } /* end if */
+ /* Check for moving to a 2-byte size encoding */
+ else if (orig_prfx_size > 2 && chunk0_newsize <= 65535) {
+ less_prfx_size = orig_prfx_size - 2;
+ new_size_flags = H5O_HDR_CHUNK0_2;
+ adjust_size_flags = TRUE;
+ } /* end if */
+ /* Check for moving to a 4-byte size encoding */
+ else if (orig_prfx_size > 4 && chunk0_newsize <= 4294967295) {
+ less_prfx_size = orig_prfx_size - 4;
+ new_size_flags = H5O_HDR_CHUNK0_4;
+ adjust_size_flags = TRUE;
+ } /* end if */
+ } /* end if */
+
+ if(adjust_size_flags) {
+ /* Adjust object header prefix flags */
+ oh->flags &= ~H5O_HDR_CHUNK0_SIZE;
+ oh->flags |= new_size_flags;
+
+ /* Slide chunk 0 data down */
+ HDmemmove(chunk->image + H5O_SIZEOF_HDR(oh) - sizeof_chksum,
+ chunk->image + H5O_SIZEOF_HDR(oh) - sizeof_chksum + less_prfx_size,
+ new_size - H5O_SIZEOF_HDR(oh));
+
+ /* Adjust chunk size */
+ new_size -= less_prfx_size;
+ } /* end if */
+
+ /* Allocate less memory space for chunk's image */
+ chunk->size = new_size;
+ chunk->image = H5FL_BLK_REALLOC(chunk_image, old_image, chunk->size);
+ chunk->gap = 0;
+ chunk->dirty = TRUE;
+ if (NULL == oh->chunk[chunkno].image)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Spin through existing messages, adjusting them */
+ for (u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++) {
+ if (adjust_size_flags || (chunk->image != old_image))
+ /* Adjust raw addresses for messages in this chunk to reflect new 'image' address */
+ if (curr_msg->chunkno == chunkno)
+ curr_msg->raw = chunk->image - less_prfx_size + (curr_msg->raw - old_image);
+
+ /* Find continuation message which points to this chunk and adjust chunk's size */
+ /* (Chunk 0 doesn't have a continuation message that points to it and
+ * its size is directly encoded in the object header) */
+ if (chunkno > 0 && (H5O_CONT_ID == curr_msg->type->id) &&
+ (((H5O_cont_t *)(curr_msg->native))->chunkno == chunkno)) {
+ /* Adjust size of continuation message */
+ HDassert(((H5O_cont_t *)(curr_msg->native))->size == old_size);
+ ((H5O_cont_t *)(curr_msg->native))->size = chunk->size;
+
+ /* Flag continuation message as dirty */
+ curr_msg->dirty = TRUE;
+ } /* end if */
+ } /* end for */
+
+ /* Free the unused space in the file */
+ if (H5MF_xfree(f, H5FD_MEM_OHDR, dxpl_id, chunk->addr + new_size, (hsize_t)(old_size - new_size)) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to shrink object header chunk")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5O_alloc_shrink_chunk() */
diff --git a/src/H5Oattr.c b/src/H5Oattr.c
index 3e0b757..85b1ef3 100644
--- a/src/H5Oattr.c
+++ b/src/H5Oattr.c
@@ -30,7 +30,8 @@
/* PRIVATE PROTOTYPES */
static herr_t H5O_attr_encode(H5F_t *f, uint8_t *p, const void *mesg);
-static void *H5O_attr_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags, const uint8_t *p);
+static void *H5O_attr_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags,
+ unsigned *ioflags, const uint8_t *p);
static void *H5O_attr_copy(const void *_mesg, void *_dest);
static size_t H5O_attr_size(const H5F_t *f, const void *_mesg);
static herr_t H5O_attr_free(void *mesg);
@@ -77,7 +78,7 @@ const H5O_msg_class_t H5O_MSG_ATTR[1] = {{
H5O_attr_shared_encode, /* encode message */
H5O_attr_copy, /* copy the native value */
H5O_attr_shared_size, /* size of raw message */
- H5O_attr_reset, /* reset method */
+ H5O_attr_reset, /* reset method */
H5O_attr_free, /* free method */
H5O_attr_shared_delete, /* file delete method */
H5O_attr_shared_link, /* link method */
@@ -124,7 +125,7 @@ H5FL_EXTERN(H5S_extent_t);
--------------------------------------------------------------------------*/
static void *
H5O_attr_decode(H5F_t *f, hid_t dxpl_id, unsigned UNUSED mesg_flags,
- const uint8_t *p)
+ unsigned *ioflags, const uint8_t *p)
{
H5A_t *attr = NULL;
H5S_extent_t *extent; /*extent dimensionality information */
@@ -141,13 +142,16 @@ H5O_attr_decode(H5F_t *f, hid_t dxpl_id, unsigned UNUSED mesg_flags,
if(NULL == (attr = H5FL_CALLOC(H5A_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ if(NULL == (attr->shared = H5FL_CALLOC(H5A_shared_t)))
+ HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, NULL, "can't allocate shared attr structure")
+
/* Version number */
- attr->version = *p++;
- if(attr->version < H5O_ATTR_VERSION_1 || attr->version > H5O_ATTR_VERSION_LATEST)
+ attr->shared->version = *p++;
+ if(attr->shared->version < H5O_ATTR_VERSION_1 || attr->shared->version > H5O_ATTR_VERSION_LATEST)
HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, NULL, "bad version number for attribute message")
/* Get the flags byte if we have a later version of the attribute */
- if(attr->version >= H5O_ATTR_VERSION_2) {
+ if(attr->shared->version >= H5O_ATTR_VERSION_2) {
flags = *p++;
/* Check for unknown flag */
@@ -162,69 +166,73 @@ H5O_attr_decode(H5F_t *f, hid_t dxpl_id, unsigned UNUSED mesg_flags,
* the file are exact but the parts are aligned on 8-byte boundaries.
*/
UINT16DECODE(p, name_len); /*including null*/
- UINT16DECODE(p, attr->dt_size);
- UINT16DECODE(p, attr->ds_size);
+ UINT16DECODE(p, attr->shared->dt_size);
+ UINT16DECODE(p, attr->shared->ds_size);
/*
* Decode the character encoding for the name for versions 3 or later,
* as well as some reserved bytes.
*/
- if(attr->version >= H5O_ATTR_VERSION_3)
- attr->encoding = *p++;
+ if(attr->shared->version >= H5O_ATTR_VERSION_3)
+ attr->shared->encoding = *p++;
/* Decode and store the name */
- if(NULL == (attr->name = H5MM_strdup((const char *)p)))
+ if(NULL == (attr->shared->name = H5MM_strdup((const char *)p)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- if(attr->version < H5O_ATTR_VERSION_2)
+ if(attr->shared->version < H5O_ATTR_VERSION_2)
p += H5O_ALIGN_OLD(name_len); /* advance the memory pointer */
else
p += name_len; /* advance the memory pointer */
/* Decode the attribute's datatype */
- if((attr->dt = (H5T_t *)(H5O_MSG_DTYPE->decode)(f, dxpl_id, ((flags & H5O_ATTR_FLAG_TYPE_SHARED) ? H5O_MSG_FLAG_SHARED : 0), p)) == NULL)
+ if(NULL == (attr->shared->dt = (H5T_t *)(H5O_MSG_DTYPE->decode)(f, dxpl_id, ((flags & H5O_ATTR_FLAG_TYPE_SHARED) ? H5O_MSG_FLAG_SHARED : 0), ioflags, p)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, NULL, "can't decode attribute datatype")
- if(attr->version < H5O_ATTR_VERSION_2)
- p += H5O_ALIGN_OLD(attr->dt_size);
+ if(attr->shared->version < H5O_ATTR_VERSION_2)
+ p += H5O_ALIGN_OLD(attr->shared->dt_size);
else
- p += attr->dt_size;
+ p += attr->shared->dt_size;
/* decode the attribute dataspace. It can be shared in versions >= 3
* What's actually shared, though, is only the extent.
*/
- if(NULL == (attr->ds = H5FL_CALLOC(H5S_t)))
+ if(NULL == (attr->shared->ds = H5FL_CALLOC(H5S_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Decode attribute's dataspace extent */
- if((extent = (H5S_extent_t *)(H5O_MSG_SDSPACE->decode)(f, dxpl_id, ((flags & H5O_ATTR_FLAG_SPACE_SHARED) ? H5O_MSG_FLAG_SHARED : 0), p)) == NULL)
+ if((extent = (H5S_extent_t *)(H5O_MSG_SDSPACE->decode)(f, dxpl_id, ((flags & H5O_ATTR_FLAG_SPACE_SHARED) ? H5O_MSG_FLAG_SHARED : 0), ioflags, p)) == NULL)
HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, NULL, "can't decode attribute dataspace")
/* Copy the extent information to the dataspace */
- HDmemcpy(&(attr->ds->extent), extent, sizeof(H5S_extent_t));
+ HDmemcpy(&(attr->shared->ds->extent), extent, sizeof(H5S_extent_t));
/* Release temporary extent information */
- H5FL_FREE(H5S_extent_t, extent);
+ (void)H5FL_FREE(H5S_extent_t, extent);
/* Default to entire dataspace being selected */
- if(H5S_select_all(attr->ds, FALSE) < 0)
+ if(H5S_select_all(attr->shared->ds, FALSE) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, NULL, "unable to set all selection")
- if(attr->version < H5O_ATTR_VERSION_2)
- p += H5O_ALIGN_OLD(attr->ds_size);
+ if(attr->shared->version < H5O_ATTR_VERSION_2)
+ p += H5O_ALIGN_OLD(attr->shared->ds_size);
else
- p += attr->ds_size;
+ p += attr->shared->ds_size;
/* Compute the size of the data */
- H5_ASSIGN_OVERFLOW(attr->data_size, H5S_GET_EXTENT_NPOINTS(attr->ds) * H5T_get_size(attr->dt), hsize_t, size_t);
+ H5_ASSIGN_OVERFLOW(attr->shared->data_size, H5S_GET_EXTENT_NPOINTS(attr->shared->ds) * H5T_get_size(attr->shared->dt), hsize_t, size_t);
/* Go get the data */
- if(attr->data_size) {
- if(NULL == (attr->data = H5FL_BLK_MALLOC(attr_buf, attr->data_size)))
+ if(attr->shared->data_size) {
+ if(NULL == (attr->shared->data = H5FL_BLK_MALLOC(attr_buf, attr->shared->data_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- HDmemcpy(attr->data, p, attr->data_size);
+ HDmemcpy(attr->shared->data, p, attr->shared->data_size);
} /* end if */
/* Indicate that the fill values aren't to be written out */
- attr->initialized = 1;
+ attr->shared->initialized = 1;
+
+ /* Increment the reference count for this object header message in cache(compact
+ storage) or for the object from dense storage. */
+ attr->shared->nrefs++;
/* Set return value */
ret_value = attr;
@@ -268,17 +276,17 @@ H5O_attr_encode(H5F_t *f, uint8_t *p, const void *mesg)
HDassert(attr);
/* Check whether datatype and dataspace are shared */
- if((is_type_shared = H5O_msg_is_shared(H5O_DTYPE_ID, attr->dt)) < 0)
+ if((is_type_shared = H5O_msg_is_shared(H5O_DTYPE_ID, attr->shared->dt)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "can't determine if datatype is shared")
- if((is_space_shared = H5O_msg_is_shared(H5O_SDSPACE_ID, attr->ds)) < 0)
+ if((is_space_shared = H5O_msg_is_shared(H5O_SDSPACE_ID, attr->shared->ds)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "can't determine if dataspace is shared")
/* Encode Version */
- *p++ = attr->version;
+ *p++ = attr->shared->version;
/* Set attribute flags if version >1 */
- if(attr->version >= H5O_ATTR_VERSION_2) {
+ if(attr->shared->version >= H5O_ATTR_VERSION_2) {
flags = (is_type_shared ? H5O_ATTR_FLAG_TYPE_SHARED : 0 );
flags |= (is_space_shared ? H5O_ATTR_FLAG_SPACE_SHARED : 0);
*p++ = flags; /* Set flags for attribute */
@@ -291,18 +299,18 @@ H5O_attr_encode(H5F_t *f, uint8_t *p, const void *mesg)
* encoded lengths are exact but we pad each part except the data to be a
* multiple of eight bytes (in the first version).
*/
- name_len = HDstrlen(attr->name) + 1;
+ name_len = HDstrlen(attr->shared->name) + 1;
UINT16ENCODE(p, name_len);
- UINT16ENCODE(p, attr->dt_size);
- UINT16ENCODE(p, attr->ds_size);
+ UINT16ENCODE(p, attr->shared->dt_size);
+ UINT16ENCODE(p, attr->shared->ds_size);
/* The character encoding for the attribute's name, in later versions */
- if(attr->version >= H5O_ATTR_VERSION_3)
- *p++ = attr->encoding;
+ if(attr->shared->version >= H5O_ATTR_VERSION_3)
+ *p++ = attr->shared->encoding;
/* Write the name including null terminator */
- HDmemcpy(p, attr->name, name_len);
- if(attr->version < H5O_ATTR_VERSION_2) {
+ HDmemcpy(p, attr->shared->name, name_len);
+ if(attr->shared->version < H5O_ATTR_VERSION_2) {
/* Pad to the correct number of bytes */
HDmemset(p + name_len, 0, H5O_ALIGN_OLD(name_len) - name_len);
p += H5O_ALIGN_OLD(name_len);
@@ -311,32 +319,32 @@ H5O_attr_encode(H5F_t *f, uint8_t *p, const void *mesg)
p += name_len;
/* encode the attribute datatype */
- if((H5O_MSG_DTYPE->encode)(f, FALSE, p, attr->dt) < 0)
+ if((H5O_MSG_DTYPE->encode)(f, FALSE, p, attr->shared->dt) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "can't encode attribute datatype")
- if(attr->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);
+ if(attr->shared->version < H5O_ATTR_VERSION_2) {
+ HDmemset(p + attr->shared->dt_size, 0, H5O_ALIGN_OLD(attr->shared->dt_size) - attr->shared->dt_size);
+ p += H5O_ALIGN_OLD(attr->shared->dt_size);
} /* end if */
else
- p += attr->dt_size;
+ p += attr->shared->dt_size;
/* encode the attribute dataspace */
- if((H5O_MSG_SDSPACE->encode)(f, FALSE, p, &(attr->ds->extent)) < 0)
+ if((H5O_MSG_SDSPACE->encode)(f, FALSE, p, &(attr->shared->ds->extent)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "can't encode attribute dataspace")
- if(attr->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);
+ if(attr->shared->version < H5O_ATTR_VERSION_2) {
+ HDmemset(p + attr->shared->ds_size, 0, H5O_ALIGN_OLD(attr->shared->ds_size) - attr->shared->ds_size);
+ p += H5O_ALIGN_OLD(attr->shared->ds_size);
} /* end if */
else
- p += attr->ds_size;
+ p += attr->shared->ds_size;
- /* Store attribute data */
- if(attr->data)
- HDmemcpy(p, attr->data, attr->data_size);
+ /* Store attribute data. If there's no data, store 0 as fill value. */
+ if(attr->shared->data)
+ HDmemcpy(p, attr->shared->data, attr->shared->data_size);
else
- HDmemset(p, 0, attr->data_size);
+ HDmemset(p, 0, attr->shared->data_size);
done:
FUNC_LEAVE_NOAPI(ret_value);
@@ -412,25 +420,25 @@ H5O_attr_size(const H5F_t UNUSED *f, const void *_mesg)
2; /*space size */
/* Length of attribute name */
- name_len = HDstrlen(attr->name) + 1;
+ name_len = HDstrlen(attr->shared->name) + 1;
/* Version-specific size information */
- if(attr->version == H5O_ATTR_VERSION_1)
+ if(attr->shared->version == H5O_ATTR_VERSION_1)
ret_value += H5O_ALIGN_OLD(name_len) + /*attribute name */
- H5O_ALIGN_OLD(attr->dt_size) + /*datatype */
- H5O_ALIGN_OLD(attr->ds_size) + /*dataspace */
- attr->data_size; /*the data itself */
- else if(attr->version == H5O_ATTR_VERSION_2)
+ H5O_ALIGN_OLD(attr->shared->dt_size) + /*datatype */
+ H5O_ALIGN_OLD(attr->shared->ds_size) + /*dataspace */
+ attr->shared->data_size; /*the data itself */
+ else if(attr->shared->version == H5O_ATTR_VERSION_2)
ret_value += name_len + /*attribute name */
- attr->dt_size + /*datatype */
- attr->ds_size + /*dataspace */
- attr->data_size; /*the data itself */
- else if(attr->version == H5O_ATTR_VERSION_3)
+ attr->shared->dt_size + /*datatype */
+ attr->shared->ds_size + /*dataspace */
+ attr->shared->data_size; /*the data itself */
+ else if(attr->shared->version == H5O_ATTR_VERSION_3)
ret_value += 1 + /*character encoding */
name_len + /*attribute name */
- attr->dt_size + /*datatype */
- attr->ds_size + /*dataspace */
- attr->data_size; /*the data itself */
+ attr->shared->dt_size + /*datatype */
+ attr->shared->ds_size + /*dataspace */
+ attr->shared->data_size; /*the data itself */
else
HDassert(0 && "Bad attribute version");
@@ -449,18 +457,20 @@ H5O_attr_size(const H5F_t UNUSED *f, const void *_mesg)
* Programmer: Robb Matzke
* Tuesday, December 9, 1997
*
+ * Modification:Raymond Lu
+ * 25 June 2008
+ * Made this function empty. The freeing action is actually
+ * done in H5O_attr_free (see H5O_msg_free_real). But this
+ * empty reset function needs to be here. Otherwise, the
+ * caller function H5O_msg_reset_real will zero-set the whole
+ * message.
*-------------------------------------------------------------------------
*/
herr_t
-H5O_attr_reset(void *_mesg)
+H5O_attr_reset(void UNUSED *_mesg)
{
- H5A_t *attr = (H5A_t *)_mesg;
-
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_attr_reset)
- if(attr)
- H5A_free(attr);
-
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_attr_reset() */
@@ -475,18 +485,27 @@ H5O_attr_reset(void *_mesg)
* Programmer: Quincey Koziol
* Thursday, November 18, 2004
*
+ * Modification:Raymond Lu
+ * 4 June 2008
+ * Let this function call H5A_close in turn.
+ *
*-------------------------------------------------------------------------
*/
static herr_t
H5O_attr_free(void *mesg)
{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_attr_free)
+ H5A_t *attr = (H5A_t *)mesg;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5O_attr_free)
HDassert(mesg);
- H5FL_FREE(H5A_t, mesg);
+ if(H5A_close(attr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCLOSEOBJ, FAIL, "unable to close attribute object")
- FUNC_LEAVE_NOAPI(SUCCEED)
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_attr_free() */
@@ -515,11 +534,11 @@ H5O_attr_delete(H5F_t *f, hid_t dxpl_id, H5O_t *oh, void *_mesg)
HDassert(attr);
/* Decrement reference count on datatype in file */
- if((H5O_MSG_DTYPE->del)(f, dxpl_id, oh, attr->dt) < 0)
+ if((H5O_MSG_DTYPE->del)(f, dxpl_id, oh, attr->shared->dt) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust datatype link count")
/* Decrement reference count on dataspace in file */
- if((H5O_MSG_SDSPACE->del)(f, dxpl_id, oh, attr->ds) < 0)
+ if((H5O_MSG_SDSPACE->del)(f, dxpl_id, oh, attr->shared->ds) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust dataspace link count")
done:
@@ -558,9 +577,9 @@ H5O_attr_link(H5F_t *f, hid_t dxpl_id, H5O_t *oh, void *_mesg)
* message is deleted.
*/
/* Increment reference count on datatype & dataspace in file */
- if((H5O_MSG_DTYPE->link)(f, dxpl_id, oh, attr->dt) < 0)
+ if((H5O_MSG_DTYPE->link)(f, dxpl_id, oh, attr->shared->dt) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust datatype link count")
- if((H5O_MSG_SDSPACE->link)(f, dxpl_id, oh, attr->ds) < 0)
+ if((H5O_MSG_SDSPACE->link)(f, dxpl_id, oh, attr->shared->ds) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust dataspace link count")
done:
@@ -650,33 +669,39 @@ H5O_attr_copy_file(H5F_t UNUSED *file_src, const H5O_msg_class_t UNUSED *mesg_ty
/* Copy the top level of the attribute */
*attr_dst = *attr_src;
+ if(NULL == (attr_dst->shared = H5FL_CALLOC(H5A_shared_t)))
+ HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, NULL, "can't allocate shared attr structure")
+
/* Don't have an opened group location for copy */
- H5O_loc_reset(&(attr_dst->oloc));
+ H5O_loc_reset(&(attr_dst->shared->oloc));
H5G_name_reset(&(attr_dst->path));
attr_dst->obj_opened = FALSE;
+ /* Reference count for the header message in the cache */
+ attr_dst->shared->nrefs = 1;
+
/* Copy attribute's name */
- attr_dst->name = H5MM_strdup(attr_src->name);
- HDassert(attr_dst->name);
+ attr_dst->shared->name = H5MM_strdup(attr_src->shared->name);
+ HDassert(attr_dst->shared->name);
/* Copy attribute's datatype */
/* (Start destination datatype as transient, even if source is named) */
- attr_dst->dt = H5T_copy(attr_src->dt, H5T_COPY_ALL);
- HDassert(attr_dst->dt);
+ if(NULL == (attr_dst->shared->dt = H5T_copy(attr_src->shared->dt, H5T_COPY_ALL)))
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "cannot copy datatype")
/* Set the location of the destination datatype */
- if(H5T_set_loc(attr_dst->dt, file_dst, H5T_LOC_DISK) < 0)
+ if(H5T_set_loc(attr_dst->shared->dt, file_dst, H5T_LOC_DISK) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "cannot mark datatype on disk")
/* Check for named datatype being copied */
- if(H5T_committed(attr_src->dt)) {
+ if(H5T_committed(attr_src->shared->dt)) {
H5O_loc_t *src_oloc; /* Pointer to source datatype's object location */
H5O_loc_t *dst_oloc; /* Pointer to dest. datatype's object location */
/* Get group entries for source & destination */
- src_oloc = H5T_oloc(attr_src->dt);
+ src_oloc = H5T_oloc(attr_src->shared->dt);
HDassert(src_oloc);
- dst_oloc = H5T_oloc(attr_dst->dt);
+ dst_oloc = H5T_oloc(attr_dst->shared->dt);
HDassert(dst_oloc);
/* Reset object location for new object */
@@ -688,59 +713,59 @@ H5O_attr_copy_file(H5F_t UNUSED *file_src, const H5O_msg_class_t UNUSED *mesg_ty
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy object")
/* Update shared message info from named datatype info */
- H5T_update_shared(attr_dst->dt);
+ H5T_update_shared(attr_dst->shared->dt);
} /* end if */
else {
/* If the datatype is not named, it may have been shared in the
* source file's heap. Un-share it for now. We'll try to shared
* it in the destination file below.
*/
- if(H5O_msg_reset_share(H5O_DTYPE_ID, attr_dst->dt) < 0)
+ if(H5O_msg_reset_share(H5O_DTYPE_ID, attr_dst->shared->dt) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to reset datatype sharing")
} /* end else */
/* Copy the dataspace for the attribute */
- attr_dst->ds = H5S_copy(attr_src->ds, FALSE);
- HDassert(attr_dst->ds);
+ attr_dst->shared->ds = H5S_copy(attr_src->shared->ds, FALSE, FALSE);
+ HDassert(attr_dst->shared->ds);
/* Reset the dataspace's sharing in the source file before trying to share
* it in the destination.
*/
- if(H5O_msg_reset_share(H5O_SDSPACE_ID, attr_dst->ds) < 0)
+ if(H5O_msg_reset_share(H5O_SDSPACE_ID, attr_dst->shared->ds) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to reset dataspace sharing")
/* Try to share both the datatype and dataset. This does nothing if the
* datatype is committed or sharing is disabled.
*/
- if(H5SM_try_share(file_dst, dxpl_id, NULL, H5O_DTYPE_ID, attr_dst->dt, NULL) < 0)
+ if(H5SM_try_share(file_dst, dxpl_id, NULL, H5O_DTYPE_ID, attr_dst->shared->dt, NULL) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, NULL, "can't share attribute datatype")
- if(H5SM_try_share(file_dst, dxpl_id, NULL, H5O_SDSPACE_ID, attr_dst->ds, NULL) < 0)
+ if(H5SM_try_share(file_dst, dxpl_id, NULL, H5O_SDSPACE_ID, attr_dst->shared->ds, NULL) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, NULL, "can't share attribute dataspace")
/* Compute the sizes of the datatype and dataspace. This is their raw
* size unless they're shared.
*/
- attr_dst->dt_size = H5O_msg_raw_size(file_dst, H5O_DTYPE_ID, FALSE, attr_dst->dt);
- HDassert(attr_dst->dt_size > 0);
- attr_dst->ds_size = H5O_msg_raw_size(file_dst, H5O_SDSPACE_ID, FALSE, attr_dst->ds);
- HDassert(attr_dst->ds_size > 0);
+ attr_dst->shared->dt_size = H5O_msg_raw_size(file_dst, H5O_DTYPE_ID, FALSE, attr_dst->shared->dt);
+ HDassert(attr_dst->shared->dt_size > 0);
+ attr_dst->shared->ds_size = H5O_msg_raw_size(file_dst, H5O_SDSPACE_ID, FALSE, attr_dst->shared->ds);
+ HDassert(attr_dst->shared->ds_size > 0);
/* Check whether to recompute the size of the attribute */
/* (happens when the datatype or dataspace changes sharing status) */
- if(attr_dst->dt_size != attr_src->dt_size || attr_dst->ds_size != attr_src->ds_size)
+ if(attr_dst->shared->dt_size != attr_src->shared->dt_size || attr_dst->shared->ds_size != attr_src->shared->ds_size)
*recompute_size = TRUE;
/* Compute the size of the data */
- H5_ASSIGN_OVERFLOW(attr_dst->data_size, H5S_GET_EXTENT_NPOINTS(attr_dst->ds) * H5T_get_size(attr_dst->dt), hsize_t, size_t);
+ H5_ASSIGN_OVERFLOW(attr_dst->shared->data_size, H5S_GET_EXTENT_NPOINTS(attr_dst->shared->ds) * H5T_get_size(attr_dst->shared->dt), hsize_t, size_t);
/* Copy (& convert) the data, if necessary */
- if(attr_src->data) {
- if(NULL == (attr_dst->data = H5FL_BLK_MALLOC(attr_buf, attr_dst->data_size)))
+ if(attr_src->shared->data) {
+ if(NULL == (attr_dst->shared->data = H5FL_BLK_MALLOC(attr_buf, attr_dst->shared->data_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Check if we need to convert data */
- if(H5T_detect_class(attr_src->dt, H5T_VLEN) > 0) {
+ if(H5T_detect_class(attr_src->shared->dt, H5T_VLEN) > 0) {
H5T_path_t *tpath_src_mem, *tpath_mem_dst; /* Datatype conversion paths */
H5T_t *dt_mem; /* Memory datatype */
size_t src_dt_size; /* Source datatype size */
@@ -752,37 +777,37 @@ H5O_attr_copy_file(H5F_t UNUSED *file_src, const H5O_msg_class_t UNUSED *mesg_ty
size_t buf_size; /* Size of copy buffer */
/* Create datatype ID for src datatype */
- if((tid_src = H5I_register(H5I_DATATYPE, attr_src->dt)) < 0)
+ if((tid_src = H5I_register(H5I_DATATYPE, attr_src->shared->dt, FALSE)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, "unable to register source file datatype")
/* create a memory copy of the variable-length datatype */
- if(NULL == (dt_mem = H5T_copy(attr_src->dt, H5T_COPY_TRANSIENT)))
+ if(NULL == (dt_mem = H5T_copy(attr_src->shared->dt, H5T_COPY_TRANSIENT)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy")
- if((tid_mem = H5I_register(H5I_DATATYPE, dt_mem)) < 0)
+ if((tid_mem = H5I_register(H5I_DATATYPE, dt_mem, FALSE)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, "unable to register memory datatype")
/* create variable-length datatype at the destinaton file */
- if((tid_dst = H5I_register(H5I_DATATYPE, attr_dst->dt)) < 0)
+ if((tid_dst = H5I_register(H5I_DATATYPE, attr_dst->shared->dt, FALSE)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, "unable to register destination file datatype")
/* Set up the conversion functions */
- if(NULL == (tpath_src_mem = H5T_path_find(attr_src->dt, dt_mem, NULL, NULL, dxpl_id, FALSE)))
+ if(NULL == (tpath_src_mem = H5T_path_find(attr_src->shared->dt, dt_mem, NULL, NULL, dxpl_id, FALSE)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to convert between src and mem datatypes")
- if(NULL == (tpath_mem_dst = H5T_path_find(dt_mem, attr_dst->dt, NULL, NULL, dxpl_id, FALSE)))
+ if(NULL == (tpath_mem_dst = H5T_path_find(dt_mem, attr_dst->shared->dt, NULL, NULL, dxpl_id, FALSE)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to convert between mem and dst datatypes")
/* Determine largest datatype size */
- if(0 == (src_dt_size = H5T_get_size(attr_src->dt)))
+ if(0 == (src_dt_size = H5T_get_size(attr_src->shared->dt)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to determine datatype size")
if(0 == (tmp_dt_size = H5T_get_size(dt_mem)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to determine datatype size")
max_dt_size = MAX(src_dt_size, tmp_dt_size);
- if(0 == (tmp_dt_size = H5T_get_size(attr_dst->dt)))
+ if(0 == (tmp_dt_size = H5T_get_size(attr_dst->shared->dt)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to determine datatype size")
max_dt_size = MAX(max_dt_size, tmp_dt_size);
/* Set number of whole elements that fit in buffer */
- if(0 == (nelmts = attr_src->data_size / src_dt_size))
+ if(0 == (nelmts = attr_src->shared->data_size / src_dt_size))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "element size too large")
/* Set up number of bytes to copy, and initial buffer size */
@@ -796,7 +821,7 @@ H5O_attr_copy_file(H5F_t UNUSED *file_src, const H5O_msg_class_t UNUSED *mesg_ty
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, NULL, "can't create simple dataspace")
/* Atomize */
- if((buf_sid = H5I_register(H5I_DATASPACE, buf_space)) < 0) {
+ if((buf_sid = H5I_register(H5I_DATASPACE, buf_space, FALSE)) < 0) {
H5S_close(buf_space);
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, NULL, "unable to register dataspace ID")
} /* end if */
@@ -809,7 +834,7 @@ H5O_attr_copy_file(H5F_t UNUSED *file_src, const H5O_msg_class_t UNUSED *mesg_ty
if(NULL == (buf = H5FL_BLK_MALLOC(attr_buf, buf_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation NULLed for raw data chunk")
- HDmemcpy(buf, attr_src->data, attr_src->data_size);
+ HDmemcpy(buf, attr_src->shared->data, attr_src->shared->data_size);
/* Convert from source file to memory */
if(H5T_convert(tpath_src_mem, tid_src, tid_mem, nelmts, (size_t)0, (size_t)0, buf, NULL, dxpl_id) < 0)
@@ -821,30 +846,30 @@ H5O_attr_copy_file(H5F_t UNUSED *file_src, const H5O_msg_class_t UNUSED *mesg_ty
if(H5T_convert(tpath_mem_dst, tid_mem, tid_dst, nelmts, (size_t)0, (size_t)0, buf, NULL, dxpl_id) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "datatype conversion NULLed")
- HDmemcpy(attr_dst->data, buf, attr_dst->data_size);
+ HDmemcpy(attr_dst->shared->data, buf, attr_dst->shared->data_size);
if(H5D_vlen_reclaim(tid_mem, buf_space, H5P_DATASET_XFER_DEFAULT, reclaim_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADITER, NULL, "unable to reclaim variable-length data")
} /* end if */
else {
- HDassert(attr_dst->data_size == attr_src->data_size);
- HDmemcpy(attr_dst->data, attr_src->data, attr_src->data_size);
+ HDassert(attr_dst->shared->data_size == attr_src->shared->data_size);
+ HDmemcpy(attr_dst->shared->data, attr_src->shared->data, attr_src->shared->data_size);
} /* end else */
- } /* end if(attr_src->data) */
+ } /* end if(attr_src->shared->data) */
/* Recompute the version to encode the destination attribute */
if(H5A_set_version(file_dst, attr_dst) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "unable to update attribute version")
/* Indicate that the fill values aren't to be written out */
- attr_dst->initialized = TRUE;
+ attr_dst->shared->initialized = TRUE;
/* Set return value */
ret_value = attr_dst;
done:
if(buf_sid > 0)
- if(H5I_dec_ref(buf_sid) < 0)
+ if(H5I_dec_ref(buf_sid, FALSE) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "Can't decrement temporary dataspace ID")
if(tid_src > 0)
/* Don't decrement ID, we want to keep underlying datatype */
@@ -856,7 +881,7 @@ done:
HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "Can't decrement temporary datatype ID")
if(tid_mem > 0)
/* Decrement the memory datatype ID, it's transient */
- if(H5I_dec_ref(tid_mem) < 0)
+ if(H5I_dec_ref(tid_mem, FALSE) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "Can't decrement temporary datatype ID")
if(buf)
buf = H5FL_BLK_FREE(attr_buf, buf);
@@ -864,9 +889,8 @@ done:
reclaim_buf = H5FL_BLK_FREE(attr_buf, reclaim_buf);
/* Release destination attribute information on failure */
- if(!ret_value)
- if(attr_dst)
- (void)H5A_free(attr_dst);
+ if(!ret_value && attr_dst && H5A_close(attr_dst) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute")
FUNC_LEAVE_NOAPI(ret_value)
} /* H5O_attr_copy_file() */
@@ -907,12 +931,11 @@ H5O_attr_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src,
HDassert(attr_dst);
HDassert(file_dst);
-
/* Only need to fix reference attribute with real data being copied to
* another file.
*/
- if((NULL != attr_src->data) &&
- (H5T_get_class(attr_src->dt, FALSE) == H5T_REFERENCE) &&
+ if((NULL != attr_src->shared->data) &&
+ (H5T_get_class(attr_src->shared->dt, FALSE) == H5T_REFERENCE) &&
(file_src != file_dst)) {
/* copy object pointed by reference. The current implementation does not
@@ -924,16 +947,16 @@ H5O_attr_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src,
size_t ref_count;
/* Determine # of reference elements to copy */
- ref_count = attr_dst->data_size / H5T_get_size(attr_dst->dt);
+ ref_count = attr_dst->shared->data_size / H5T_get_size(attr_dst->shared->dt);
/* Copy objects referenced in source buffer to destination file and set destination elements */
- if(H5O_copy_expand_ref(file_src, attr_src->data, dxpl_id,
- file_dst, attr_dst->data, ref_count, H5T_get_ref_type(attr_src->dt), cpy_info) < 0)
+ if(H5O_copy_expand_ref(file_src, attr_src->shared->data, dxpl_id,
+ file_dst, attr_dst->shared->data, ref_count, H5T_get_ref_type(attr_src->shared->dt), cpy_info) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "unable to copy reference attribute")
} /* end if */
else
/* Reset value to zero */
- HDmemset(attr_dst->data, 0, attr_dst->data_size);
+ HDmemset(attr_dst->shared->data, 0, attr_dst->shared->data_size);
} /* end if */
done:
@@ -965,7 +988,7 @@ H5O_attr_get_crt_index(const void *_mesg, H5O_msg_crt_idx_t *crt_idx /*out*/)
HDassert(crt_idx);
/* Get the attribute's creation index */
- *crt_idx = attr->crt_idx;
+ *crt_idx = attr->shared->crt_idx;
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_attr_get_crt_index() */
@@ -994,7 +1017,7 @@ H5O_attr_set_crt_index(void *_mesg, H5O_msg_crt_idx_t crt_idx)
HDassert(attr);
/* Set the creation index */
- attr->crt_idx = crt_idx;
+ attr->shared->crt_idx = crt_idx;
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_attr_set_crt_index() */
@@ -1037,8 +1060,8 @@ H5O_attr_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int in
fprintf(stream, "%*s%-*s \"%s\"\n", indent, "", fwidth,
"Name:",
- mesg->name);
- switch(mesg->encoding) {
+ mesg->shared->name);
+ switch(mesg->shared->encoding) {
case H5T_CSET_ASCII:
s = "ASCII";
break;
@@ -1046,7 +1069,7 @@ H5O_attr_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int in
s = "UTF-8";
break;
default:
- sprintf(buf, "H5T_CSET_RESERVED_%d", (int)(mesg->encoding));
+ sprintf(buf, "H5T_CSET_RESERVED_%d", (int)(mesg->shared->encoding));
s = buf;
break;
} /* end switch */
@@ -1055,32 +1078,32 @@ H5O_attr_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int in
s);
HDfprintf(stream, "%*s%-*s %t\n", indent, "", fwidth,
"Initialized:",
- mesg->initialized);
+ mesg->shared->initialized);
HDfprintf(stream, "%*s%-*s %t\n", indent, "", fwidth,
"Object opened:",
mesg->obj_opened);
HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
"Object:",
- mesg->oloc.addr);
+ mesg->shared->oloc.addr);
/* Check for attribute creation order index on the attribute */
- if(mesg->crt_idx != H5O_MAX_CRT_ORDER_IDX)
+ if(mesg->shared->crt_idx != H5O_MAX_CRT_ORDER_IDX)
HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
"Creation Index:",
- (unsigned)mesg->crt_idx);
+ (unsigned)mesg->shared->crt_idx);
fprintf(stream, "%*sDatatype...\n", indent, "");
fprintf(stream, "%*s%-*s %lu\n", indent+3, "", MAX(0,fwidth-3),
"Encoded Size:",
- (unsigned long)(mesg->dt_size));
- if((H5O_MSG_DTYPE->debug)(f, dxpl_id, mesg->dt, stream, indent + 3, MAX(0, fwidth - 3)) < 0)
+ (unsigned long)(mesg->shared->dt_size));
+ if((H5O_MSG_DTYPE->debug)(f, dxpl_id, mesg->shared->dt, stream, indent + 3, MAX(0, fwidth - 3)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to display datatype message info")
fprintf(stream, "%*sDataspace...\n", indent, "");
fprintf(stream, "%*s%-*s %lu\n", indent+3, "", MAX(0, fwidth - 3),
"Encoded Size:",
- (unsigned long)(mesg->ds_size));
- if(H5S_debug(f, dxpl_id, mesg->ds, stream, indent+3, MAX(0, fwidth - 3)) < 0)
+ (unsigned long)(mesg->shared->ds_size));
+ if(H5S_debug(f, dxpl_id, mesg->shared->ds, stream, indent+3, MAX(0, fwidth - 3)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to display dataspace message info")
done:
diff --git a/src/H5Oattribute.c b/src/H5Oattribute.c
index 5c9f875..846d2ec 100644
--- a/src/H5Oattribute.c
+++ b/src/H5Oattribute.c
@@ -40,6 +40,8 @@
#include "H5MMprivate.h" /* Memory management */
#include "H5Opkg.h" /* Object headers */
#include "H5SMprivate.h" /* Shared Object Header Messages */
+#include "H5Iprivate.h" /* IDs */
+#include "H5Fprivate.h" /* File */
/****************/
@@ -136,7 +138,8 @@ typedef struct {
static herr_t H5O_attr_iterate_real(hid_t loc_id, const H5O_loc_t *loc,
hid_t dxpl_id, H5_index_t idx_type, H5_iter_order_t order, hsize_t skip,
hsize_t *last_attr, const H5A_attr_iter_op_t *attr_op, void *op_data);
-
+static htri_t H5O_attr_find_opened_attr(const H5O_loc_t *loc, H5A_t **attr,
+ const char* name_to_open);
/*********************/
/* Package Variables */
@@ -306,11 +309,11 @@ H5O_attr_create(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINC, FAIL, "attribute creation index can't be incremented")
/* Set the creation order index on the attribute & incr. creation order index */
- attr->crt_idx = ainfo.max_crt_idx++;
+ attr->shared->crt_idx = ainfo.max_crt_idx++;
} /* end if */
else
/* Set "bogus" creation index for attribute */
- attr->crt_idx = H5O_MAX_CRT_ORDER_IDX;
+ attr->shared->crt_idx = H5O_MAX_CRT_ORDER_IDX;
/* Add the attribute information message, if one is needed */
if(new_ainfo) {
@@ -325,7 +328,7 @@ H5O_attr_create(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr)
} /* end if */
else {
/* Set "bogus" creation index for attribute */
- attr->crt_idx = H5O_MAX_CRT_ORDER_IDX;
+ attr->shared->crt_idx = H5O_MAX_CRT_ORDER_IDX;
/* Set attribute info value to get attribute into object header */
ainfo.fheap_addr = HADDR_UNDEF;
@@ -343,6 +346,12 @@ H5O_attr_create(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to create new attribute in header")
} /* end else */
+ /* Increment reference count for shared attribute object for the
+ * object handle created by the caller function H5A_create. The count
+ * for the cached object header has been incremented in the step above
+ * (in H5O_msg_append_real). The dense storage doesn't need a count. */
+ attr->shared->nrefs += 1;
+
/* Was new attribute shared? */
if((shared_mesg = H5O_msg_is_shared(H5O_ATTR_ID, attr)) > 0) {
hsize_t attr_rc; /* Attribute's ref count in shared message storage */
@@ -426,14 +435,14 @@ H5O_attr_open_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/, unsigned sequence,
HDassert(!udata->attr);
/* Check for correct attribute message to modify */
- if(HDstrcmp(((H5A_t *)mesg->native)->name, udata->name) == 0) {
+ if(HDstrcmp(((H5A_t *)mesg->native)->shared->name, udata->name) == 0) {
/* Make a copy of the attribute to return */
if(NULL == (udata->attr = H5A_copy(NULL, (H5A_t *)mesg->native)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "unable to copy attribute")
/* Assign [somewhat arbitrary] creation order value, for older versions of the format */
if(oh->version == H5O_VERSION_1)
- udata->attr->crt_idx = sequence;
+ udata->attr->shared->crt_idx = sequence;
/* Stop iterating */
ret_value = H5_ITER_STOP;
@@ -454,6 +463,11 @@ done:
* Programmer: Quincey Koziol
* Monday, December 11, 2006
*
+ * Modification:Raymond Lu
+ * 23 June 2008
+ * If the attribute is in dense storage and has already been
+ * opened, make a copy of already opened object to share some
+ * object information.
*-------------------------------------------------------------------------
*/
H5A_t *
@@ -462,6 +476,8 @@ H5O_attr_open_by_name(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
H5O_t *oh = NULL; /* Pointer to actual object header */
H5O_ainfo_t ainfo; /* Attribute information for object */
H5A_t *ret_value; /* Return value */
+ H5A_t *exist_attr = NULL; /* Opened attribute object */
+ htri_t found_open_attr = FALSE; /* Whether opened object is found */
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_open_by_name)
@@ -479,34 +495,40 @@ H5O_attr_open_by_name(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
/* Clear error stack from not finding attribute info */
H5E_clear_stack(NULL);
- /* Check for opening attribute with dense storage */
- if(H5F_addr_defined(ainfo.fheap_addr)) {
- /* Open attribute in dense storage */
- if(NULL == (ret_value = H5A_dense_open(loc->file, dxpl_id, &ainfo, name)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "can't open attribute")
- } /* end if */
- else {
- H5O_iter_opn_t udata; /* User data for callback */
- H5O_mesg_operator_t op; /* Wrapper for operator */
-
- /* Set up user data for callback */
- udata.name = name;
- udata.attr = NULL;
-
- /* Iterate over attributes, to locate correct one to open */
- op.op_type = H5O_MESG_OP_LIB;
- op.u.lib_op = H5O_attr_open_cb;
- if(H5O_msg_iterate_real(loc->file, oh, H5O_MSG_ATTR, &op, &udata, dxpl_id) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "error updating attribute")
-
- /* Check that we found the attribute */
- if(!udata.attr)
- HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "can't locate attribute")
-
- /* Get attribute opened from object header */
- HDassert(udata.attr);
- ret_value = udata.attr;
- } /* end else */
+ /* If found the attribute is already opened, make a copy of it to share the
+ object information. If not, open attribute as a new object */
+ if((found_open_attr = H5O_attr_find_opened_attr(loc, &exist_attr, name)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, NULL, "failed in finding opened attribute")
+ else if(found_open_attr == TRUE) {
+ if(NULL == (ret_value = H5A_copy(NULL, exist_attr)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "can't copy existing attribute")
+ } else {
+ if(H5F_addr_defined(ainfo.fheap_addr)) { /* open attribute with dense storage */
+ if(NULL == (ret_value = H5A_dense_open(loc->file, dxpl_id, &ainfo, name)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "can't open attribute")
+ } else {
+ H5O_iter_opn_t udata; /* User data for callback */
+ H5O_mesg_operator_t op; /* Wrapper for operator */
+
+ /* Set up user data for callback */
+ udata.name = name;
+ udata.attr = NULL;
+
+ /* Iterate over attributes, to locate correct one to open */
+ op.op_type = H5O_MESG_OP_LIB;
+ op.u.lib_op = H5O_attr_open_cb;
+ if(H5O_msg_iterate_real(loc->file, oh, H5O_MSG_ATTR, &op, &udata, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "error updating attribute")
+
+ /* Check that we found the attribute */
+ if(!udata.attr)
+ HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "can't locate attribute")
+
+ /* Get attribute opened from object header */
+ HDassert(udata.attr);
+ ret_value = udata.attr;
+ } /* end else */
+ }
done:
if(oh && H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, oh, H5AC__NO_FLAGS_SET) < 0)
@@ -542,7 +564,7 @@ H5O_attr_open_by_idx_cb(const H5A_t *attr, void *_ret_attr)
HDassert(attr);
HDassert(ret_attr);
- /* Copy attribute information */
+ /* Copy attribute information. Shared some attribute information. */
if(NULL == (*ret_attr = H5A_copy(NULL, attr)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute")
@@ -562,6 +584,11 @@ done:
* Programmer: Quincey Koziol
* Monday, December 18, 2006
*
+ * Modification:Raymond Lu
+ * 23 June 2008
+ * After opening the attribute, check whether it's in dense
+ * storage and has already been opened. If it has, close the
+ * opened object and make a copy of already opened object.
*-------------------------------------------------------------------------
*/
H5A_t *
@@ -569,7 +596,11 @@ H5O_attr_open_by_idx(const H5O_loc_t *loc, H5_index_t idx_type,
H5_iter_order_t order, hsize_t n, hid_t dxpl_id)
{
H5A_attr_iter_op_t attr_op; /* Attribute operator */
+ H5A_t *exist_attr = NULL; /* Opened attribute object */
+ htri_t found_open_attr = FALSE; /* Whether opened object is found */
H5A_t *ret_value = NULL; /* Return value */
+ H5O_t *oh = NULL; /* Object header */
+ H5O_ainfo_t ainfo; /* Attribute information for object */
FUNC_ENTER_NOAPI_NOINIT(H5O_attr_open_by_idx)
@@ -584,12 +615,113 @@ H5O_attr_open_by_idx(const H5O_loc_t *loc, H5_index_t idx_type,
if(H5O_attr_iterate_real((hid_t)-1, loc, dxpl_id, idx_type, order, n, NULL, &attr_op, &ret_value) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_BADITER, NULL, "can't locate attribute")
+
+ /* Protect the object header to iterate over */
+ if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, NULL, "unable to load object header")
+
+ /* Check for attribute info stored */
+ ainfo.fheap_addr = HADDR_UNDEF;
+ if(oh->version > H5O_VERSION_1 && NULL == H5A_get_ainfo(loc->file, dxpl_id, oh, &ainfo))
+ /* Clear error stack from not finding attribute info */
+ H5E_clear_stack(NULL);
+
+ /* Find out whether it has already been opened. If it has, close the object
+ * and make a copy of the already opened object to share the object info. */
+ if(ret_value) {
+ if((found_open_attr = H5O_attr_find_opened_attr(loc, &exist_attr,
+ ret_value->shared->name)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, NULL, "failed in finding opened attribute")
+
+ /* If found that the attribute is already opened, make a copy of it
+ and close the object just opened. */
+ if(found_open_attr && exist_attr) {
+ if(H5A_close(ret_value) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCLOSEOBJ, NULL, "can't close attribute")
+
+ if(NULL == (ret_value = H5A_copy(NULL, exist_attr)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "can't copy existing attribute")
+ }
+ }
+
done:
+ if(oh && H5AC_unprotect(loc->file, H5AC_ind_dxpl_id, H5AC_OHDR, loc->addr, oh,
+ H5AC__NO_FLAGS_SET) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_PROTECT, NULL, "unable to release object header")
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_attr_open_by_idx() */
/*-------------------------------------------------------------------------
+ * Function: H5O_attr_find_opened_attr
+ *
+ * Purpose: Find out whether an attribute has been opened by giving
+ * the name. Return the pointer to the object if found.
+ *
+ * Return: TRUE: found the already opened object
+ * FALSE: didn't find the opened object
+ * FAIL: function failed.
+ *
+ * Programmer: Raymond Lu
+ * 23 June 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static
+htri_t H5O_attr_find_opened_attr(const H5O_loc_t *loc, H5A_t **attr, const char* name_to_open)
+{
+ htri_t ret_value = FALSE;
+ int num_open_attr = 0;
+ hid_t *attr_id_list = NULL;
+ unsigned long loc_fnum, attr_fnum;
+ int i;
+
+ FUNC_ENTER_NOAPI_NOINIT(H5O_attr_find_opened_attr)
+
+ /* Get file serial number for the location of attribute */
+ if(H5F_get_fileno(loc->file, &loc_fnum) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, "can't get file serial number")
+
+ /* Count all opened attributes */
+ if((num_open_attr = H5F_get_obj_count(loc->file, H5F_OBJ_ATTR | H5F_OBJ_LOCAL, FALSE)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, FAIL, "can't get number of opened attributes")
+
+ /* Find out whether the attribute has been opened */
+ if(num_open_attr) {
+ attr_id_list = (hid_t*)H5MM_malloc(num_open_attr*sizeof(hid_t));
+
+ /* Retrieve the IDs of all opened attributes */
+ if(H5F_get_obj_ids(loc->file, H5F_OBJ_ATTR | H5F_OBJ_LOCAL, num_open_attr, attr_id_list, FALSE) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't IDs of opened attributes")
+
+ for(i=0; i<num_open_attr; i++) {
+ if(NULL == (*attr = (H5A_t *)H5I_object_verify(attr_id_list[i], H5I_ATTR)))
+ HGOTO_ERROR(H5E_ATTR, H5E_BADTYPE, FAIL, "not an attribute")
+
+ /* Get file serial number for attribute */
+ if(H5F_get_fileno((*attr)->shared->oloc.file, &attr_fnum) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, "can't get file serial number")
+
+ /* Verify whether it's the right object. The attribute name, object address
+ * to which the attribute is attached, and file serial number should all
+ * match. */
+ if(!strcmp(name_to_open, (*attr)->shared->name) &&
+ loc->addr == (*attr)->shared->oloc.addr &&
+ loc_fnum == attr_fnum) {
+ ret_value = TRUE;
+ break;
+ }
+ }
+ H5MM_free(attr_id_list);
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_attr_find_opened_attr */
+
+
+/*-------------------------------------------------------------------------
* Function: H5O_attr_update_shared
*
* Purpose: Update a shared attribute.
@@ -677,6 +809,10 @@ done:
* koziol@hdfgroup.org
* Dec 4 2006
*
+ * Modification:Raymond Lu
+ * 4 June 2008
+ * Took out the data copying part because the attribute data
+ * is shared between attribute handle and object header.
*-------------------------------------------------------------------------
*/
static herr_t
@@ -694,18 +830,7 @@ H5O_attr_write_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
HDassert(!udata->found);
/* Check for correct attribute message to modify */
- if(HDstrcmp(((H5A_t *)mesg->native)->name, udata->attr->name) == 0) {
- /* Allocate storage for the message's data, if necessary */
- if(((H5A_t *)mesg->native)->data == NULL)
- if(NULL == (((H5A_t *)mesg->native)->data = H5FL_BLK_MALLOC(attr_buf, udata->attr->data_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5_ITER_ERROR, "memory allocation failed")
-
- /* Copy the data into the header message */
- /* (Needs to occur before updating the shared message, or the hash
- * value on the old & new messages will be the same)
- */
- HDmemcpy(((H5A_t *)mesg->native)->data, udata->attr->data, udata->attr->data_size);
-
+ if(HDstrcmp(((H5A_t *)mesg->native)->shared->name, udata->attr->shared->name) == 0) {
/* Update the shared attribute in the SOHM storage */
if(mesg->flags & H5O_MSG_FLAG_SHARED)
if(H5O_attr_update_shared(udata->f, udata->dxpl_id, oh, udata->attr, (H5O_shared_t *)mesg->native) < 0)
@@ -836,7 +961,7 @@ H5O_attr_rename_chk_cb(H5O_t UNUSED *oh, H5O_mesg_t *mesg/*in,out*/,
HDassert(!udata->found);
/* Check for existing attribute with new name */
- if(HDstrcmp(((H5A_t *)mesg->native)->name, udata->new_name) == 0) {
+ if(HDstrcmp(((H5A_t *)mesg->native)->shared->name, udata->new_name) == 0) {
/* Indicate that we found an existing attribute with the new name*/
udata->found = TRUE;
@@ -882,12 +1007,12 @@ H5O_attr_rename_mod_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
HDassert(!udata->found);
/* Find correct attribute message to rename */
- if(HDstrcmp(((H5A_t *)mesg->native)->name, udata->old_name) == 0) {
- unsigned old_version = ((H5A_t *)mesg->native)->version; /* Old version of the attribute */
+ if(HDstrcmp(((H5A_t *)mesg->native)->shared->name, udata->old_name) == 0) {
+ unsigned old_version = ((H5A_t *)mesg->native)->shared->version; /* Old version of the attribute */
/* Change the name for the attribute */
- H5MM_xfree(((H5A_t *)mesg->native)->name);
- ((H5A_t *)mesg->native)->name = H5MM_xstrdup(udata->new_name);
+ H5MM_xfree(((H5A_t *)mesg->native)->shared->name);
+ ((H5A_t *)mesg->native)->shared->name = H5MM_xstrdup(udata->new_name);
/* Recompute the version to encode the attribute with */
if(H5A_set_version(udata->f, ((H5A_t *)mesg->native)) < 0)
@@ -899,7 +1024,7 @@ H5O_attr_rename_mod_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
/* Check for shared message */
if(mesg->flags & H5O_MSG_FLAG_SHARED) {
/* Update the shared attribute in the SOHM storage */
- if(H5O_attr_update_shared(udata->f, udata->dxpl_id, oh, mesg->native, NULL) < 0)
+ if(H5O_attr_update_shared(udata->f, udata->dxpl_id, oh, (H5A_t *)mesg->native, NULL) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, H5_ITER_ERROR, "unable to update attribute in shared storage")
} /* end if */
else {
@@ -908,10 +1033,10 @@ H5O_attr_rename_mod_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
/* Check for attribute message changing size */
if(HDstrlen(udata->new_name) != HDstrlen(udata->old_name) ||
- old_version != ((H5A_t *)mesg->native)->version) {
+ old_version != ((H5A_t *)mesg->native)->shared->version) {
H5A_t *attr; /* Attribute to re-add */
- /* Take ownership of the message's native info (the attribute)
+ /* Take ownership of the message's native info (the attribute)
* so any shared objects in the file aren't adjusted (and
* possibly deleted) when the message is released.
*/
@@ -939,8 +1064,8 @@ H5O_attr_rename_mod_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
/* Sanity check */
HDassert(H5O_msg_is_shared(H5O_ATTR_ID, attr) == FALSE);
- /* Release the local copy of the attribute */
- H5O_msg_free_real(H5O_MSG_ATTR, attr);
+ /* Close the local copy of the attribute */
+ H5A_close(attr);
} /* end if */
} /* end else */
@@ -1081,7 +1206,8 @@ H5O_attr_iterate_real(hid_t loc_id, const H5O_loc_t *loc, hid_t dxpl_id,
HDassert(attr_op);
/* Protect the object header to iterate over */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr,
+ NULL, NULL, (H5F_get_intent(loc->file) & H5F_ACC_RDWR) ? H5AC_WRITE : H5AC_READ)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, FAIL, "unable to load object header")
/* Check for attribute info stored */
@@ -1184,6 +1310,14 @@ done:
* Programmer: Quincey Koziol
* Wednesday, February 14, 2007
*
+ * Modification:Raymond Lu
+ * 24 June 2008
+ * When converting storage from dense to compact, if found
+ * the attribute is already opened, use the opened message
+ * to insert. If not, still use the message in the attribute
+ * table. This will guarantee that the attribute message is
+ * shared between the object in metadata cache and the opened
+ * object.
*-------------------------------------------------------------------------
*/
static herr_t
@@ -1217,35 +1351,51 @@ H5O_attr_remove_update(const H5O_loc_t *loc, H5O_t *oh, H5O_ainfo_t *ainfo,
* can't fit into an object header message)
*/
for(u = 0; u < ainfo->nattrs; u++)
- if(H5O_msg_size_oh(loc->file, oh, H5O_ATTR_ID, &(atable.attrs[u]), (size_t)0) >= H5O_MESG_MAX_SIZE) {
+ if(H5O_msg_size_oh(loc->file, oh, H5O_ATTR_ID, (atable.attrs[u]), (size_t)0) >= H5O_MESG_MAX_SIZE) {
can_convert = FALSE;
break;
} /* end if */
/* If ok, insert attributes as object header messages */
if(can_convert) {
+ H5A_t *exist_attr = NULL;
+ htri_t found_open_attr = FALSE;
+
/* Iterate over attributes, to put them into header */
for(u = 0; u < ainfo->nattrs; u++) {
htri_t shared_mesg; /* Should this message be stored in the Shared Message table? */
/* Check if attribute is shared */
- if((shared_mesg = H5O_msg_is_shared(H5O_ATTR_ID, &(atable.attrs[u]))) < 0)
+ if((shared_mesg = H5O_msg_is_shared(H5O_ATTR_ID, (atable.attrs[u]))) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "error determining if message is shared")
else if(shared_mesg == 0) {
/* Increment reference count on attribute components */
/* (so that they aren't deleted when the dense attribute storage is deleted) */
- if(H5O_attr_link(loc->file, dxpl_id, oh, &(atable.attrs[u])) < 0)
+ if(H5O_attr_link(loc->file, dxpl_id, oh, (atable.attrs[u])) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust attribute link count")
} /* end if */
else {
/* Reset 'shared' status, so attribute will be shared again */
- atable.attrs[u].sh_loc.type = H5O_SHARE_TYPE_UNSHARED;
+ (atable.attrs[u])->sh_loc.type = H5O_SHARE_TYPE_UNSHARED;
} /* end else */
- /* Insert attribute message into object header */
- /* (Will increment reference count on shared attributes) */
- if(H5O_msg_append_real(loc->file, dxpl_id, oh, H5O_MSG_ATTR, 0, 0, &(atable.attrs[u])) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "can't create message")
+ /* Insert attribute message into object header (Will increment
+ reference count on shared attributes) */
+ /* Find out whether the attribute has been opened */
+ if((found_open_attr = H5O_attr_find_opened_attr(loc, &exist_attr,
+ (atable.attrs[u])->shared->name)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "failed in finding opened attribute")
+
+ /* If found the attribute is already opened, use the opened message to insert.
+ If not, still use the message in the attribute table. */
+ if(found_open_attr && exist_attr) {
+ if(H5O_msg_append_real(loc->file, dxpl_id, oh, H5O_MSG_ATTR, 0, 0, exist_attr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "can't create message")
+
+ } else {
+ if(H5O_msg_append_real(loc->file, dxpl_id, oh, H5O_MSG_ATTR, 0, 0, (atable.attrs[u])) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "can't create message")
+ }
} /* end for */
/* Remove the dense storage */
@@ -1304,7 +1454,7 @@ H5O_attr_remove_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
HDassert(!udata->found);
/* Check for correct attribute message to modify */
- if(HDstrcmp(((H5A_t *)mesg->native)->name, udata->name) == 0) {
+ if(HDstrcmp(((H5A_t *)mesg->native)->shared->name, udata->name) == 0) {
/* Convert message into a null message (i.e. delete it) */
if(H5O_release_mesg(udata->f, udata->dxpl_id, oh, mesg, TRUE) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, H5_ITER_ERROR, "unable to convert into null message")
@@ -1468,7 +1618,7 @@ H5O_attr_remove_by_idx(const H5O_loc_t *loc, H5_index_t idx_type,
/* Set up user data for callback, to remove the attribute by name */
udata.f = loc->file;
udata.dxpl_id = dxpl_id;
- udata.name = atable.attrs[n].name;
+ udata.name = ((atable.attrs[n])->shared)->name;
udata.found = FALSE;
/* Iterate over attributes, to locate correct one to delete */
@@ -1582,7 +1732,7 @@ H5O_attr_exists_cb(H5O_t UNUSED *oh, H5O_mesg_t *mesg/*in,out*/,
HDassert(!udata->found);
/* Check for correct attribute message */
- if(HDstrcmp(((H5A_t *)mesg->native)->name, udata->name) == 0) {
+ if(HDstrcmp(((H5A_t *)mesg->native)->shared->name, udata->name) == 0) {
/* Indicate that this message is the attribute sought */
udata->found = TRUE;
diff --git a/src/H5Obogus.c b/src/H5Obogus.c
index 1233ec0..c257ca4 100644
--- a/src/H5Obogus.c
+++ b/src/H5Obogus.c
@@ -38,7 +38,8 @@
#ifdef H5O_ENABLE_BOGUS
/* PRIVATE PROTOTYPES */
-static void *H5O_bogus_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags, const uint8_t *p);
+static void *H5O_bogus_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags,
+ unsigned *ioflags, const uint8_t *p);
static herr_t H5O_bogus_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
static size_t H5O_bogus_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
static herr_t H5O_bogus_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream,
@@ -87,7 +88,7 @@ const H5O_msg_class_t H5O_MSG_BOGUS[1] = {{
*/
static void *
H5O_bogus_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
- const uint8_t *p)
+ unsigned UNUSED *ioflags, const uint8_t *p)
{
H5O_bogus_t *mesg = NULL;
void *ret_value; /* Return value */
diff --git a/src/H5Obtreek.c b/src/H5Obtreek.c
index e116ff2..36e4c1a 100644
--- a/src/H5Obtreek.c
+++ b/src/H5Obtreek.c
@@ -28,7 +28,8 @@
#include "H5Opkg.h" /* Object headers */
#include "H5MMprivate.h" /* Memory management */
-static void *H5O_btreek_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags, const uint8_t *p);
+static void *H5O_btreek_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags,
+ unsigned *ioflags, const uint8_t *p);
static herr_t H5O_btreek_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
static void *H5O_btreek_copy(const void *_mesg, void *_dest);
static size_t H5O_btreek_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
@@ -79,7 +80,7 @@ const H5O_msg_class_t H5O_MSG_BTREEK[1] = {{
*/
static void *
H5O_btreek_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
- const uint8_t *p)
+ unsigned UNUSED *ioflags, const uint8_t *p)
{
H5O_btreek_t *mesg; /* Native message */
void *ret_value; /* Return value */
@@ -95,11 +96,11 @@ H5O_btreek_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_fl
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for message")
/* Allocate space for message */
- if(NULL == (mesg = H5MM_calloc(sizeof(H5O_btreek_t))))
+ if(NULL == (mesg = (H5O_btreek_t *)H5MM_calloc(sizeof(H5O_btreek_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for v1 B-tree 'K' message")
/* Retrieve non-default B-tree 'K' values */
- UINT16DECODE(p, mesg->btree_k[H5B_ISTORE_ID]);
+ UINT16DECODE(p, mesg->btree_k[H5B_CHUNK_ID]);
UINT16DECODE(p, mesg->btree_k[H5B_SNODE_ID]);
UINT16DECODE(p, mesg->sym_leaf_k);
@@ -137,7 +138,7 @@ H5O_btreek_encode(H5F_t UNUSED *f, hbool_t UNUSED disable_shared, uint8_t *p, co
/* Store version and non-default v1 B-tree 'K' values */
*p++ = H5O_BTREEK_VERSION;
- UINT16ENCODE(p, mesg->btree_k[H5B_ISTORE_ID]);
+ UINT16ENCODE(p, mesg->btree_k[H5B_CHUNK_ID]);
UINT16ENCODE(p, mesg->btree_k[H5B_SNODE_ID]);
UINT16ENCODE(p, mesg->sym_leaf_k);
@@ -171,7 +172,7 @@ H5O_btreek_copy(const void *_mesg, void *_dest)
/* Sanity check */
HDassert(mesg);
- if(!dest && NULL == (dest = H5MM_malloc(sizeof(H5O_btreek_t))))
+ if(!dest && NULL == (dest = (H5O_btreek_t *)H5MM_malloc(sizeof(H5O_btreek_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for shared message table message")
/* All this message requires is a shallow copy */
@@ -210,7 +211,7 @@ H5O_btreek_size(const H5F_t UNUSED *f, hbool_t UNUSED disable_shared, const void
HDassert(f);
ret_value = 1 + /* Version number */
- 2 + /* Indexed storage internal B-tree 'K' value */
+ 2 + /* Chunked storage internal B-tree 'K' value */
2 + /* Symbol table node internal B-tree 'K' value */
2; /* Symbol table node leaf 'K' value */
@@ -246,7 +247,7 @@ H5O_btreek_debug(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const void *_mesg, FILE
HDassert(fwidth >= 0);
HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
- "Indexed storage internal B-tree 'K' value:", mesg->btree_k[H5B_ISTORE_ID]);
+ "Chunked storage internal B-tree 'K' value:", mesg->btree_k[H5B_CHUNK_ID]);
HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
"Symbol table node internal B-tree 'K' value:", mesg->btree_k[H5B_SNODE_ID]);
HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
diff --git a/src/H5Ocache.c b/src/H5Ocache.c
index b5c8c7d..c50f557 100644
--- a/src/H5Ocache.c
+++ b/src/H5Ocache.c
@@ -37,6 +37,7 @@
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
#include "H5FLprivate.h" /* Free lists */
+#include "H5MFprivate.h" /* File memory management */
#include "H5Opkg.h" /* Object headers */
@@ -130,8 +131,7 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
unsigned merged_null_msgs = 0; /* Number of null messages merged together */
haddr_t chunk_addr; /* Address of first chunk */
size_t chunk_size; /* Size of first chunk */
- haddr_t abs_eoa; /* Absolute end of file address */
- haddr_t rel_eoa; /* Relative end of file address */
+ haddr_t eoa; /* Relative end of file address */
H5O_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5O_load, NULL)
@@ -143,14 +143,11 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
HDassert(!_udata2);
/* Make certain we don't speculatively read off the end of the file */
- if(HADDR_UNDEF == (abs_eoa = H5F_get_eoa(f)))
+ if(HADDR_UNDEF == (eoa = H5F_get_eoa(f, H5FD_MEM_OHDR)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to determine file size")
- /* Adjust absolute EOA address to relative EOA address */
- rel_eoa = abs_eoa - H5F_get_base_addr(f);
-
/* Compute the size of the speculative object header buffer */
- H5_ASSIGN_OVERFLOW(spec_read_size, MIN(rel_eoa - addr, H5O_SPEC_READ_SIZE), /* From: */ hsize_t, /* To: */ size_t);
+ H5_ASSIGN_OVERFLOW(spec_read_size, MIN(eoa - addr, H5O_SPEC_READ_SIZE), /* From: */ hsize_t, /* To: */ size_t);
/* Attempt to speculatively read both object header prefix and first chunk */
if(H5F_block_read(f, H5FD_MEM_OHDR, addr, spec_read_size, dxpl_id, read_buf) < 0)
@@ -167,9 +164,9 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
/* Check for magic number */
/* (indicates version 2 or later) */
- if(!HDmemcmp(p, H5O_HDR_MAGIC, (size_t)H5O_SIZEOF_MAGIC)) {
+ if(!HDmemcmp(p, H5O_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC)) {
/* Magic number */
- p += H5O_SIZEOF_MAGIC;
+ p += H5_SIZEOF_MAGIC;
/* Version */
oh->version = *p++;
@@ -349,9 +346,9 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
/* Check for magic # on chunks > 0 in later versions of the format */
if(chunkno > 0 && oh->version > H5O_VERSION_1) {
/* Magic number */
- if(HDmemcmp(p, H5O_CHK_MAGIC, (size_t)H5O_SIZEOF_MAGIC))
+ if(HDmemcmp(p, H5O_CHK_MAGIC, (size_t)H5_SIZEOF_MAGIC))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "wrong object header chunk signature")
- p += H5O_SIZEOF_MAGIC;
+ p += H5_SIZEOF_MAGIC;
} /* end if */
/* Decode messages from this chunk */
@@ -415,7 +412,7 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
#endif /* NDEBUG */
/* Check for combining two adjacent 'null' messages */
- if((H5F_get_intent(f) & H5F_ACC_RDWR) &&
+ if((H5F_INTENT(f) & H5F_ACC_RDWR) &&
H5O_NULL_ID == id && oh->nmesgs > 0 &&
H5O_NULL_ID == oh->mesg[oh->nmesgs - 1].type->id &&
oh->mesg[oh->nmesgs - 1].chunkno == chunkno) {
@@ -468,7 +465,7 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
/* Check for "mark if unknown" message flag, etc. */
else if((flags & H5O_MSG_FLAG_MARK_IF_UNKNOWN) &&
!(flags & H5O_MSG_FLAG_WAS_UNKNOWN) &&
- (H5F_get_intent(f) & H5F_ACC_RDWR)) {
+ (H5F_INTENT(f) & H5F_ACC_RDWR)) {
/* Mark the message as "unknown" */
/* This is a bit aggressive, since the application may
@@ -536,9 +533,10 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
/* Check if next message to examine is a continuation message */
if(H5O_CONT_ID == oh->mesg[curmesg].type->id) {
H5O_cont_t *cont;
+ unsigned ioflags = 0; /* Flags for decode routine */
/* Decode continuation message */
- cont = (H5O_cont_t *)(H5O_MSG_CONT->decode)(f, dxpl_id, 0, oh->mesg[curmesg].raw);
+ cont = (H5O_cont_t *)(H5O_MSG_CONT->decode)(f, dxpl_id, 0, &ioflags, oh->mesg[curmesg].raw);
cont->chunkno = oh->nchunks; /*the next chunk to allocate */
/* Save 'native' form of continuation message */
@@ -547,14 +545,21 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
/* Set up to read in next chunk */
chunk_addr = cont->addr;
chunk_size = cont->size;
+
+ /* Mark the object header as dirty if the message was changed by decoding */
+ if((ioflags & H5O_DECODEIO_DIRTY) && (H5F_get_intent(f) & H5F_ACC_RDWR)) {
+ oh->mesg[curmesg].dirty = TRUE;
+ oh->cache_info.is_dirty = TRUE;
+ }
} /* end if */
/* Check if next message to examine is a ref. count message */
else if(H5O_REFCOUNT_ID == oh->mesg[curmesg].type->id) {
H5O_refcount_t *refcount;
+ unsigned ioflags = 0; /* Flags for decode routine */
/* Decode ref. count message */
HDassert(oh->version > H5O_VERSION_1);
- refcount = (H5O_refcount_t *)(H5O_MSG_REFCOUNT->decode)(f, dxpl_id, 0, oh->mesg[curmesg].raw);
+ refcount = (H5O_refcount_t *)(H5O_MSG_REFCOUNT->decode)(f, dxpl_id, 0, &ioflags, oh->mesg[curmesg].raw);
/* Save 'native' form of ref. count message */
oh->mesg[curmesg].native = refcount;
@@ -562,6 +567,12 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
/* Set object header values */
oh->has_refcount_msg = TRUE;
oh->nlink = *refcount;
+
+ /* Mark the object header as dirty if the message was changed by decoding */
+ if((ioflags & H5O_DECODEIO_DIRTY) && (H5F_get_intent(f) & H5F_ACC_RDWR)) {
+ oh->mesg[curmesg].dirty = TRUE;
+ oh->cache_info.is_dirty = TRUE;
+ }
} /* end if */
/* Check if next message to examine is a link message */
else if(H5O_LINK_ID == oh->mesg[curmesg].type->id) {
@@ -580,10 +591,25 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1,
if(merged_null_msgs)
oh->cache_info.is_dirty = TRUE;
+/* Don't check for the incorrect # of object header messages bug unless we've
+ * enabled strict format checking. This allows for older files, created with
+ * a version of the library that had a bug in tracking the correct # of header
+ * messages to be read in without the library fussing about things. -QAK
+ */
+#ifdef H5_STRICT_FORMAT_CHECKS
/* Sanity check for the correct # of messages in object header */
if(oh->version == H5O_VERSION_1)
if((oh->nmesgs + merged_null_msgs) != nmesgs)
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "corrupt object header - too few messages")
+#else /* H5_STRICT_FORMAT_CHECKS */
+ /* Check for incorrect # of messages in object header and if we have write
+ * access on the file, flag the object header as dirty, so it gets fixed.
+ */
+ if(oh->version == H5O_VERSION_1)
+ if((oh->nmesgs + merged_null_msgs) != nmesgs &&
+ (H5F_get_intent(f) & H5F_ACC_RDWR))
+ oh->cache_info.is_dirty = TRUE;
+#endif /* H5_STRICT_FORMAT_CHECKS */
#ifdef H5O_DEBUG
H5O_assert(oh);
@@ -653,8 +679,8 @@ H5O_assert(oh);
uint64_t chunk0_size = oh->chunk[0].size - H5O_SIZEOF_HDR(oh); /* Size of chunk 0's data */
/* Verify magic number */
- HDassert(!HDmemcmp(p, H5O_HDR_MAGIC, H5O_SIZEOF_MAGIC));
- p += H5O_SIZEOF_MAGIC;
+ HDassert(!HDmemcmp(p, H5O_HDR_MAGIC, H5_SIZEOF_MAGIC));
+ p += H5_SIZEOF_MAGIC;
/* Version */
*p++ = oh->version;
@@ -710,7 +736,12 @@ H5O_assert(oh);
*p++ = 0;
/* Number of messages */
- UINT16ENCODE(p, oh->nmesgs);
+#ifdef H5O_ENABLE_BAD_MESG_COUNT
+ if(oh->store_bad_mesg_count)
+ UINT16ENCODE(p, (oh->nmesgs - 1))
+ else
+#endif /* H5O_ENABLE_BAD_MESG_COUNT */
+ UINT16ENCODE(p, oh->nmesgs);
/* Link count */
UINT32ENCODE(p, oh->nlink);
@@ -726,7 +757,7 @@ H5O_assert(oh);
/* Mark chunk 0 as dirty, since the object header prefix has been updated */
/* (this could be more sophisticated and track whether any prefix fields
- * have been changed, which could save I/O accesses if the
+ * have been changed, which could save I/O accesses if the
* messages in chunk 0 haven't changed - QAK)
*/
HDassert(H5F_addr_eq(addr, oh->chunk[0].addr));
@@ -741,7 +772,7 @@ H5O_assert(oh);
/* Sanity checks */
if(oh->version > H5O_VERSION_1)
/* Make certain the magic # is present */
- HDassert(!HDmemcmp(oh->chunk[u].image, (u == 0 ? H5O_HDR_MAGIC : H5O_CHK_MAGIC), H5O_SIZEOF_MAGIC));
+ HDassert(!HDmemcmp(oh->chunk[u].image, (u == 0 ? H5O_HDR_MAGIC : H5O_CHK_MAGIC), H5_SIZEOF_MAGIC));
else
/* Gaps should never occur in version 1 of the format */
HDassert(oh->chunk[u].gap == 0);
@@ -804,20 +835,37 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5O_dest(H5F_t UNUSED *f, H5O_t *oh)
+H5O_dest(H5F_t *f, H5O_t *oh)
{
unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_dest)
+ FUNC_ENTER_NOAPI_NOINIT(H5O_dest)
+#ifdef QAK
+HDfprintf(stderr, "%s: oh->cache_info.addr = %a\n", FUNC, oh->cache_info.addr);
+HDfprintf(stderr, "%s: oh->cache_info.free_file_space_on_destroy = %t\n", FUNC, oh->cache_info.free_file_space_on_destroy);
+#endif /* QAK */
/* check args */
HDassert(oh);
/* Verify that node is clean */
- HDassert(oh->cache_info.is_dirty == FALSE);
+ HDassert(!oh->cache_info.is_dirty);
+
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!oh->cache_info.free_file_space_on_destroy || H5F_addr_defined(oh->cache_info.addr));
/* destroy chunks */
if(oh->chunk) {
+ /* Check for releasing file space for object header */
+ if(oh->cache_info.free_file_space_on_destroy) {
+ /* Free main (first) object header "chunk" */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_OHDR, H5AC_dxpl_id, oh->chunk[0].addr, (hsize_t)oh->chunk[0].size) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free object header")
+ } /* end if */
+
+ /* Release buffer for each chunk */
for(u = 0; u < oh->nchunks; u++) {
/* Verify that chunk is clean */
HDassert(oh->chunk[u].dirty == 0);
@@ -825,6 +873,7 @@ H5O_dest(H5F_t UNUSED *f, H5O_t *oh)
oh->chunk[u].image = H5FL_BLK_FREE(chunk_image, oh->chunk[u].image);
} /* end for */
+ /* Release array of chunk info */
oh->chunk = (H5O_chunk_t *)H5FL_SEQ_FREE(H5O_chunk_t, oh->chunk);
} /* end if */
@@ -841,9 +890,10 @@ H5O_dest(H5F_t UNUSED *f, H5O_t *oh)
} /* end if */
/* destroy object header */
- H5FL_FREE(H5O_t, oh);
+ (void)H5FL_FREE(H5O_t, oh);
- FUNC_LEAVE_NOAPI(SUCCEED)
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_dest() */
diff --git a/src/H5Ocont.c b/src/H5Ocont.c
index 92c4a3c..b3f178d 100644
--- a/src/H5Ocont.c
+++ b/src/H5Ocont.c
@@ -37,7 +37,8 @@
/* PRIVATE PROTOTYPES */
-static void *H5O_cont_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags, const uint8_t *p);
+static void *H5O_cont_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags,
+ unsigned *ioflags, const uint8_t *p);
static herr_t H5O_cont_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
static size_t H5O_cont_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
static herr_t H5O_cont_free(void *mesg);
@@ -90,7 +91,7 @@ H5FL_DEFINE(H5O_cont_t);
*/
static void *
H5O_cont_decode(H5F_t *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
- const uint8_t *p)
+ unsigned UNUSED *ioflags, const uint8_t *p)
{
H5O_cont_t *cont = NULL;
void *ret_value;
@@ -204,7 +205,7 @@ H5O_cont_free(void *mesg)
HDassert(mesg);
- H5FL_FREE(H5O_cont_t, mesg);
+ (void)H5FL_FREE(H5O_cont_t, mesg);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_cont_free() */
diff --git a/src/H5Ocopy.c b/src/H5Ocopy.c
index 4c6092d..9a905d2 100644
--- a/src/H5Ocopy.c
+++ b/src/H5Ocopy.c
@@ -98,11 +98,11 @@ H5FL_DEFINE(H5O_addr_map_t);
* Purpose: Copy an object (group or dataset) to destination location
* within a file or cross files. PLIST_ID is a property list
* which is used to pass user options and properties to the
- * copy. The name, dst_name, must not already be taken by some
+ * copy. The name, dst_name, must not already be taken by some
* other object in the destination group.
*
* H5Ocopy() will fail if the name of the destination object
- * exists in the destination group. For example,
+ * exists in the destination group. For example,
* H5Ocopy(fid_src, "/dset", fid_dst, "/dset", ...)
* will fail if "/dset" exists in the destination file
*
@@ -112,21 +112,21 @@ H5FL_DEFINE(H5O_addr_map_t);
* the group are copied. Otherwise (default), it will
* recursively copy all objects below the group
* H5O_COPY_EXPAND_SOFT_LINK_FLAG
- * If this flag is specified, it will copy the objects
- * pointed by the soft links. Otherwise (default), it
+ * If this flag is specified, it will copy the objects
+ * pointed by the soft links. Otherwise (default), it
* will copy the soft link as they are
* H5O_COPY_WITHOUT_ATTR_FLAG
- * If this flag is specified, it will copy object without
+ * If this flag is specified, it will copy object without
* copying attributes. Otherwise (default), it will
* copy object along with all its attributes
* H5O_COPY_EXPAND_REFERENCE_FLAG
* 1) Copy object between two different files:
- * When this flag is specified, it will copy objects that
+ * When this flag is specified, it will copy objects that
* are pointed by the references and update the values of
* references in the destination file. Otherwise (default)
* the values of references in the destination will set to
* zero
- * The current implementation does not handle references
+ * The current implementation does not handle references
* inside of other datatype structure. For example, if
* a member of compound datatype is reference, H5Ocopy()
* will copy that field as it is. It will not set the
@@ -137,11 +137,11 @@ H5FL_DEFINE(H5O_addr_map_t);
* Datasets or attributes of references are copied as they
* are, i.e. values of references of the destination object
* are the same as the values of the source object
- *
+ *
* OPTIONS THAT MAY APPLY TO COPY IN THE FUTURE.
* H5O_COPY_EXPAND_EXT_LINK_FLAG
* If this flag is specified, it will expand the external links
- * into new objects, Otherwise (default), it will keep external
+ * into new objects, Otherwise (default), it will keep external
* links as they are (default)
*
* PROPERTIES THAT MAY APPLY TO COPY IN FUTURE
@@ -315,7 +315,8 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
HDassert(cpy_info);
/* Get source object header */
- if(NULL == (oh_src = (H5O_t *)H5AC_protect(oloc_src->file, dxpl_id, H5AC_OHDR, oloc_src->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh_src = (H5O_t *)H5AC_protect(oloc_src->file, dxpl_id, H5AC_OHDR, oloc_src->addr, NULL, NULL,
+ (H5F_get_intent(oloc_src->file) & H5F_ACC_RDWR) ? H5AC_WRITE : H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
/* Get pointer to object class for this object */
@@ -396,7 +397,7 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
if(copy_type->pre_copy_file) {
/* Decode the message if necessary. */
- H5O_LOAD_NATIVE(oloc_src->file, dxpl_id, oh_src, mesg_src, FAIL)
+ H5O_LOAD_NATIVE(oloc_src->file, dxpl_id, 0, oh_src, mesg_src, FAIL)
/* Perform "pre copy" operation on message */
if((copy_type->pre_copy_file)(oloc_src->file, mesg_src->native, &(deleted[mesgno]), cpy_info, udata) < 0)
@@ -467,11 +468,11 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
hbool_t recompute_size; /* Whether copy_file callback created a shared message */
/* Decode the message if necessary. */
- H5O_LOAD_NATIVE(oloc_src->file, dxpl_id, oh_src, mesg_src, FAIL)
+ H5O_LOAD_NATIVE(oloc_src->file, dxpl_id, 0, oh_src, mesg_src, FAIL)
/* Copy the source message */
recompute_size = FALSE;
- if((mesg_dst->native = H5O_msg_copy_file(copy_type,
+ if((mesg_dst->native = H5O_msg_copy_file(copy_type,
oloc_src->file, mesg_src->native, oloc_dst->file,
&recompute_size, cpy_info, udata, dxpl_id)) == NULL)
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object header message")
@@ -591,7 +592,7 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
* header. This will be written when the header is flushed to disk.
*/
if(oh_dst->version > H5O_VERSION_1)
- HDmemcpy(current_pos, H5O_HDR_MAGIC, (size_t)H5O_SIZEOF_MAGIC);
+ HDmemcpy(current_pos, H5O_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
current_pos += H5O_SIZEOF_HDR(oh_dst) - H5O_SIZEOF_CHKSUM_OH(oh_dst);
/* Loop through destination messages, updating their "raw" info */
@@ -719,7 +720,7 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
} /* end if */
/* Insert destination object header in cache */
- if(H5AC_set(oloc_dst->file, dxpl_id, H5AC_OHDR, oloc_dst->addr, oh_dst, H5AC__DIRTIED_FLAG) < 0)
+ if(H5AC_set(oloc_dst->file, dxpl_id, H5AC_OHDR, oloc_dst->addr, oh_dst, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to cache object header")
done:
@@ -860,7 +861,7 @@ H5O_copy_free_addrmap_cb(void *item, void UNUSED *key, void UNUSED *op_data)
HDassert(item);
/* Release the item */
- H5FL_FREE(H5O_addr_map_t, item);
+ (void)H5FL_FREE(H5O_addr_map_t, item);
FUNC_LEAVE_NOAPI(0)
} /* H5O_copy_free_addrmap_cb() */
@@ -1000,8 +1001,8 @@ done:
*
* Return: Non-negative on success/Negative on failure
*
- * Programmer: Peter Cao
- * Aug 7 2006
+ * Programmer: Peter Cao
+ * Aug 7 2006
*
*-------------------------------------------------------------------------
*/
@@ -1056,8 +1057,8 @@ done:
*
* Return: Non-negative on success/Negative on failure
*
- * Programmer: Peter Cao
- * Aug 7 2006
+ * Programmer: Peter Cao
+ * Aug 7 2006
*
*-------------------------------------------------------------------------
*/
@@ -1123,7 +1124,7 @@ H5O_copy_expand_ref(H5F_t *file_src, void *_src_ref, hid_t dxpl_id,
uint8_t *buf; /* Buffer to store serialized selection in */
H5HG_t hobjid; /* Heap object ID */
size_t buf_size; /* Length of object in heap */
-
+
/* Making equivalent references in the destination file */
for(i = 0; i < ref_count; i++) {
/* Get the heap ID for the dataset region */
diff --git a/src/H5Odbg.c b/src/H5Odbg.c
index e77dcfd..7a49f75 100644
--- a/src/H5Odbg.c
+++ b/src/H5Odbg.c
@@ -127,7 +127,7 @@ H5O_assert(const H5O_t *oh)
/* Version specific checks */
if(oh->version > H5O_VERSION_1) {
/* Make certain that the magic number is correct for each chunk */
- HDassert(!HDmemcmp(oh->chunk[u].image, (u == 0 ? H5O_HDR_MAGIC : H5O_CHK_MAGIC), H5O_SIZEOF_MAGIC));
+ HDassert(!HDmemcmp(oh->chunk[u].image, (u == 0 ? H5O_HDR_MAGIC : H5O_CHK_MAGIC), H5_SIZEOF_MAGIC));
/* Check for valid gap size */
HDassert(oh->chunk[u].gap < (size_t)H5O_SIZEOF_MSGHDR_OH(oh));
@@ -402,7 +402,7 @@ H5O_debug_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, haddr_t addr, FILE *stream, i
} /* end for */
/* debug each message */
- if(NULL == (sequence = H5MM_calloc(NELMTS(H5O_msg_class_g) * sizeof(unsigned))))
+ if(NULL == (sequence = (unsigned *)H5MM_calloc(NELMTS(H5O_msg_class_g) * sizeof(unsigned))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
for(i = 0, mesg_total = 0; i < oh->nmesgs; i++) {
const H5O_msg_class_t *debug_type; /* Type of message to use for callbacks */
@@ -488,7 +488,7 @@ H5O_debug_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, haddr_t addr, FILE *stream, i
/* decode the message */
debug_type = oh->mesg[i].type;
if(NULL == oh->mesg[i].native && debug_type->decode)
- H5O_LOAD_NATIVE(f, dxpl_id, oh, &oh->mesg[i], FAIL)
+ H5O_LOAD_NATIVE(f, dxpl_id, H5O_DECODEIO_NOCHANGE, oh, &oh->mesg[i], FAIL)
/* print the message */
HDfprintf(stream, "%*s%-*s\n", indent + 3, "", MAX(0, fwidth - 3),
@@ -498,7 +498,7 @@ H5O_debug_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, haddr_t addr, FILE *stream, i
else
HDfprintf(stream, "%*s<No info for this message>\n", indent + 6, "");
} /* end for */
- sequence = H5MM_xfree(sequence);
+ sequence = (unsigned *)H5MM_xfree(sequence);
if(mesg_total != chunk_total)
HDfprintf(stream, "*** TOTAL SIZE DOES NOT MATCH ALLOCATED SIZE!\n");
@@ -536,7 +536,7 @@ H5O_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int f
HDassert(indent >= 0);
HDassert(fwidth >= 0);
- if(NULL == (oh = H5AC_protect(f, dxpl_id, H5AC_OHDR, addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = (H5O_t *)H5AC_protect(f, dxpl_id, H5AC_OHDR, addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
/* debug */
diff --git a/src/H5Odrvinfo.c b/src/H5Odrvinfo.c
index fd2d049..9aafe41 100644
--- a/src/H5Odrvinfo.c
+++ b/src/H5Odrvinfo.c
@@ -28,7 +28,8 @@
#include "H5Opkg.h" /* Object headers */
#include "H5MMprivate.h" /* Memory management */
-static void *H5O_drvinfo_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags, const uint8_t *p);
+static void *H5O_drvinfo_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags,
+ unsigned *ioflags, const uint8_t *p);
static herr_t H5O_drvinfo_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
static void *H5O_drvinfo_copy(const void *_mesg, void *_dest);
static size_t H5O_drvinfo_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
@@ -80,7 +81,7 @@ const H5O_msg_class_t H5O_MSG_DRVINFO[1] = {{
*/
static void *
H5O_drvinfo_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
- const uint8_t *p)
+ unsigned UNUSED *ioflags, const uint8_t *p)
{
H5O_drvinfo_t *mesg; /* Native message */
void *ret_value; /* Return value */
@@ -96,7 +97,7 @@ H5O_drvinfo_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_f
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for message")
/* Allocate space for message */
- if(NULL == (mesg = H5MM_calloc(sizeof(H5O_drvinfo_t))))
+ if(NULL == (mesg = (H5O_drvinfo_t *)H5MM_calloc(sizeof(H5O_drvinfo_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for driver info message")
/* Retrieve driver name */
@@ -109,8 +110,8 @@ H5O_drvinfo_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_f
HDassert(mesg->len);
/* Allocate space for buffer */
- if(NULL == (mesg->buf = H5MM_malloc(mesg->len))) {
- mesg = H5MM_xfree(mesg);
+ if(NULL == (mesg->buf = (uint8_t *)H5MM_malloc(mesg->len))) {
+ mesg = (H5O_drvinfo_t *)H5MM_xfree(mesg);
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for driver info buffer")
} /* end if */
@@ -187,16 +188,16 @@ H5O_drvinfo_copy(const void *_mesg, void *_dest)
/* Sanity check */
HDassert(mesg);
- if(!dest && NULL == (dest = H5MM_malloc(sizeof(H5O_drvinfo_t))))
+ if(!dest && NULL == (dest = (H5O_drvinfo_t *)H5MM_malloc(sizeof(H5O_drvinfo_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for shared message table message")
/* Shallow copy the fields */
*dest = *mesg;
/* Copy the buffer */
- if(NULL == (dest->buf = H5MM_malloc(mesg->len))) {
+ if(NULL == (dest->buf = (uint8_t *)H5MM_malloc(mesg->len))) {
if(dest != _dest)
- dest = H5MM_xfree(dest);
+ dest = (H5O_drvinfo_t *)H5MM_xfree(dest);
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
} /* end if */
HDmemcpy(dest->buf, mesg->buf, mesg->len);
@@ -269,7 +270,7 @@ H5O_drvinfo_reset(void *_mesg)
HDassert(mesg);
/* reset */
- mesg->buf = H5MM_xfree(mesg->buf);
+ mesg->buf = (uint8_t *)H5MM_xfree(mesg->buf);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_drvinfo_reset() */
diff --git a/src/H5Odtype.c b/src/H5Odtype.c
index ac07edf..71692c1 100644
--- a/src/H5Odtype.c
+++ b/src/H5Odtype.c
@@ -29,7 +29,8 @@
/* PRIVATE PROTOTYPES */
static herr_t H5O_dtype_encode(H5F_t *f, uint8_t *p, const void *mesg);
-static void *H5O_dtype_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags, const uint8_t *p);
+static void *H5O_dtype_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags,
+ unsigned *ioflags, const uint8_t *p);
static void *H5O_dtype_copy(const void *_mesg, void *_dest);
static size_t H5O_dtype_size(const H5F_t *f, const void *_mesg);
static herr_t H5O_dtype_reset(void *_mesg);
@@ -60,11 +61,30 @@ static herr_t H5O_dtype_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg,
#define H5O_SHARED_COPY_FILE H5O_dtype_shared_copy_file
#define H5O_SHARED_COPY_FILE_REAL H5O_dtype_copy_file
#define H5O_SHARED_POST_COPY_FILE H5O_dtype_shared_post_copy_file
-#undef H5O_SHARED_POST_COPY_FILE_REAL
+#undef H5O_SHARED_POST_COPY_FILE_REAL
#define H5O_SHARED_DEBUG H5O_dtype_shared_debug
#define H5O_SHARED_DEBUG_REAL H5O_dtype_debug
#include "H5Oshared.h" /* Shared Object Header Message Callbacks */
+/* Macros to check for the proper version of a datatype */
+#ifdef H5_STRICT_FORMAT_CHECKS
+/* If the version is too low, give an error. No error if nochange is set
+ * because in that case we are either debugging or deleting the object header */
+#define H5O_DTYPE_CHECK_VERSION(DT, VERS, MIN_VERS, IOF, CLASS, ERR) \
+ if(((VERS) < (MIN_VERS)) && !(*(IOF) & H5O_DECODEIO_NOCHANGE)) \
+ HGOTO_ERROR(H5E_DATATYPE, H5E_VERSION, ERR, "incorrect " CLASS " datatype version")
+#else /* H5_STRICT_FORMAT_CHECKS */
+/* If the version is too low and we are allowed to change the message, upgrade
+ * it and mark the object header as dirty */
+#define H5O_DTYPE_CHECK_VERSION(DT, VERS, MIN_VERS, IOF, CLASS, ERR) \
+ if(((VERS) < (MIN_VERS)) && !(*(IOF) & H5O_DECODEIO_NOCHANGE)) { \
+ (VERS) = (MIN_VERS); \
+ if(H5T_upgrade_version((DT), (VERS)) < 0) \
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't upgrade " CLASS " encoding version") \
+ *(IOF) |= H5O_DECODEIO_DIRTY; \
+ } /* end if */
+#endif /* H5_STRICT_FORMAT_CHECKS */
+
/* This message derives from H5O message class */
const H5O_msg_class_t H5O_MSG_DTYPE[1] = {{
H5O_DTYPE_ID, /* message id number */
@@ -103,7 +123,7 @@ const H5O_msg_class_t H5O_MSG_DTYPE[1] = {{
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt)
+H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **pp, H5T_t *dt)
{
unsigned flags, version;
unsigned i;
@@ -232,10 +252,12 @@ H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt)
case H5T_COMPOUND:
{
unsigned offset_nbytes; /* Size needed to encode member offsets */
+ size_t max_memb_pos = 0; /* Maximum member covered, so far */
+ unsigned max_version = 0; /* Maximum member version */
unsigned j;
/* Compute the # of bytes required to store a member offset */
- offset_nbytes = (H5V_log2_gen((uint64_t)dt->shared->size) + 7) / 8;
+ offset_nbytes = H5V_limit_enc_size((uint64_t)dt->shared->size);
/*
* Compound datatypes...
@@ -296,13 +318,17 @@ H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Decode the field's datatype information */
- if(H5O_dtype_decode_helper(f, pp, temp_type) < 0) {
+ if(H5O_dtype_decode_helper(f, ioflags, pp, temp_type) < 0) {
for(j = 0; j <= i; j++)
H5MM_xfree(dt->shared->u.compnd.memb[j].name);
H5MM_xfree(dt->shared->u.compnd.memb);
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "unable to decode member type")
} /* end if */
+ /* Keep track of the maximum member version found */
+ if(temp_type->shared->version > max_version)
+ max_version = temp_type->shared->version;
+
/* Go create the array datatype now, for older versions of the datatype message */
if(version == H5O_DTYPE_VERSION_1) {
/* Check if this member is an array field */
@@ -336,6 +362,18 @@ H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt)
/* Set the field datatype (finally :-) */
dt->shared->u.compnd.memb[i].type = temp_type;
+ /* Check if this field overlaps with a prior field */
+ /* (probably indicates that the file is corrupt) */
+ if(i > 0 && dt->shared->u.compnd.memb[i].offset < max_memb_pos) {
+ for(j = 0; j < i; j++)
+ if(dt->shared->u.compnd.memb[i].offset >= dt->shared->u.compnd.memb[j].offset
+ && dt->shared->u.compnd.memb[i].offset < (dt->shared->u.compnd.memb[j].offset + dt->shared->u.compnd.memb[j].size))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "member overlaps with previous member")
+ } /* end if */
+
+ /* Update the maximum member position covered */
+ max_memb_pos = MAX(max_memb_pos, (dt->shared->u.compnd.memb[i].offset + dt->shared->u.compnd.memb[i].size));
+
/* Check if the datatype stayed packed */
if(dt->shared->u.compnd.packed) {
/* Check if the member type is packed */
@@ -359,6 +397,9 @@ H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt)
dt->shared->u.compnd.packed = FALSE;
} /* end if */
} /* end for */
+ /* Check that no member of this compound has a version greater
+ * than the compound itself. */
+ H5O_DTYPE_CHECK_VERSION(dt, version, max_version, ioflags, "compound", FAIL)
}
break;
@@ -389,8 +430,14 @@ H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt)
dt->shared->u.enumer.nmembs = dt->shared->u.enumer.nalloc = flags & 0xffff;
if(NULL == (dt->shared->parent = H5T_alloc()))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
- if(H5O_dtype_decode_helper(f, pp, dt->shared->parent) < 0)
+ if(H5O_dtype_decode_helper(f, ioflags, pp, dt->shared->parent) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "unable to decode parent datatype")
+
+ /* Check if the parent of this enum has a version greater than the
+ * enum itself. */
+ H5O_DTYPE_CHECK_VERSION(dt, version, dt->shared->parent->shared->version,
+ ioflags, "enum", FAIL)
+
if(NULL == (dt->shared->u.enumer.name = (char **)H5MM_calloc(dt->shared->u.enumer.nalloc * sizeof(char*))) ||
NULL == (dt->shared->u.enumer.value = (uint8_t *)H5MM_calloc(dt->shared->u.enumer.nalloc * dt->shared->parent->shared->size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
@@ -425,9 +472,14 @@ H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt)
/* Decode base type of VL information */
if(NULL == (dt->shared->parent = H5T_alloc()))
HGOTO_ERROR(H5E_DATATYPE, H5E_NOSPACE, FAIL, "memory allocation failed")
- if(H5O_dtype_decode_helper(f, pp, dt->shared->parent) < 0)
+ if(H5O_dtype_decode_helper(f, ioflags, pp, dt->shared->parent) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "unable to decode VL parent type")
+ /* Check if the parent of this vlen has a version greater than the
+ * vlen itself. */
+ H5O_DTYPE_CHECK_VERSION(dt, version, dt->shared->parent->shared->version,
+ ioflags, "vlen", FAIL)
+
dt->shared->force_conv=TRUE;
/* Mark this type as on disk */
if(H5T_set_loc(dt, f, H5T_LOC_DISK) < 0)
@@ -458,8 +510,17 @@ H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt)
/* Decode base type of array */
if(NULL == (dt->shared->parent = H5T_alloc()))
HGOTO_ERROR(H5E_DATATYPE, H5E_NOSPACE, FAIL, "memory allocation failed")
- if(H5O_dtype_decode_helper(f, pp, dt->shared->parent) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "unable to decode VL parent type")
+ if(H5O_dtype_decode_helper(f, ioflags, pp, dt->shared->parent) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "unable to decode array parent type")
+
+ /* Check if the parent of this array has a version greater than the
+ * array itself. */
+ H5O_DTYPE_CHECK_VERSION(dt, version, dt->shared->parent->shared->version,
+ ioflags, "array", FAIL)
+
+ /* There should be no array datatypes with version < 2. */
+ H5O_DTYPE_CHECK_VERSION(dt, version, H5O_DTYPE_VERSION_2, ioflags,
+ "array", FAIL)
/*
* Set the "force conversion" flag if a VL base datatype is used or
@@ -734,7 +795,7 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt)
unsigned offset_nbytes; /* Size needed to encode member offsets */
/* Compute the # of bytes required to store a member offset */
- offset_nbytes = (H5V_log2_gen((uint64_t)dt->shared->size) + 7) / 8;
+ offset_nbytes = H5V_limit_enc_size((uint64_t)dt->shared->size);
/*
* Compound datatypes...
@@ -745,6 +806,9 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt)
/* (compound datatypes w/array members must be encoded w/version >= 2) */
HDassert(dt->shared->u.compnd.memb[i].type->shared->type != H5T_ARRAY || dt->shared->version >= H5O_DTYPE_VERSION_2);
+ /* Check that the version is at least as great as the member */
+ HDassert(dt->shared->version >= dt->shared->u.compnd.memb[i].type->shared->version);
+
/* Name */
HDstrcpy((char*)(*pp), dt->shared->u.compnd.memb[i].name);
@@ -804,6 +868,9 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt)
break;
case H5T_ENUM:
+ /* Check that the version is at least as great as the parent */
+ HDassert(dt->shared->version >= dt->shared->parent->shared->version);
+
/*
* Enumeration datatypes...
*/
@@ -836,6 +903,9 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt)
break;
case H5T_VLEN: /* Variable length datatypes... */
+ /* Check that the version is at least as great as the parent */
+ HDassert(dt->shared->version >= dt->shared->parent->shared->version);
+
flags |= (dt->shared->u.vlen.type & 0x0f);
if(dt->shared->u.vlen.type == H5T_VLEN_STRING) {
flags |= (dt->shared->u.vlen.pad & 0x0f) << 4;
@@ -851,6 +921,12 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt)
/* Double-check the number of dimensions */
HDassert(dt->shared->u.array.ndims <= H5S_MAX_RANK);
+ /* Check that the version is valid */
+ HDassert(dt->shared->version >= H5O_DTYPE_VERSION_2);
+
+ /* Check that the version is at least as great as the parent */
+ HDassert(dt->shared->version >= dt->shared->parent->shared->version);
+
/* Encode the number of dimensions */
*(*pp)++ = dt->shared->u.array.ndims;
@@ -914,7 +990,8 @@ done:
function using malloc() and is returned to the caller.
--------------------------------------------------------------------------*/
static void *
-H5O_dtype_decode(H5F_t *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags, const uint8_t *p)
+H5O_dtype_decode(H5F_t *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
+ unsigned *ioflags/*in,out*/, const uint8_t *p)
{
H5T_t *dt = NULL;
void *ret_value; /* Return value */
@@ -929,21 +1006,13 @@ H5O_dtype_decode(H5F_t *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags, con
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Perform actual decode of message */
- if(H5O_dtype_decode_helper(f, &p, dt) < 0)
+ if(H5O_dtype_decode_helper(f, ioflags, &p, dt) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, NULL, "can't decode type")
/* Set return value */
ret_value = dt;
done:
- if(ret_value == NULL) {
- if(dt != NULL) {
- if(dt->shared != NULL)
- H5FL_FREE(H5T_shared_t, dt->shared);
- H5FL_FREE(H5T_t, dt);
- } /* end if */
- } /* end if */
-
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_dtype_decode() */
@@ -1023,7 +1092,7 @@ H5O_dtype_copy(const void *_src, void *_dst)
/* Was result already allocated? */
if(_dst) {
*((H5T_t *) _dst) = *dst;
- H5FL_FREE(H5T_t, dst);
+ (void)H5FL_FREE(H5T_t, dst);
dst = (H5T_t *) _dst;
} /* end if */
@@ -1050,9 +1119,6 @@ done:
This function returns the size of the raw simple datatype message on
success. (Not counting the message type or size fields, only the data
portion of the message). It doesn't take into account alignment.
- NOTES
- All datatype messages have a common 8 byte header, plus a variable-
- sized "properties" field.
--------------------------------------------------------------------------*/
static size_t
H5O_dtype_size(const H5F_t *f, const void *_mesg)
@@ -1097,7 +1163,7 @@ H5O_dtype_size(const H5F_t *f, const void *_mesg)
unsigned offset_nbytes; /* Size needed to encode member offsets */
/* Compute the # of bytes required to store a member offset */
- offset_nbytes = (H5V_log2_gen((uint64_t)dt->shared->size) + 7) / 8;
+ offset_nbytes = H5V_limit_enc_size((uint64_t)dt->shared->size);
/* Compute the total size needed to encode compound datatype */
for(u = 0; u < dt->shared->u.compnd.nmembs; u++) {
@@ -1118,7 +1184,7 @@ H5O_dtype_size(const H5F_t *f, const void *_mesg)
ret_value += offset_nbytes; /*member offset*/
if(dt->shared->version >= H5O_DTYPE_VERSION_2)
ret_value += 4; /*member offset*/
- else
+ else
ret_value += 4 + /*member offset*/
1 + /*dimensionality*/
3 + /*reserved*/
@@ -1220,8 +1286,8 @@ H5O_dtype_free(void *mesg)
HDassert(mesg);
- H5FL_FREE(H5T_shared_t, ((H5T_t *) mesg)->shared);
- H5FL_FREE(H5T_t,mesg);
+ (void)H5FL_FREE(H5T_shared_t, ((H5T_t *) mesg)->shared);
+ (void)H5FL_FREE(H5T_t, mesg);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_dtype_free() */
@@ -1242,8 +1308,8 @@ H5O_dtype_free(void *mesg)
static herr_t
H5O_dtype_set_share(void *_mesg/*in,out*/, const H5O_shared_t *sh)
{
- H5T_t *dt = (H5T_t *)_mesg;
- herr_t ret_value = SUCCEED;
+ H5T_t *dt = (H5T_t *)_mesg;
+ herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT(H5O_dtype_set_share)
@@ -1282,7 +1348,7 @@ done:
* Function: H5O_dtype_can_share
*
* Purpose: Determines if this datatype is allowed to be shared or
- * not. Immutable datatypes or datatypes that are already
+ * not. Immutable datatypes or datatypes that are already
* shared cannot be shared (again).
*
* Return: TRUE if datatype can be shared
@@ -1342,9 +1408,9 @@ H5O_dtype_pre_copy_file(H5F_t *file_src, const void *mesg_src,
hbool_t UNUSED *deleted, const H5O_copy_t UNUSED *cpy_info,
void *_udata)
{
- const H5T_t *dt_src = (const H5T_t *)mesg_src; /* Source datatype */
+ const H5T_t *dt_src = (const H5T_t *)mesg_src; /* Source datatype */
H5D_copy_file_ud_t *udata = (H5D_copy_file_ud_t *)_udata; /* Dataset copying user data */
- herr_t ret_value = SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_dtype_pre_copy_file)
@@ -1376,12 +1442,12 @@ done:
/*-------------------------------------------------------------------------
* Function: H5O_dtype_copy_file
- *
+ *
* Purpose: Copy a native datatype message from one file to another.
*
* Return: Success: Native copy of message
* Failure: NULL
- *
+ *
* Programmer: James Laird
* December 12, 2006
*
@@ -1392,8 +1458,8 @@ H5O_dtype_copy_file(H5F_t UNUSED *file_src, const H5O_msg_class_t *mesg_type,
void *native_src, H5F_t *file_dst, hbool_t UNUSED *recompute_size,
H5O_copy_t UNUSED *cpy_info, void UNUSED *udata, hid_t UNUSED dxpl_id)
{
- H5T_t *dst_mesg = NULL; /* Destination datatype */
- void *ret_value = NULL; /* Return value */
+ H5T_t *dst_mesg; /* Destination datatype */
+ void *ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_dtype_copy_file)
@@ -1510,6 +1576,9 @@ H5O_dtype_debug(H5F_t *f, hid_t dxpl_id, const void *mesg, FILE *stream,
"Size:",
(unsigned long)(dt->shared->size), 1 == dt->shared->size ? "" : "s");
+ fprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
+ "Version:", dt->shared->version);
+
if (H5T_COMPOUND == dt->shared->type) {
fprintf(stream, "%*s%-*s %d\n", indent, "", fwidth,
"Number of members:",
diff --git a/src/H5Oefl.c b/src/H5Oefl.c
index 5fa9d6a..ee51e1c 100644
--- a/src/H5Oefl.c
+++ b/src/H5Oefl.c
@@ -29,7 +29,8 @@
#include "H5Opkg.h" /* Object headers */
/* PRIVATE PROTOTYPES */
-static void *H5O_efl_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags, const uint8_t *p);
+static void *H5O_efl_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags,
+ unsigned *ioflags, const uint8_t *p);
static herr_t H5O_efl_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
static void *H5O_efl_copy(const void *_mesg, void *_dest);
static size_t H5O_efl_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
@@ -84,7 +85,7 @@ const H5O_msg_class_t H5O_MSG_EFL[1] = {{
*/
static void *
H5O_efl_decode(H5F_t *f, hid_t dxpl_id, unsigned UNUSED mesg_flags,
- const uint8_t *p)
+ unsigned UNUSED *ioflags, const uint8_t *p)
{
H5O_efl_t *mesg = NULL;
int version;
@@ -99,7 +100,7 @@ H5O_efl_decode(H5F_t *f, hid_t dxpl_id, unsigned UNUSED mesg_flags,
HDassert(f);
HDassert(p);
- if(NULL == (mesg = H5MM_calloc(sizeof(H5O_efl_t))))
+ if(NULL == (mesg = (H5O_efl_t *)H5MM_calloc(sizeof(H5O_efl_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Version */
@@ -125,7 +126,7 @@ H5O_efl_decode(H5F_t *f, hid_t dxpl_id, unsigned UNUSED mesg_flags,
if(NULL == (heap = H5HL_protect(f, dxpl_id, mesg->heap_addr, H5AC_READ)))
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, NULL, "unable to read protect link value")
- s = H5HL_offset_into(f, heap, 0);
+ s = (const char *)H5HL_offset_into(f, heap, 0);
HDassert(s && !*s);
@@ -135,7 +136,7 @@ H5O_efl_decode(H5F_t *f, hid_t dxpl_id, unsigned UNUSED mesg_flags,
#endif
/* Decode the file list */
- mesg->slot = H5MM_calloc(mesg->nalloc * sizeof(H5O_efl_entry_t));
+ mesg->slot = (H5O_efl_entry_t *)H5MM_calloc(mesg->nalloc * sizeof(H5O_efl_entry_t));
if(NULL == mesg->slot)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
@@ -145,7 +146,7 @@ H5O_efl_decode(H5F_t *f, hid_t dxpl_id, unsigned UNUSED mesg_flags,
/* Name */
H5F_DECODE_LENGTH (f, p, mesg->slot[u].name_offset);
- s = H5HL_offset_into(f, heap, mesg->slot[u].name_offset);
+ s = (const char *)H5HL_offset_into(f, heap, mesg->slot[u].name_offset);
HDassert(s && *s);
mesg->slot[u].name = H5MM_xstrdup (s);
HDassert(mesg->slot[u].name);
@@ -261,12 +262,12 @@ H5O_efl_copy(const void *_mesg, void *_dest)
/* check args */
HDassert(mesg);
if(!dest) {
- if(NULL == (dest = H5MM_calloc(sizeof(H5O_efl_t))) ||
- NULL == (dest->slot = H5MM_malloc(mesg->nalloc * sizeof(H5O_efl_entry_t))))
+ if(NULL == (dest = (H5O_efl_t *)H5MM_calloc(sizeof(H5O_efl_t))) ||
+ NULL == (dest->slot = (H5O_efl_entry_t *)H5MM_malloc(mesg->nalloc * sizeof(H5O_efl_entry_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
} else if(dest->nalloc < mesg->nalloc) {
H5MM_xfree(dest->slot);
- if(NULL == (dest->slot = H5MM_malloc(mesg->nalloc * sizeof(H5O_efl_entry_t))))
+ if(NULL == (dest->slot = (H5O_efl_entry_t *)H5MM_malloc(mesg->nalloc * sizeof(H5O_efl_entry_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
}
dest->heap_addr = mesg->heap_addr;
@@ -353,11 +354,11 @@ H5O_efl_reset(void *_mesg)
/* reset */
for(u = 0; u < mesg->nused; u++)
- mesg->slot[u].name = H5MM_xfree(mesg->slot[u].name);
+ mesg->slot[u].name = (char *)H5MM_xfree(mesg->slot[u].name);
mesg->heap_addr = HADDR_UNDEF;
mesg->nused = mesg->nalloc = 0;
if(mesg->slot)
- mesg->slot = H5MM_xfree(mesg->slot);
+ mesg->slot = (H5O_efl_entry_t *)H5MM_xfree(mesg->slot);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_efl_reset() */
@@ -434,7 +435,7 @@ H5O_efl_copy_file(H5F_t UNUSED *file_src, void *mesg_src, H5F_t *file_dst,
HDassert(file_dst);
/* Allocate space for the destination efl */
- if(NULL == (efl_dst = H5MM_calloc(sizeof(H5O_efl_t))))
+ if(NULL == (efl_dst = (H5O_efl_t *)H5MM_calloc(sizeof(H5O_efl_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Copy the "top level" information */
@@ -461,7 +462,7 @@ H5O_efl_copy_file(H5F_t UNUSED *file_src, void *mesg_src, H5F_t *file_dst,
/* allocate array of external file entries */
if(efl_src->nalloc > 0) {
size = efl_src->nalloc * sizeof(H5O_efl_entry_t);
- if((efl_dst->slot = H5MM_calloc(size)) == NULL)
+ if((efl_dst->slot = (H5O_efl_entry_t *)H5MM_calloc(size)) == NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* copy content from the source. Need to update later */
diff --git a/src/H5Ofill.c b/src/H5Ofill.c
index 1335274..43ec1a4 100644
--- a/src/H5Ofill.c
+++ b/src/H5Ofill.c
@@ -33,10 +33,12 @@
#include "H5Sprivate.h" /* Dataspaces */
-static void *H5O_fill_old_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags, const uint8_t *p);
+static void *H5O_fill_old_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags,
+ unsigned *ioflags, const uint8_t *p);
static herr_t H5O_fill_old_encode(H5F_t *f, uint8_t *p, const void *_mesg);
static size_t H5O_fill_old_size(const H5F_t *f, const void *_mesg);
-static void *H5O_fill_new_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags, const uint8_t *p);
+static void *H5O_fill_new_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags,
+ unsigned *ioflags, const uint8_t *p);
static herr_t H5O_fill_new_encode(H5F_t *f, uint8_t *p, const void *_mesg);
static size_t H5O_fill_new_size(const H5F_t *f, const void *_mesg);
static void *H5O_fill_copy(const void *_mesg, void *_dest);
@@ -181,7 +183,7 @@ H5FL_BLK_EXTERN(type_conv);
*/
static void *
H5O_fill_new_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
- const uint8_t *p)
+ unsigned UNUSED *ioflags, const uint8_t *p)
{
H5O_fill_t *fill = NULL;
void *ret_value;
@@ -273,7 +275,7 @@ done:
if(!ret_value && fill) {
if(fill->buf)
H5MM_xfree(fill->buf);
- H5FL_FREE(H5O_fill_t, fill);
+ (void)H5FL_FREE(H5O_fill_t, fill);
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
@@ -295,7 +297,7 @@ done:
*/
static void *
H5O_fill_old_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
- const uint8_t *p)
+ unsigned UNUSED *ioflags, const uint8_t *p)
{
H5O_fill_t *fill = NULL; /* Decoded fill value message */
void *ret_value; /* Return value */
@@ -333,7 +335,7 @@ done:
if(!ret_value && fill) {
if(fill->buf)
H5MM_xfree(fill->buf);
- H5FL_FREE(H5O_fill_t, fill);
+ (void)H5FL_FREE(H5O_fill_t, fill);
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
@@ -505,7 +507,7 @@ H5O_fill_copy(const void *_src, void *_dst)
/* Copy data type of fill value */
if(src->type) {
if(NULL == (dst->type = H5T_copy(src->type, H5T_COPY_TRANSIENT)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy fill value data type")
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "can't copy datatype")
} /* end if */
else
dst->type = NULL;
@@ -532,37 +534,37 @@ H5O_fill_copy(const void *_src, void *_dst)
size_t bkg_size; /* Size of background buffer */
/* Wrap copies of types to convert */
- dst_id = H5I_register(H5I_DATATYPE, H5T_copy(dst->type, H5T_COPY_TRANSIENT));
+ dst_id = H5I_register(H5I_DATATYPE, H5T_copy(dst->type, H5T_COPY_TRANSIENT), FALSE);
if(dst_id < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy/register datatype")
- src_id = H5I_register(H5I_DATATYPE, H5T_copy(src->type, H5T_COPY_ALL));
+ src_id = H5I_register(H5I_DATATYPE, H5T_copy(src->type, H5T_COPY_ALL), FALSE);
if(src_id < 0) {
- H5I_dec_ref(dst_id);
+ H5I_dec_ref(dst_id, FALSE);
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy/register datatype")
} /* end if */
/* Allocate a background buffer */
bkg_size = MAX(H5T_get_size(dst->type), H5T_get_size(src->type));
if(H5T_path_bkg(tpath) && NULL == (bkg_buf = H5FL_BLK_CALLOC(type_conv, bkg_size))) {
- H5I_dec_ref(src_id);
- H5I_dec_ref(dst_id);
+ H5I_dec_ref(src_id, FALSE);
+ H5I_dec_ref(dst_id, FALSE);
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
} /* end if */
/* Convert fill value */
if(H5T_convert(tpath, src_id, dst_id, (size_t)1, (size_t)0, (size_t)0, dst->buf, bkg_buf, H5AC_ind_dxpl_id) < 0) {
- H5I_dec_ref(src_id);
- H5I_dec_ref(dst_id);
+ H5I_dec_ref(src_id, FALSE);
+ H5I_dec_ref(dst_id, FALSE);
if(bkg_buf)
- H5FL_BLK_FREE(type_conv, bkg_buf);
+ (void)H5FL_BLK_FREE(type_conv, bkg_buf);
HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, NULL, "datatype conversion failed")
} /* end if */
/* Release the background buffer */
- H5I_dec_ref(src_id);
- H5I_dec_ref(dst_id);
+ H5I_dec_ref(src_id, FALSE);
+ H5I_dec_ref(dst_id, FALSE);
if(bkg_buf)
- H5FL_BLK_FREE(type_conv, bkg_buf);
+ (void)H5FL_BLK_FREE(type_conv, bkg_buf);
} /* end if */
} /* end if */
} /* end if */
@@ -579,7 +581,7 @@ done:
if(dst->type)
H5T_close(dst->type);
if(!_dst)
- H5FL_FREE(H5O_fill_t, dst);
+ (void)H5FL_FREE(H5O_fill_t, dst);
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
@@ -694,7 +696,7 @@ H5O_fill_reset_dyn(H5O_fill_t *fill)
/* Copy the fill value datatype and get an ID for it */
if(NULL == (fill_type = H5T_copy(fill->type, H5T_COPY_TRANSIENT)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy fill value datatype")
- if((fill_type_id = H5I_register(H5I_DATATYPE, fill_type)) < 0) {
+ if((fill_type_id = H5I_register(H5I_DATATYPE, fill_type, FALSE)) < 0) {
H5T_close(fill_type);
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register fill value datatype")
} /* end if */
@@ -724,7 +726,7 @@ H5O_fill_reset_dyn(H5O_fill_t *fill)
done:
if(fill_type_id > 0)
- H5I_dec_ref(fill_type_id);
+ H5I_dec_ref(fill_type_id, FALSE);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_fill_reset_dyn() */
@@ -781,7 +783,7 @@ H5O_fill_free(void *fill)
HDassert(fill);
- H5FL_FREE(H5O_fill_t, fill);
+ (void)H5FL_FREE(H5O_fill_t, fill);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_fill_free() */
@@ -936,8 +938,8 @@ H5O_fill_convert(H5O_fill_t *fill, H5T_t *dset_type, hbool_t *fill_changed, hid_
/* Don't bother doing anything if there will be no actual conversion */
if(!H5T_path_noop(tpath)) {
- if((src_id = H5I_register(H5I_DATATYPE, H5T_copy(fill->type, H5T_COPY_ALL))) < 0 ||
- (dst_id = H5I_register(H5I_DATATYPE, H5T_copy(dset_type, H5T_COPY_ALL))) < 0)
+ if((src_id = H5I_register(H5I_DATATYPE, H5T_copy(fill->type, H5T_COPY_ALL), FALSE)) < 0 ||
+ (dst_id = H5I_register(H5I_DATATYPE, H5T_copy(dset_type, H5T_COPY_ALL), FALSE)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy/register data type")
/*
@@ -976,9 +978,9 @@ H5O_fill_convert(H5O_fill_t *fill, H5T_t *dset_type, hbool_t *fill_changed, hid_
done:
if(src_id >= 0)
- H5I_dec_ref(src_id);
+ H5I_dec_ref(src_id, FALSE);
if(dst_id >= 0)
- H5I_dec_ref(dst_id);
+ H5I_dec_ref(dst_id, FALSE);
if(buf != fill->buf)
H5MM_xfree(buf);
if(bkg)
diff --git a/src/H5Oginfo.c b/src/H5Oginfo.c
index 5888f58..2323fff 100644
--- a/src/H5Oginfo.c
+++ b/src/H5Oginfo.c
@@ -33,7 +33,8 @@
/* PRIVATE PROTOTYPES */
-static void *H5O_ginfo_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags, const uint8_t *p);
+static void *H5O_ginfo_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags,
+ unsigned *ioflags, const uint8_t *p);
static herr_t H5O_ginfo_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
static void *H5O_ginfo_copy(const void *_mesg, void *_dest);
static size_t H5O_ginfo_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
@@ -95,7 +96,7 @@ H5FL_DEFINE_STATIC(H5O_ginfo_t);
*/
static void *
H5O_ginfo_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
- const uint8_t *p)
+ unsigned UNUSED *ioflags, const uint8_t *p)
{
H5O_ginfo_t *ginfo = NULL; /* Pointer to group information message */
unsigned char flags; /* Flags for encoding group info */
@@ -147,7 +148,7 @@ H5O_ginfo_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_fla
done:
if(ret_value == NULL)
if(ginfo != NULL)
- H5FL_FREE(H5O_ginfo_t, ginfo);
+ (void)H5FL_FREE(H5O_ginfo_t, ginfo);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_ginfo_decode() */
@@ -303,7 +304,7 @@ H5O_ginfo_free(void *mesg)
HDassert(mesg);
- H5FL_FREE(H5O_ginfo_t, mesg);
+ (void)H5FL_FREE(H5O_ginfo_t, mesg);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_ginfo_free() */
diff --git a/src/H5Olayout.c b/src/H5Olayout.c
index e750d48..f2b6b30 100644
--- a/src/H5Olayout.c
+++ b/src/H5Olayout.c
@@ -33,7 +33,8 @@
/* PRIVATE PROTOTYPES */
-static void *H5O_layout_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags, const uint8_t *p);
+static void *H5O_layout_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags,
+ unsigned *ioflags, const uint8_t *p);
static herr_t H5O_layout_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
static void *H5O_layout_copy(const void *_mesg, void *_dest);
static size_t H5O_layout_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
@@ -99,7 +100,7 @@ H5FL_DEFINE(H5O_layout_t);
*/
static void *
H5O_layout_decode(H5F_t *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
- const uint8_t *p)
+ unsigned UNUSED *ioflags, const uint8_t *p)
{
H5O_layout_t *mesg = NULL;
unsigned u;
@@ -136,11 +137,30 @@ H5O_layout_decode(H5F_t *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
p += 5;
/* Address */
- if(mesg->type == H5D_CONTIGUOUS)
+ if(mesg->type == H5D_CONTIGUOUS) {
H5F_addr_decode(f, &p, &(mesg->u.contig.addr));
- else if(mesg->type == H5D_CHUNKED)
+
+ /* Set the layout operations */
+ mesg->ops = H5D_LOPS_CONTIG;
+ } /* end if */
+ else if(mesg->type == H5D_CHUNKED) {
H5F_addr_decode(f, &p, &(mesg->u.chunk.addr));
+ /* Set the layout operations */
+ mesg->ops = H5D_LOPS_CHUNK;
+
+ /* Set the chunk operations */
+ /* (Only "btree" indexing type currently supported */
+ mesg->u.chunk.ops = H5D_COPS_BTREE;
+ } /* end if */
+ else {
+ /* Sanity check */
+ HDassert(mesg->type == H5D_COMPACT);
+
+ /* Set the layout operations */
+ mesg->ops = H5D_LOPS_COMPACT;
+ } /* end else */
+
/* Read the size */
if(mesg->type != H5D_CHUNKED) {
/* Don't compute size of contiguous storage here, due to possible
@@ -185,11 +205,17 @@ H5O_layout_decode(H5F_t *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
HDmemcpy(mesg->u.compact.buf, p, mesg->u.compact.size);
p += mesg->u.compact.size;
} /* end if */
+
+ /* Set the layout operations */
+ mesg->ops = H5D_LOPS_COMPACT;
break;
case H5D_CONTIGUOUS:
H5F_addr_decode(f, &p, &(mesg->u.contig.addr));
H5F_DECODE_LENGTH(f, p, mesg->u.contig.size);
+
+ /* Set the layout operations */
+ mesg->ops = H5D_LOPS_CONTIG;
break;
case H5D_CHUNKED:
@@ -208,6 +234,13 @@ H5O_layout_decode(H5F_t *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
/* Compute chunk size */
for(u = 1, mesg->u.chunk.size = mesg->u.chunk.dim[0]; u < mesg->u.chunk.ndims; u++)
mesg->u.chunk.size *= mesg->u.chunk.dim[u];
+
+ /* Set the layout operations */
+ mesg->ops = H5D_LOPS_CHUNK;
+
+ /* Set the chunk operations */
+ /* (Only "btree" indexing type currently supported */
+ mesg->u.chunk.ops = H5D_COPS_BTREE;
break;
default:
@@ -221,7 +254,7 @@ H5O_layout_decode(H5F_t *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
done:
if(ret_value == NULL)
if(mesg)
- H5FL_FREE(H5O_layout_t, mesg);
+ (void)H5FL_FREE(H5O_layout_t, mesg);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_layout_decode() */
@@ -519,22 +552,22 @@ H5O_layout_reset (void *_mesg)
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_layout_free (void *_mesg)
+H5O_layout_free(void *_mesg)
{
H5O_layout_t *mesg = (H5O_layout_t *) _mesg;
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_layout_free);
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_layout_free)
- assert (mesg);
+ HDassert(mesg);
/* Free the compact storage buffer */
- if(mesg->type==H5D_COMPACT)
- mesg->u.compact.buf=H5MM_xfree(mesg->u.compact.buf);
+ if(mesg->type == H5D_COMPACT)
+ mesg->u.compact.buf = H5MM_xfree(mesg->u.compact.buf);
- H5FL_FREE(H5O_layout_t,mesg);
+ (void)H5FL_FREE(H5O_layout_t, mesg);
- FUNC_LEAVE_NOAPI(SUCCEED);
-}
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5O_layout_free() */
/*-------------------------------------------------------------------------
@@ -576,8 +609,8 @@ H5O_layout_delete(H5F_t *f, hid_t dxpl_id, H5O_t UNUSED *open_oh, void *_mesg)
break;
case H5D_CHUNKED: /* Chunked blocks on disk */
- /* Free the file space for the raw data */
- if(H5D_istore_delete(f, dxpl_id, mesg) < 0)
+ /* Free the file space for the index & chunk raw data */
+ if(H5D_chunk_delete(f, dxpl_id, mesg) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free raw data")
break;
@@ -670,7 +703,7 @@ H5O_layout_copy_file(H5F_t *file_src, void *mesg_src, H5F_t *file_dst,
layout_dst->u.chunk.addr = HADDR_UNDEF;
/* create chunked layout */
- if(H5D_istore_copy(file_src, layout_src, file_dst, layout_dst, udata->src_dtype, cpy_info, udata->src_pline, dxpl_id) < 0)
+ if(H5D_chunk_copy(file_src, layout_src, file_dst, layout_dst, udata->src_dtype, cpy_info, udata->src_pline, dxpl_id) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTINIT, NULL, "unable to copy chunked storage")
/* Freed by copy routine */
@@ -688,7 +721,7 @@ H5O_layout_copy_file(H5F_t *file_src, void *mesg_src, H5F_t *file_dst,
done:
if(!ret_value)
if(layout_dst)
- H5FL_FREE(H5O_layout_t, layout_dst);
+ (void)H5FL_FREE(H5O_layout_t, layout_dst);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_layout_copy_file() */
@@ -709,8 +742,8 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_layout_debug(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const void *_mesg, FILE * stream,
- int indent, int fwidth)
+H5O_layout_debug(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const void *_mesg,
+ FILE * stream, int indent, int fwidth)
{
const H5O_layout_t *mesg = (const H5O_layout_t *) _mesg;
unsigned u;
@@ -758,5 +791,5 @@ H5O_layout_debug(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const void *_mesg, FILE
} /* end else */
FUNC_LEAVE_NOAPI(SUCCEED);
-}
+} /* end H5O_layout_debug() */
diff --git a/src/H5Olinfo.c b/src/H5Olinfo.c
index 660b0e1..d1eb2c0 100644
--- a/src/H5Olinfo.c
+++ b/src/H5Olinfo.c
@@ -35,7 +35,8 @@
/* PRIVATE PROTOTYPES */
-static void *H5O_linfo_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags, const uint8_t *p);
+static void *H5O_linfo_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags,
+ unsigned *ioflags, const uint8_t *p);
static herr_t H5O_linfo_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
static void *H5O_linfo_copy(const void *_mesg, void *_dest);
static size_t H5O_linfo_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
@@ -111,7 +112,7 @@ H5FL_DEFINE_STATIC(H5O_linfo_t);
*/
static void *
H5O_linfo_decode(H5F_t *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
- const uint8_t *p)
+ unsigned UNUSED *ioflags, const uint8_t *p)
{
H5O_linfo_t *linfo = NULL; /* Link info */
unsigned char index_flags; /* Flags for encoding link index info */
@@ -165,7 +166,7 @@ H5O_linfo_decode(H5F_t *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
done:
if(ret_value == NULL)
if(linfo != NULL)
- H5FL_FREE(H5O_linfo_t, linfo);
+ (void)H5FL_FREE(H5O_linfo_t, linfo);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_linfo_decode() */
@@ -320,7 +321,7 @@ H5O_linfo_free(void *mesg)
HDassert(mesg);
- H5FL_FREE(H5O_linfo_t, mesg);
+ (void)H5FL_FREE(H5O_linfo_t, mesg);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_linfo_free() */
@@ -390,7 +391,7 @@ H5O_linfo_copy_file(H5F_t UNUSED *file_src, void *native_src, H5F_t *file_dst,
HDassert(cpy_info);
/* Copy the source message */
- if(NULL == (linfo_dst = H5O_linfo_copy(linfo_src, NULL)))
+ if(NULL == (linfo_dst = (H5O_linfo_t *)H5O_linfo_copy(linfo_src, NULL)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "memory allocation failed")
/* If we are performing a 'shallow hierarchy' copy, and the links in this
@@ -421,7 +422,7 @@ H5O_linfo_copy_file(H5F_t UNUSED *file_src, void *native_src, H5F_t *file_dst,
done:
if(!ret_value)
if(linfo_dst)
- H5FL_FREE(H5O_linfo_t, linfo_dst);
+ (void)H5FL_FREE(H5O_linfo_t, linfo_dst);
FUNC_LEAVE_NOAPI(ret_value)
} /* H5O_linfo_copy_file() */
@@ -513,7 +514,6 @@ H5O_linfo_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src,
/* Check for copying dense link storage */
if(H5F_addr_defined(linfo_src->fheap_addr)) {
H5O_linfo_postcopy_ud_t udata; /* User data for iteration callback */
- H5G_link_iterate_t lnk_op; /* Link operator */
/* Set up dense link iteration user data */
udata.src_oloc = src_oloc;
@@ -522,12 +522,8 @@ H5O_linfo_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src,
udata.dxpl_id = dxpl_id;
udata.cpy_info = cpy_info;
- /* Build iterator operator */
- lnk_op.op_type = H5G_LINK_OP_LIB;
- lnk_op.u.lib_op = H5O_linfo_post_copy_file_cb;
-
/* Iterate over the links in the group, building a table of the link messages */
- if(H5G_dense_iterate(src_oloc->file, dxpl_id, linfo_src, H5_INDEX_NAME, H5_ITER_NATIVE, (hsize_t)0, NULL, (hid_t)0, &lnk_op, &udata) < 0)
+ if(H5G_dense_iterate(src_oloc->file, dxpl_id, linfo_src, H5_INDEX_NAME, H5_ITER_NATIVE, (hsize_t)0, NULL, H5O_linfo_post_copy_file_cb, &udata) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTNEXT, FAIL, "error iterating over links")
} /* end if */
diff --git a/src/H5Olink.c b/src/H5Olink.c
index 175c937..39cbfc6 100644
--- a/src/H5Olink.c
+++ b/src/H5Olink.c
@@ -38,7 +38,8 @@
/* PRIVATE PROTOTYPES */
-static void *H5O_link_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags, const uint8_t *p);
+static void *H5O_link_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags,
+ unsigned *ioflags, const uint8_t *p);
static herr_t H5O_link_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
static void *H5O_link_copy(const void *_mesg, void *_dest);
static size_t H5O_link_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
@@ -116,7 +117,7 @@ H5FL_DEFINE_STATIC(H5O_link_t);
*/
static void *
H5O_link_decode(H5F_t *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
- const uint8_t *p)
+ unsigned UNUSED *ioflags, const uint8_t *p)
{
H5O_link_t *lnk = NULL; /* Pointer to link message */
size_t len = 0; /* Length of a string in the message */
@@ -197,7 +198,7 @@ H5O_link_decode(H5F_t *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "invalid name length")
/* Get the link's name */
- if(NULL == (lnk->name = H5MM_malloc(len + 1)))
+ if(NULL == (lnk->name = (char *)H5MM_malloc(len + 1)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
HDmemcpy(lnk->name, p, len);
lnk->name[len] = '\0';
@@ -215,7 +216,7 @@ H5O_link_decode(H5F_t *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
UINT16DECODE(p, len)
if(len == 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "invalid link length")
- if(NULL == (lnk->u.soft.name = H5MM_malloc((size_t)len + 1)))
+ if(NULL == (lnk->u.soft.name = (char *)H5MM_malloc((size_t)len + 1)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
HDmemcpy(lnk->u.soft.name, p, len);
lnk->u.soft.name[len] = '\0';
@@ -253,7 +254,7 @@ done:
H5MM_xfree(lnk->u.soft.name);
if(lnk->type >= H5L_TYPE_UD_MIN && lnk->u.ud.size > 0 && lnk->u.ud.udata != NULL)
H5MM_xfree(lnk->u.ud.udata);
- H5FL_FREE(H5O_link_t, lnk);
+ (void)H5FL_FREE(H5O_link_t, lnk);
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
@@ -534,12 +535,12 @@ H5O_link_reset(void *_mesg)
if(lnk) {
/* Free information for link (but don't free link pointer) */
if(lnk->type == H5L_TYPE_SOFT)
- lnk->u.soft.name = H5MM_xfree(lnk->u.soft.name);
+ lnk->u.soft.name = (char *)H5MM_xfree(lnk->u.soft.name);
else if (lnk->type >= H5L_TYPE_UD_MIN) {
if(lnk->u.ud.size > 0)
lnk->u.ud.udata = H5MM_xfree(lnk->u.ud.udata);
} /* end if */
- lnk->name = H5MM_xfree(lnk->name);
+ lnk->name = (char *)H5MM_xfree(lnk->name);
} /* end if */
FUNC_LEAVE_NOAPI(SUCCEED)
@@ -569,7 +570,7 @@ H5O_link_free(void *_mesg)
/* Free information for link */
H5O_link_reset(lnk);
- H5FL_FREE(H5O_link_t, lnk);
+ (void)H5FL_FREE(H5O_link_t, lnk);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_link_free() */
@@ -627,17 +628,17 @@ H5O_link_delete(H5F_t *f, hid_t dxpl_id, H5O_t UNUSED *open_oh, void *_mesg)
hid_t file_id; /* ID for the file the link is located in (passed to user callback) */
/* Get a file ID for the file the link is in */
- if((file_id = H5F_get_id(f)) < 0)
+ if((file_id = H5F_get_id(f, FALSE)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to get file ID")
/* Call user-defined link's 'delete' callback */
if((link_class->del_func)(lnk->name, file_id, lnk->u.ud.udata, lnk->u.ud.size) < 0) {
- H5I_dec_ref(file_id);
+ H5I_dec_ref(file_id, FALSE);
HGOTO_ERROR(H5E_OHDR, H5E_CALLBACK, FAIL, "link deletion callback returned failure")
} /* end if */
/* Release the file ID */
- if(H5I_dec_ref(file_id) < 0)
+ if(H5I_dec_ref(file_id, FALSE) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTCLOSEFILE, FAIL, "can't close file")
} /* end if */
} /* end if */
@@ -836,7 +837,7 @@ H5O_link_debug(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const void *_mesg, FILE *
default:
if(lnk->type >= H5L_TYPE_UD_MIN) {
if(lnk->type == H5L_TYPE_EXTERNAL) {
- const char * objname = (const char *)lnk->u.ud.udata + (HDstrlen(lnk->u.ud.udata) + 1);
+ const char *objname = (const char *)lnk->u.ud.udata + (HDstrlen((const char *)lnk->u.ud.udata) + 1);
HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
"External File Name:", lnk->u.ud.udata);
diff --git a/src/H5Omessage.c b/src/H5Omessage.c
index 799f267..1682117 100644
--- a/src/H5Omessage.c
+++ b/src/H5Omessage.c
@@ -74,7 +74,7 @@ typedef struct {
/********************/
static herr_t H5O_msg_reset_real(const H5O_msg_class_t *type, void *native);
-static herr_t H5O_msg_remove_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
+static herr_t H5O_msg_remove_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
unsigned sequence, hbool_t *oh_modified, void *_udata/*in,out*/);
static herr_t H5O_copy_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned idx,
const H5O_msg_class_t *type, const void *mesg, unsigned mesg_flags,
@@ -136,7 +136,7 @@ H5O_msg_create(const H5O_loc_t *loc, unsigned type_id, unsigned mesg_flags,
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
/* Go append message to object header */
- if(H5O_msg_append(loc->file, dxpl_id, oh, type_id, mesg_flags, update_flags, mesg) < 0)
+ if(H5O_msg_append_oh(loc->file, dxpl_id, oh, type_id, mesg_flags, update_flags, mesg) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to append to object header")
done:
@@ -148,7 +148,7 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5O_msg_append
+ * Function: H5O_msg_append_oh
*
* Purpose: Simplified version of H5O_msg_create, used when creating a new
* object header message (usually during object creation) and
@@ -165,13 +165,13 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5O_msg_append(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned type_id,
+H5O_msg_append_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned type_id,
unsigned mesg_flags, unsigned update_flags, void *mesg)
{
const H5O_msg_class_t *type; /* Original H5O class type for the ID */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5O_msg_append, FAIL)
+ FUNC_ENTER_NOAPI(H5O_msg_append_oh, FAIL)
/* check args */
HDassert(f);
@@ -189,7 +189,7 @@ H5O_msg_append(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned type_id,
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5O_msg_append() */
+} /* end H5O_msg_append_oh() */
/*-------------------------------------------------------------------------
@@ -301,6 +301,53 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5O_msg_write_oh
+ *
+ * Purpose: Modifies an existing message or creates a new message.
+ *
+ * The UPDATE_FLAGS argument are flags that allow the caller
+ * to skip updating the modification time or reseting the message
+ * data. This is useful when several calls to H5O_msg_write will be
+ * made in a sequence.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Dec 6 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5O_msg_write_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned type_id,
+ unsigned mesg_flags, unsigned update_flags, void *mesg)
+{
+ const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5O_msg_write_oh, FAIL)
+
+ /* check args */
+ HDassert(f);
+ HDassert(oh);
+ HDassert(H5O_ATTR_ID != type_id); /* Attributes are modified in another routine */
+ 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(0 == (mesg_flags & ~H5O_MSG_FLAG_BITS));
+
+ /* Call the "real" modify routine */
+ if(H5O_msg_write_real(f, dxpl_id, oh, type, mesg_flags, update_flags, mesg) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header message")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_msg_write_oh() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5O_msg_write_real
*
* Purpose: Modifies an existing message or creates a new message.
@@ -437,7 +484,8 @@ H5O_msg_read(const H5O_loc_t *loc, unsigned type_id, void *mesg,
HDassert(type_id < NELMTS(H5O_msg_class_g));
/* Get the object header */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL,
+ (H5F_get_intent(loc->file) & H5F_ACC_RDWR) ? H5AC_WRITE : H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "unable to load object header")
/* Call the "real" read routine */
@@ -503,7 +551,7 @@ H5O_msg_read_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned type_id,
* Decode the message if necessary. If the message is shared then retrieve
* native message through the shared interface.
*/
- H5O_LOAD_NATIVE(f, dxpl_id, oh, &(oh->mesg[idx]), NULL)
+ H5O_LOAD_NATIVE(f, dxpl_id, 0, oh, &(oh->mesg[idx]), NULL)
/*
* The object header caches the native message (along with
@@ -831,7 +879,7 @@ H5O_msg_count_real(const H5O_t *oh, const H5O_msg_class_t *type)
*-------------------------------------------------------------------------
*/
htri_t
-H5O_msg_exists(H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id)
+H5O_msg_exists(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id)
{
H5O_t *oh = NULL; /* Object header for location */
htri_t ret_value; /* Return value */
@@ -1183,7 +1231,8 @@ H5O_msg_iterate(const H5O_loc_t *loc, unsigned type_id,
HDassert(op);
/* Protect the object header to iterate over */
- if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, NULL, NULL,
+ (H5F_get_intent(loc->file) & H5F_ACC_RDWR) ? H5AC_WRITE : H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
/* Call the "real" iterate routine */
@@ -1252,7 +1301,7 @@ H5O_msg_iterate_real(H5F_t *f, H5O_t *oh, const H5O_msg_class_t *type,
for(sequence = 0, idx = 0, idx_msg = &oh->mesg[0]; idx < oh->nmesgs && !ret_value; idx++, idx_msg++) {
if(type == idx_msg->type) {
/* Decode the message if necessary. */
- H5O_LOAD_NATIVE(f, dxpl_id, oh, idx_msg, FAIL)
+ H5O_LOAD_NATIVE(f, dxpl_id, 0, oh, idx_msg, FAIL)
/* Check for making an "internal" (i.e. within the H5O package) callback */
if(op->op_type == H5O_MESG_OP_LIB)
@@ -1374,7 +1423,7 @@ H5O_msg_size_f(const H5F_t *f, hid_t ocpl_id, unsigned type_id,
HDassert(mesg);
/* Get the property list */
- if(NULL == (ocpl = H5I_object(ocpl_id)))
+ if(NULL == (ocpl = (H5P_genplist_t *)H5I_object(ocpl_id)))
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, 0, "not a property list")
/* Get any object header status flags set by properties */
@@ -1606,7 +1655,7 @@ H5O_msg_set_share(unsigned type_id, const H5O_shared_t *share, void *mesg)
HDassert(share);
HDassert(share->type != H5O_SHARE_TYPE_UNSHARED);
- /* If there's a special action for this class that needs to be performed
+ /* If there's a special action for this class that needs to be performed
* when setting the shared component, do that
*/
if(type->set_share) {
@@ -1764,6 +1813,7 @@ H5O_msg_decode(H5F_t *f, hid_t dxpl_id, unsigned type_id, const unsigned char *b
{
const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
void *ret_value; /* Return value */
+ unsigned ioflags = 0; /* Flags for decode routine */
FUNC_ENTER_NOAPI(H5O_msg_decode, NULL)
@@ -1774,7 +1824,7 @@ H5O_msg_decode(H5F_t *f, hid_t dxpl_id, unsigned type_id, const unsigned char *b
HDassert(type);
/* decode */
- if((ret_value = (type->decode)(f, dxpl_id, 0, buf)) == NULL)
+ if((ret_value = (type->decode)(f, dxpl_id, 0, &ioflags, buf)) == NULL)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, NULL, "unable to decode message")
done:
@@ -2029,7 +2079,7 @@ H5O_delete_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5O_mesg_t *mesg)
/* Check if there is a file space deletion callback for this type of message */
if(type->del) {
/* Decode the message if necessary. */
- H5O_LOAD_NATIVE(f, dxpl_id, oh, mesg, FAIL)
+ H5O_LOAD_NATIVE(f, dxpl_id, H5O_DECODEIO_NOCHANGE, oh, mesg, FAIL)
if((type->del)(f, dxpl_id, oh, mesg->native) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete file space for object header message")
diff --git a/src/H5Omtime.c b/src/H5Omtime.c
index 0a70e5b..46272a0 100644
--- a/src/H5Omtime.c
+++ b/src/H5Omtime.c
@@ -27,17 +27,14 @@
#include "H5MMprivate.h" /* Memory management */
#include "H5Opkg.h" /* Object headers */
-#if defined (_WIN32) && !defined (__MWERKS__)
-#include <sys/types.h>
-#include <sys/timeb.h>
-#endif
-
-static void *H5O_mtime_new_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags, const uint8_t *p);
+static void *H5O_mtime_new_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags,
+ unsigned *ioflags, const uint8_t *p);
static herr_t H5O_mtime_new_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
static size_t H5O_mtime_new_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
-static void *H5O_mtime_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags, const uint8_t *p);
+static void *H5O_mtime_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags,
+ unsigned *ioflags, const uint8_t *p);
static herr_t H5O_mtime_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
static void *H5O_mtime_copy(const void *_mesg, void *_dest);
static size_t H5O_mtime_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
@@ -123,7 +120,7 @@ H5FL_DEFINE(time_t);
*/
static void *
H5O_mtime_new_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
- const uint8_t *p)
+ unsigned UNUSED *ioflags, const uint8_t *p)
{
time_t *mesg;
uint32_t tmp_time; /* Temporary copy of the time */
@@ -176,7 +173,7 @@ done:
*/
static void *
H5O_mtime_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
- const uint8_t *p)
+ unsigned UNUSED *ioflags, const uint8_t *p)
{
time_t *mesg, the_time;
int i;
@@ -247,24 +244,7 @@ H5O_mtime_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_fla
the_time -= tz.tz_minuteswest * 60 - (tm.tm_isdst ? 3600 : 0);
}
-#elif defined (_WIN32)
- #if !defined (__MWERKS__) /* MSVC */
- {
- struct timeb timebuffer;
- long tz;
-
- ftime(&timebuffer);
- tz = timebuffer.timezone;
- /* daylight is not handled properly. Currently we just hard-code
- the problem. */
- the_time -= tz * 60 - 3600;
- }
- #else /*__MWERKS__*/
-
- ;
-
- #endif /*__MWERKS__*/
-#else /* _WIN32 */
+#else
/*
* The catch-all. If we can't convert a character string universal
* coordinated time to a time_t value reliably then we can't decode the
@@ -516,16 +496,16 @@ H5O_mtime_reset(void UNUSED *_mesg)
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_mtime_free (void *mesg)
+H5O_mtime_free(void *mesg)
{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_mtime_free);
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_mtime_free)
- assert (mesg);
+ HDassert(mesg);
- H5FL_FREE(time_t,mesg);
+ (void)H5FL_FREE(time_t, mesg);
- FUNC_LEAVE_NOAPI(SUCCEED);
-}
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5O_mtime_free() */
/*-------------------------------------------------------------------------
diff --git a/src/H5Oname.c b/src/H5Oname.c
index 44ab432..915546b 100644
--- a/src/H5Oname.c
+++ b/src/H5Oname.c
@@ -33,7 +33,8 @@
/* PRIVATE PROTOTYPES */
-static void *H5O_name_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags, const uint8_t *p);
+static void *H5O_name_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags,
+ unsigned *ioflags, const uint8_t *p);
static herr_t H5O_name_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
static void *H5O_name_copy(const void *_mesg, void *_dest);
static size_t H5O_name_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
@@ -84,34 +85,34 @@ const H5O_msg_class_t H5O_MSG_NAME[1] = {{
*/
static void *
H5O_name_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
- const uint8_t *p)
+ unsigned UNUSED *ioflags, const uint8_t *p)
{
H5O_name_t *mesg;
void *ret_value; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5O_name_decode);
+ FUNC_ENTER_NOAPI_NOINIT(H5O_name_decode)
/* check args */
- assert(f);
- assert(p);
+ HDassert(f);
+ HDassert(p);
/* decode */
- if (NULL==(mesg = H5MM_calloc(sizeof(H5O_name_t))) ||
- NULL==(mesg->s = H5MM_malloc (HDstrlen((const char*)p)+1)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
- HDstrcpy(mesg->s, (const char*)p);
+ if(NULL == (mesg = (H5O_name_t *)H5MM_calloc(sizeof(H5O_name_t))) ||
+ NULL == (mesg->s = (char *)H5MM_malloc(HDstrlen((const char *)p) + 1)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ HDstrcpy(mesg->s, (const char *)p);
/* Set return value */
- ret_value=mesg;
+ ret_value = mesg;
done:
- if(ret_value==NULL) {
+ if(NULL == ret_value) {
if(mesg)
- H5MM_xfree (mesg);
+ H5MM_xfree(mesg);
} /* end if */
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_name_decode() */
/*-------------------------------------------------------------------------
@@ -173,24 +174,25 @@ H5O_name_copy(const void *_mesg, void *_dest)
H5O_name_t *dest = (H5O_name_t *) _dest;
void *ret_value; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5O_name_copy);
+ FUNC_ENTER_NOAPI_NOINIT(H5O_name_copy)
/* check args */
- assert(mesg);
- if (!dest && NULL==(dest = H5MM_calloc(sizeof(H5O_name_t))))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
+ HDassert(mesg);
+
+ if(!dest && NULL == (dest = (H5O_name_t *)H5MM_calloc(sizeof(H5O_name_t))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* copy */
*dest = *mesg;
- if((dest->s = H5MM_xstrdup(mesg->s))==NULL)
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
+ if(NULL == (dest->s = H5MM_xstrdup(mesg->s)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Set return value */
- ret_value=dest;
+ ret_value = dest;
done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_name_copy() */
/*-------------------------------------------------------------------------
@@ -252,16 +254,16 @@ H5O_name_reset(void *_mesg)
{
H5O_name_t *mesg = (H5O_name_t *) _mesg;
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_name_reset);
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_name_reset)
/* check args */
- assert(mesg);
+ HDassert(mesg);
/* reset */
- mesg->s = H5MM_xfree(mesg->s);
+ mesg->s = (char *)H5MM_xfree(mesg->s);
- FUNC_LEAVE_NOAPI(SUCCEED);
-}
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5O_name_reset() */
/*-------------------------------------------------------------------------
diff --git a/src/H5Opkg.h b/src/H5Opkg.h
index c90ff0a..f15198e 100644
--- a/src/H5Opkg.h
+++ b/src/H5Opkg.h
@@ -43,7 +43,7 @@
*/
#define H5O_VERSION_2 2
-/* The latest version of the format. Look through the 'flush'
+/* The latest version of the format. Look through the 'flush'
* and 'size' callback for places to change when updating this. */
#define H5O_VERSION_LATEST H5O_VERSION_2
@@ -67,13 +67,6 @@
#define H5O_ALIGN_F(F, X) \
H5O_ALIGN_VERS((H5F_USE_LATEST_FORMAT(F) ? H5O_VERSION_LATEST : H5O_VERSION_1), X)
-/* Size of signature information (on disk) */
-#define H5O_SIZEOF_MAGIC 4
-
-/* Object header signatures */
-#define H5O_HDR_MAGIC "OHDR" /* Header */
-#define H5O_CHK_MAGIC "OCHK" /* Continuation chunk */
-
/* Size of checksum (on disk) */
#define H5O_SIZEOF_CHKSUM 4
@@ -106,7 +99,7 @@
4 + /*reference count */ \
4) /*chunk data size */ \
: \
- (H5O_SIZEOF_MAGIC + /*magic number */ \
+ (H5_SIZEOF_MAGIC + /*magic number */ \
1 + /*version number */ \
1 + /*flags */ \
(((O)->flags & H5O_HDR_STORE_TIMES) ? ( \
@@ -155,7 +148,7 @@
0 + /*no magic # */ \
0 /*no checksum */ \
: \
- H5O_SIZEOF_MAGIC + /*magic # */ \
+ H5_SIZEOF_MAGIC + /*magic # */ \
H5O_SIZEOF_CHKSUM /*checksum */ \
)
#define H5O_SIZEOF_CHKHDR_OH(O) \
@@ -174,17 +167,29 @@
#define H5O_SIZEOF_CHKSUM_OH(O) \
H5O_SIZEOF_CHKSUM_VERS((O)->version)
+/* Input/output flags for decode functions */
+#define H5O_DECODEIO_NOCHANGE 0x01u /* IN: do not modify values */
+#define H5O_DECODEIO_DIRTY 0x02u /* OUT: message has been changed */
+
/* Load native information for a message, if it's not already present */
/* (Only works for messages with decode callback) */
-#define H5O_LOAD_NATIVE(F, DXPL, OH, MSG, ERR) \
+#define H5O_LOAD_NATIVE(F, DXPL, IOF, OH, MSG, ERR) \
if(NULL == (MSG)->native) { \
const H5O_msg_class_t *msg_type = (MSG)->type; \
+ unsigned ioflags = (IOF); \
\
/* Decode the message */ \
HDassert(msg_type->decode); \
- if(NULL == ((MSG)->native = (msg_type->decode)((F), (DXPL), (MSG)->flags, (MSG)->raw))) \
+ if(NULL == ((MSG)->native = (msg_type->decode)((F), (DXPL), (MSG)->flags, &ioflags, (MSG)->raw))) \
HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, ERR, "unable to decode message") \
\
+ /* Mark the object header dirty if the message was changed by decoding */ \
+ if((ioflags & H5O_DECODEIO_DIRTY) && (H5F_get_intent((F)) & H5F_ACC_RDWR)) { \
+ (MSG)->dirty = TRUE; \
+ if(H5AC_mark_pinned_or_protected_entry_dirty((F), (OH)) < 0) \
+ HGOTO_ERROR(H5E_OHDR, H5E_CANTMARKDIRTY, ERR, "unable to mark object header as dirty") \
+ } \
+ \
/* Set the message's "shared info", if it's shareable */ \
if((MSG)->flags & H5O_MSG_FLAG_SHAREABLE) { \
H5O_UPDATE_SHARED((H5O_shared_t *)(MSG)->native, H5O_SHARE_TYPE_HERE, (F), msg_type->id, (MSG)->crt_idx, (OH)->chunk[0].addr) \
@@ -209,7 +214,7 @@ struct H5O_msg_class_t {
const char *name; /*for debugging */
size_t native_size; /*size of native message */
unsigned share_flags; /* Message sharing settings */
- void *(*decode)(H5F_t*, hid_t, unsigned, const uint8_t *);
+ void *(*decode)(H5F_t*, hid_t, unsigned, unsigned *, const uint8_t *);
herr_t (*encode)(H5F_t*, hbool_t, uint8_t*, const void *);
void *(*copy)(const void *, void *); /*copy native value */
size_t (*raw_size)(const H5F_t *, hbool_t, const void *);/*sizeof encoded message */
@@ -253,6 +258,12 @@ struct H5O_t {
/* File-specific information (not stored) */
size_t sizeof_size; /* Size of file sizes */
size_t sizeof_addr; /* Size of file addresses */
+#ifdef H5O_ENABLE_BAD_MESG_COUNT
+ hbool_t store_bad_mesg_count; /* Flag to indicate that a bad message count should be stored */
+ /* (This is to simulate a bug in earlier
+ * versions of the library)
+ */
+#endif /* H5O_ENABLE_BAD_MESG_COUNT */
/* Object information (stored) */
hbool_t has_refcount_msg; /* Whether the object has a ref. count message */
@@ -284,7 +295,7 @@ struct H5O_t {
};
/* Callback information for copying dataset */
-typedef struct {
+typedef struct H5D_copy_file_ud_t {
struct H5S_extent_t *src_space_extent; /* Copy of dataspace extent for dataset */
H5T_t *src_dtype; /* Copy of datatype for dataset */
H5O_pline_t *src_pline; /* Copy of filter pipeline for dataet */
@@ -297,7 +308,7 @@ typedef struct H5O_obj_class_t {
void *(*get_copy_file_udata)(void); /*retrieve user data for 'copy file' operation */
void (*free_copy_file_udata)(void *); /*free user data for 'copy file' operation */
htri_t (*isa)(H5O_t *); /*if a header matches an object class */
- hid_t (*open)(const H5G_loc_t *, hid_t ); /*open an object of this class */
+ hid_t (*open)(const H5G_loc_t *, hid_t, hid_t, hbool_t ); /*open an object of this class */
void *(*create)(H5F_t *, void *, H5G_loc_t *, hid_t ); /*create an object of this class */
H5O_loc_t *(*get_oloc)(hid_t ); /*get the object header location for an object */
} H5O_obj_class_t;
@@ -395,7 +406,7 @@ H5_DLLVAR const H5O_msg_class_t H5O_MSG_NAME[1];
*/
H5_DLLVAR const H5O_msg_class_t H5O_MSG_MTIME[1];
-/* Shared Message information message (0x000f)
+/* Shared Message information message (0x000f)
* A message for the superblock extension, holding information about
* the file-wide shared message "SOHM" table
*/
@@ -413,13 +424,13 @@ H5_DLLVAR const H5O_msg_class_t H5O_MSG_STAB[1];
*/
H5_DLLVAR const H5O_msg_class_t H5O_MSG_MTIME_NEW[1];
-/* v1 B-tree 'K' value message (0x0013)
+/* v1 B-tree 'K' value message (0x0013)
* A message for the superblock extension, holding information about
* the file-wide v1 B-tree 'K' values.
*/
H5_DLLVAR const H5O_msg_class_t H5O_MSG_BTREEK[1];
-/* Driver info message (0x0014)
+/* Driver info message (0x0014)
* A message for the superblock extension, holding information about
* the file driver settings
*/
@@ -452,7 +463,7 @@ H5_DLLVAR const H5O_obj_class_t H5O_OBJ_DATATYPE[1];
/* Package-local function prototypes */
H5_DLL herr_t H5O_msg_flush(H5F_t *f, H5O_t *oh, H5O_mesg_t *mesg);
H5_DLL herr_t H5O_flush_msgs(H5F_t *f, H5O_t *oh);
-H5_DLL hid_t H5O_open_by_loc(const H5G_loc_t *obj_loc, hid_t dxpl_id);
+H5_DLL hid_t H5O_open_by_loc(const H5G_loc_t *obj_loc, hid_t lapl_id, hid_t dxpl_id, hbool_t app_ref);
H5_DLL herr_t H5O_delete_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, H5O_mesg_t *mesg);
H5_DLL const H5O_obj_class_t *H5O_obj_class_real(H5O_t *oh);
@@ -496,14 +507,15 @@ H5_DLL herr_t H5O_release_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
H5O_mesg_t *mesg, hbool_t adj_link);
/* Shared object operators */
-H5_DLL void * H5O_shared_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *buf, const H5O_msg_class_t *type);
+H5_DLL void * H5O_shared_decode(H5F_t *f, hid_t dxpl_id, unsigned *ioflags,
+ const uint8_t *buf, const H5O_msg_class_t *type);
H5_DLL herr_t H5O_shared_encode(const H5F_t *f, uint8_t *buf/*out*/, const H5O_shared_t *sh_mesg);
H5_DLL size_t H5O_shared_size(const H5F_t *f, const H5O_shared_t *sh_mesg);
H5_DLL herr_t H5O_shared_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
const H5O_msg_class_t *mesg_type, H5O_shared_t *sh_mesg);
H5_DLL herr_t H5O_shared_link(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
const H5O_msg_class_t *mesg_type, H5O_shared_t *sh_mesg);
-H5_DLL herr_t H5O_shared_copy_file(H5F_t *file_src, H5F_t *file_dst,
+H5_DLL herr_t H5O_shared_copy_file(H5F_t *file_src, H5F_t *file_dst,
const H5O_msg_class_t *mesg_type, const void *_native_src, void *_native_dst,
hbool_t *recompute_size, H5O_copy_t *cpy_info, void *udata, hid_t dxpl_id);
H5_DLL herr_t H5O_shared_post_copy_file (H5F_t *f, hid_t dxpl_id, H5O_t *oh, void *mesg);
diff --git a/src/H5Opline.c b/src/H5Opline.c
index 9a926c1..fed2861 100644
--- a/src/H5Opline.c
+++ b/src/H5Opline.c
@@ -33,12 +33,13 @@
/* PRIVATE PROTOTYPES */
static herr_t H5O_pline_encode(H5F_t *f, uint8_t *p, const void *mesg);
-static void *H5O_pline_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags, const uint8_t *p);
+static void *H5O_pline_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags,
+ unsigned *ioflags, const uint8_t *p);
static void *H5O_pline_copy(const void *_mesg, void *_dest);
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_pre_copy_file(H5F_t *file_src,
+static herr_t H5O_pline_pre_copy_file(H5F_t *file_src,
const 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,
FILE * stream, int indent, int fwidth);
@@ -107,7 +108,7 @@ H5FL_DEFINE(H5O_pline_t);
*/
static void *
H5O_pline_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
- const uint8_t *p)
+ unsigned UNUSED *ioflags, const uint8_t *p)
{
H5O_pline_t *pline = NULL; /* Pipeline message */
H5Z_filter_info_t *filter; /* Filter to decode */
@@ -542,9 +543,9 @@ H5O_pline_free(void *mesg)
{
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_pline_free)
- HDassert (mesg);
+ HDassert(mesg);
- H5FL_FREE(H5O_pline_t, mesg);
+ (void)H5FL_FREE(H5O_pline_t, mesg);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_pline_free() */
diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h
index 31738a9..f65b15d 100644
--- a/src/H5Oprivate.h
+++ b/src/H5Oprivate.h
@@ -91,6 +91,10 @@ typedef struct H5O_t H5O_t;
#define H5O_BOGUS_MSG_FLAGS_NAME "bogus msg flags" /* Flags for 'bogus' message */
#define H5O_BOGUS_MSG_FLAGS_SIZE sizeof(uint8_t)
#endif /* H5O_ENABLE_BOGUS */
+#ifdef H5O_ENABLE_BAD_MESG_COUNT
+#define H5O_BAD_MESG_COUNT_NAME "bad message count" /* Flag setting bad message count */
+#define H5O_BAD_MESG_COUNT_SIZE sizeof(hbool_t)
+#endif /* H5O_ENABLE_BAD_MESG_COUNT */
/* ========= Object Copy properties ============ */
#define H5O_CPY_OPTION_NAME "copy object" /* Copy options */
@@ -322,6 +326,10 @@ typedef struct H5O_efl_t {
*/
#define H5O_LAYOUT_NDIMS (H5S_MAX_RANK+1)
+/* Forward declaration of structs used below */
+struct H5D_layout_ops_t; /* Defined in H5Dpkg.h */
+struct H5D_chunk_ops_t; /* Defined in H5Dpkg.h */
+
typedef struct H5O_layout_contig_t {
haddr_t addr; /* File address of data */
hsize_t size; /* Size of data in bytes */
@@ -330,9 +338,10 @@ typedef struct H5O_layout_contig_t {
typedef struct H5O_layout_chunk_t {
haddr_t addr; /* File address of B-tree */
unsigned ndims; /* Num dimensions in chunk */
- size_t dim[H5O_LAYOUT_NDIMS]; /* Size of chunk in elements */
- size_t size; /* Size of chunk in bytes */
+ uint32_t dim[H5O_LAYOUT_NDIMS]; /* Size of chunk in elements */
+ uint32_t size; /* Size of chunk in bytes */
H5RC_t *btree_shared; /* Ref-counted info for B-tree nodes */
+ const struct H5D_chunk_ops_t *ops; /* Pointer to chunked layout operations */
} H5O_layout_chunk_t;
typedef struct H5O_layout_compact_t {
@@ -344,6 +353,7 @@ typedef struct H5O_layout_compact_t {
typedef struct H5O_layout_t {
H5D_layout_t type; /* Type of layout */
unsigned version; /* Version of message */
+ const struct H5D_layout_ops_t *ops; /* Pointer to data layout I/O operations */
union {
H5O_layout_contig_t contig; /* Information for contiguous layout */
H5O_layout_chunk_t chunk; /* Information for chunked layout */
@@ -536,38 +546,41 @@ H5_DLL herr_t H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint,
H5_DLL herr_t H5O_open(H5O_loc_t *loc);
H5_DLL herr_t H5O_close(H5O_loc_t *loc);
H5_DLL int H5O_link(const H5O_loc_t *loc, int adjust, hid_t dxpl_id);
-H5_DLL struct H5O_t *H5O_protect(H5O_loc_t *loc, hid_t dxpl_id);
-H5_DLL herr_t H5O_unprotect(H5O_loc_t *loc, struct H5O_t *oh);
+H5_DLL H5O_t *H5O_protect(H5O_loc_t *loc, hid_t dxpl_id);
+H5_DLL herr_t H5O_unprotect(H5O_loc_t *loc, H5O_t *oh);
H5_DLL herr_t H5O_touch(H5O_loc_t *loc, hbool_t force, hid_t dxpl_id);
-H5_DLL herr_t H5O_touch_oh(H5F_t *f, hid_t dxpl_id, struct H5O_t *oh,
+H5_DLL herr_t H5O_touch_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
hbool_t force);
#ifdef H5O_ENABLE_BOGUS
-H5_DLL herr_t H5O_bogus_oh(H5F_t *f, hid_t dxpl_id, struct H5O_t *oh, unsigned mesg_flags);
+H5_DLL herr_t H5O_bogus_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned mesg_flags);
#endif /* H5O_ENABLE_BOGUS */
H5_DLL herr_t H5O_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr);
H5_DLL herr_t H5O_get_info(H5O_loc_t *oloc, hid_t dxpl_id, hbool_t want_ih_info,
H5O_info_t *oinfo);
H5_DLL herr_t H5O_obj_type(const H5O_loc_t *loc, H5O_type_t *obj_type, hid_t dxpl_id);
H5_DLL herr_t H5O_get_create_plist(const H5O_loc_t *loc, hid_t dxpl_id, struct H5P_genplist_t *oc_plist);
-H5_DLL hid_t H5O_open_name(H5G_loc_t *loc, const char *name, hid_t lapl_id);
+H5_DLL hid_t H5O_open_name(H5G_loc_t *loc, const char *name, hid_t lapl_id, hbool_t app_ref);
H5_DLL herr_t H5O_get_nlinks(const H5O_loc_t *loc, hid_t dxpl_id, hsize_t *nlinks);
H5_DLL void *H5O_obj_create(H5F_t *f, H5O_type_t obj_type, void *crt_info, H5G_loc_t *obj_loc, hid_t dxpl_id);
H5_DLL haddr_t H5O_get_oh_addr(const H5O_t *oh);
+H5_DLL herr_t H5O_get_rc_and_type(const H5O_loc_t *oloc, hid_t dxpl_id, unsigned *rc, H5O_type_t *otype);
/* Object header message routines */
H5_DLL herr_t H5O_msg_create(const H5O_loc_t *loc, unsigned type_id, unsigned mesg_flags,
unsigned update_flags, void *mesg, hid_t dxpl_id);
-H5_DLL herr_t H5O_msg_append(H5F_t *f, hid_t dxpl_id, struct H5O_t *oh, unsigned type_id,
+H5_DLL herr_t H5O_msg_append_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned type_id,
unsigned mesg_flags, unsigned update_flags, void *mesg);
-H5_DLL herr_t H5O_msg_write(const H5O_loc_t *loc, unsigned type_id, unsigned flags,
- unsigned update_flags, void *mesg, hid_t dxpl_id);
+H5_DLL herr_t H5O_msg_write(const H5O_loc_t *loc, unsigned type_id,
+ unsigned mesg_flags, unsigned update_flags, void *mesg, hid_t dxpl_id);
+H5_DLL herr_t H5O_msg_write_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
+ unsigned type_id, unsigned mesg_flags, unsigned update_flags, void *mesg);
H5_DLL void *H5O_msg_read(const H5O_loc_t *loc, unsigned type_id, void *mesg,
hid_t dxpl_id);
H5_DLL herr_t H5O_msg_reset(unsigned type_id, void *native);
H5_DLL void *H5O_msg_free(unsigned type_id, void *mesg);
H5_DLL void *H5O_msg_copy(unsigned type_id, const void *mesg, void *dst);
H5_DLL int H5O_msg_count(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id);
-H5_DLL htri_t H5O_msg_exists(H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id);
+H5_DLL htri_t H5O_msg_exists(const H5O_loc_t *loc, unsigned type_id, hid_t dxpl_id);
H5_DLL herr_t H5O_msg_remove(const H5O_loc_t *loc, unsigned type_id, int sequence,
hbool_t adj_link, hid_t dxpl_id);
H5_DLL herr_t H5O_msg_remove_op(const H5O_loc_t *loc, unsigned type_id, int sequence,
@@ -590,7 +603,7 @@ H5_DLL herr_t H5O_msg_get_crt_index(unsigned type_id, const void *mesg,
H5O_msg_crt_idx_t *crt_idx);
H5_DLL herr_t H5O_msg_encode(H5F_t *f, unsigned type_id, hbool_t disable_shared,
unsigned char *buf, const void *obj);
-H5_DLL void* H5O_msg_decode(H5F_t *f, hid_t dxpl_id, unsigned type_id,
+H5_DLL void* H5O_msg_decode(H5F_t *f, hid_t dxpl_id, unsigned type_id,
const unsigned char *buf);
H5_DLL herr_t H5O_msg_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
unsigned type_id, void *mesg);
diff --git a/src/H5Opublic.h b/src/H5Opublic.h
index 6ddd565..ddf1a93 100644
--- a/src/H5Opublic.h
+++ b/src/H5Opublic.h
@@ -52,13 +52,13 @@
* but we need to assign each kind of message to a different bit so that
* one index can hold multiple types.)
*/
-#define H5O_MESG_NONE_FLAG 0x0000 /* No shared messages */
-#define H5O_MESG_SDSPACE_FLAG 0x0001 /* Simple Dataspace Message. */
-#define H5O_MESG_DTYPE_FLAG 0x0002 /* Datatype Message. */
-#define H5O_MESG_FILL_FLAG 0x0004 /* Fill Value Message. */
-#define H5O_MESG_PLINE_FLAG 0x0008 /* Filter pipeline message. */
-#define H5O_MESG_ATTR_FLAG 0x0010 /* Attribute Message. */
-#define H5O_MESG_ALL_FLAG (H5O_MESG_SDSPACE_FLAG | H5O_MESG_DTYPE_FLAG | H5O_MESG_FILL_FLAG | H5O_MESG_PLINE_FLAG | H5O_MESG_ATTR_FLAG)
+#define H5O_SHMESG_NONE_FLAG 0x0000 /* No shared messages */
+#define H5O_SHMESG_SDSPACE_FLAG ((unsigned)1 << 0x0001) /* Simple Dataspace Message. */
+#define H5O_SHMESG_DTYPE_FLAG ((unsigned)1 << 0x0003) /* Datatype Message. */
+#define H5O_SHMESG_FILL_FLAG ((unsigned)1 << 0x0005) /* Fill Value Message. */
+#define H5O_SHMESG_PLINE_FLAG ((unsigned)1 << 0x000b) /* Filter pipeline message. */
+#define H5O_SHMESG_ATTR_FLAG ((unsigned)1 << 0x000c) /* Attribute Message. */
+#define H5O_SHMESG_ALL_FLAG (H5O_SHMESG_SDSPACE_FLAG | H5O_SHMESG_DTYPE_FLAG | H5O_SHMESG_FILL_FLAG | H5O_SHMESG_PLINE_FLAG | H5O_SHMESG_ATTR_FLAG)
/* Object header status flag definitions */
#define H5O_HDR_CHUNK0_SIZE 0x03 /* 2-bit field indicating # of bytes to store the size of chunk 0's data */
@@ -124,6 +124,10 @@ typedef struct H5O_info_t {
/* Typedef for message creation indexes */
typedef uint32_t H5O_msg_crt_idx_t;
+/* Prototype for H5Ovisit/H5Ovisit_by_name() operator */
+typedef herr_t (*H5O_iterate_t)(hid_t obj, const char *name, const H5O_info_t *info,
+ void *op_data);
+
/********************/
/* Public Variables */
@@ -159,10 +163,15 @@ H5_DLL herr_t H5Oset_comment_by_name(hid_t loc_id, const char *name,
H5_DLL ssize_t H5Oget_comment(hid_t obj_id, char *comment, size_t bufsize);
H5_DLL ssize_t H5Oget_comment_by_name(hid_t loc_id, const char *name,
char *comment, size_t bufsize, hid_t lapl_id);
+H5_DLL herr_t H5Ovisit(hid_t obj_id, H5_index_t idx_type, H5_iter_order_t order,
+ H5O_iterate_t op, void *op_data);
+H5_DLL herr_t H5Ovisit_by_name(hid_t loc_id, const char *obj_name,
+ H5_index_t idx_type, H5_iter_order_t order, H5O_iterate_t op,
+ void *op_data, hid_t lapl_id);
H5_DLL herr_t H5Oclose(hid_t object_id);
/* Symbols defined for compatibility with previous versions of the HDF5 API.
- *
+ *
* Use of these symbols is deprecated.
*/
#ifndef H5_NO_DEPRECATED_SYMBOLS
diff --git a/src/H5Orefcount.c b/src/H5Orefcount.c
index 0a06d11..b2f02b2 100644
--- a/src/H5Orefcount.c
+++ b/src/H5Orefcount.c
@@ -33,7 +33,8 @@
/* PRIVATE PROTOTYPES */
-static void *H5O_refcount_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags, const uint8_t *p);
+static void *H5O_refcount_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags,
+ unsigned *ioflags, const uint8_t *p);
static herr_t H5O_refcount_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
static void *H5O_refcount_copy(const void *_mesg, void *_dest);
static size_t H5O_refcount_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
@@ -90,7 +91,7 @@ H5FL_DEFINE_STATIC(H5O_refcount_t);
*/
static void *
H5O_refcount_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
- const uint8_t *p)
+ unsigned UNUSED *ioflags, const uint8_t *p)
{
H5O_refcount_t *refcount = NULL; /* Reference count */
void *ret_value; /* Return value */
@@ -117,7 +118,7 @@ H5O_refcount_decode(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_
done:
if(ret_value == NULL && refcount != NULL)
- H5FL_FREE(H5O_refcount_t, refcount);
+ (void)H5FL_FREE(H5O_refcount_t, refcount);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_refcount_decode() */
@@ -249,7 +250,7 @@ H5O_refcount_free(void *mesg)
HDassert(mesg);
- H5FL_FREE(H5O_refcount_t, mesg);
+ (void)H5FL_FREE(H5O_refcount_t, mesg);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_refcount_free() */
diff --git a/src/H5Osdspace.c b/src/H5Osdspace.c
index c97498a..fe7bf02 100644
--- a/src/H5Osdspace.c
+++ b/src/H5Osdspace.c
@@ -26,7 +26,8 @@
/* PRIVATE PROTOTYPES */
-static void *H5O_sdspace_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags, const uint8_t *p);
+static void *H5O_sdspace_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags,
+ unsigned *ioflags, const uint8_t *p);
static herr_t H5O_sdspace_encode(H5F_t *f, uint8_t *p, const void *_mesg);
static void *H5O_sdspace_copy(const void *_mesg, void *_dest);
static size_t H5O_sdspace_size(const H5F_t *f, const void *_mesg);
@@ -109,7 +110,7 @@ H5FL_ARR_EXTERN(hsize_t);
--------------------------------------------------------------------------*/
static void *
H5O_sdspace_decode(H5F_t *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
- const uint8_t *p)
+ unsigned UNUSED *ioflags, const uint8_t *p)
{
H5S_extent_t *sdim = NULL;/* New extent dimensionality structure */
void *ret_value;
@@ -189,7 +190,7 @@ H5O_sdspace_decode(H5F_t *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
done:
if(!ret_value && sdim) {
H5S_extent_release(sdim);
- H5FL_FREE(H5S_extent_t, sdim);
+ (void)H5FL_FREE(H5S_extent_t, sdim);
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
@@ -309,7 +310,7 @@ H5O_sdspace_copy(const void *mesg, void *dest)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Copy extent information */
- if(H5S_extent_copy(dst, src) < 0)
+ if(H5S_extent_copy(dst, src, TRUE) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, NULL, "can't copy extent")
/* Set return value */
@@ -413,7 +414,7 @@ H5O_sdspace_free(void *mesg)
HDassert(mesg);
- H5FL_FREE(H5S_extent_t, mesg);
+ (void)H5FL_FREE(H5S_extent_t, mesg);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_sdspace_free() */
@@ -460,7 +461,7 @@ H5O_sdspace_pre_copy_file(H5F_t UNUSED *file_src, const void *mesg_src,
HGOTO_ERROR(H5E_DATASPACE, H5E_NOSPACE, FAIL, "dataspace extent allocation failed")
/* Create a copy of the dataspace extent */
- if(H5S_extent_copy(udata->src_space_extent, src_space_extent) < 0)
+ if(H5S_extent_copy(udata->src_space_extent, src_space_extent, TRUE) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy extent")
} /* end if */
diff --git a/src/H5Oshared.c b/src/H5Oshared.c
index e406065..062443a 100644
--- a/src/H5Oshared.c
+++ b/src/H5Oshared.c
@@ -107,8 +107,8 @@
*-------------------------------------------------------------------------
*/
static void *
-H5O_shared_read(H5F_t *f, hid_t dxpl_id, const H5O_shared_t *shared,
- const H5O_msg_class_t *type)
+H5O_shared_read(H5F_t *f, hid_t dxpl_id, unsigned *ioflags,
+ const H5O_shared_t *shared, const H5O_msg_class_t *type)
{
H5HF_t *fheap = NULL;
H5WB_t *wb = NULL; /* Wrapped buffer for attribute data */
@@ -151,7 +151,7 @@ H5O_shared_read(H5F_t *f, hid_t dxpl_id, const H5O_shared_t *shared,
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "can't wrap buffer")
/* Get a pointer to a buffer that's large enough for message */
- if(NULL == (mesg_ptr = H5WB_actual(wb, mesg_size)))
+ if(NULL == (mesg_ptr = (uint8_t *)H5WB_actual(wb, mesg_size)))
HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, NULL, "can't get actual buffer")
/* Retrieve the message from the heap */
@@ -159,7 +159,7 @@ H5O_shared_read(H5F_t *f, hid_t dxpl_id, const H5O_shared_t *shared,
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "can't read message from fractal heap.")
/* Decode the message */
- if(NULL == (ret_value = (type->decode)(f, dxpl_id, 0, mesg_ptr)))
+ if(NULL == (ret_value = (type->decode)(f, dxpl_id, 0, ioflags, mesg_ptr)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, NULL, "can't decode shared message.")
} /* end if */
else {
@@ -277,7 +277,8 @@ done:
*-------------------------------------------------------------------------
*/
void *
-H5O_shared_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *buf, const H5O_msg_class_t *type)
+H5O_shared_decode(H5F_t *f, hid_t dxpl_id, unsigned *ioflags,
+ const uint8_t *buf, const H5O_msg_class_t *type)
{
H5O_shared_t sh_mesg; /* Shared message info */
unsigned version; /* Shared message version */
@@ -343,7 +344,7 @@ H5O_shared_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *buf, const H5O_msg_cla
sh_mesg.msg_type_id = type->id;
/* Retrieve actual message, through decoded shared message info */
- if(NULL == (ret_value = H5O_shared_read(f, dxpl_id, &sh_mesg, type)))
+ if(NULL == (ret_value = H5O_shared_read(f, dxpl_id, ioflags, &sh_mesg, type)))
HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to retrieve native message")
done:
@@ -489,7 +490,7 @@ H5O_shared_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
HDassert(f);
HDassert(sh_mesg);
- /*
+ /*
* 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
@@ -555,7 +556,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5O_shared_copy_file(H5F_t UNUSED *file_src, H5F_t *file_dst,
+H5O_shared_copy_file(H5F_t UNUSED *file_src, H5F_t *file_dst,
const H5O_msg_class_t *mesg_type, const void *_native_src, void *_native_dst,
hbool_t UNUSED *recompute_size, H5O_copy_t *cpy_info, void UNUSED *udata,
hid_t dxpl_id)
@@ -614,7 +615,7 @@ done:
* Purpose: Delate a shared message and replace with a new one.
* The function is needed at cases such as coping a shared reg_ref attribute.
* When a shared reg_ref attribute is copied from one file to
- * another, the values in file need to be replaced. The only way
+ * another, the values in file need to be replaced. The only way
* to complish that is to delete the old message and write the
* new message with the correct values.
*
diff --git a/src/H5Oshared.h b/src/H5Oshared.h
index 582d29b..d52cd8f 100644
--- a/src/H5Oshared.h
+++ b/src/H5Oshared.h
@@ -48,7 +48,8 @@
*-------------------------------------------------------------------------
*/
static H5_inline void *
-H5O_SHARED_DECODE(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags, const uint8_t *p)
+H5O_SHARED_DECODE(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags,
+ unsigned *ioflags, const uint8_t *p)
{
void *ret_value; /* Return value */
@@ -67,12 +68,20 @@ H5O_SHARED_DECODE(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags, const uint8_t *p
/* Check for shared message */
if(mesg_flags & H5O_MSG_FLAG_SHARED) {
/* Retrieve native message info indirectly through shared message */
- if(NULL == (ret_value = H5O_shared_decode(f, dxpl_id, p, H5O_SHARED_TYPE)))
+ if(NULL == (ret_value = H5O_shared_decode(f, dxpl_id, ioflags, p, H5O_SHARED_TYPE)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, NULL, "unable to decode shared message")
+
+ /* We currently do not support automatically fixing shared messages */
+#ifdef H5_STRICT_FORMAT_CHECKS
+ if(*ioflags & H5O_DECODEIO_DIRTY)
+ HGOTO_ERROR(H5E_OHDR, H5E_UNSUPPORTED, NULL, "unable to mark shared message dirty")
+#else /* H5_STRICT_FORMAT_CHECKS */
+ *ioflags &= ~H5O_DECODEIO_DIRTY;
+#endif /* H5_STRICT_FORMAT_CHECKS */
} /* end if */
else {
/* Decode native message directly */
- if(NULL == (ret_value = H5O_SHARED_DECODE_REAL(f, dxpl_id, mesg_flags, p)))
+ if(NULL == (ret_value = H5O_SHARED_DECODE_REAL(f, dxpl_id, mesg_flags, ioflags, p)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, NULL, "unable to decode native message")
} /* end else */
@@ -350,7 +359,7 @@ done:
if(!ret_value)
if(dst_mesg)
H5O_msg_free(H5O_SHARED_TYPE->id, dst_mesg);
-
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5O_SHARED_COPY_FILE() */
@@ -395,7 +404,7 @@ H5O_SHARED_POST_COPY_FILE(const H5O_loc_t *oloc_src, const void *mesg_src,
#ifdef H5O_SHARED_POST_COPY_FILE_REAL
/* Call native message's copy file callback to copy the message */
- if(H5O_SHARED_POST_COPY_FILE_REAL(oloc_src, mesg_src, oloc_dst, mesg_dst, dxpl_id, cpy_info) <0 )
+ if(H5O_SHARED_POST_COPY_FILE_REAL(oloc_src, mesg_src, oloc_dst, mesg_dst, dxpl_id, cpy_info) <0 )
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy native message to another file")
#endif /* H5O_SHARED_POST_COPY_FILE_REAL */
diff --git a/src/H5Oshmesg.c b/src/H5Oshmesg.c
index e66bdec..74fe739 100644
--- a/src/H5Oshmesg.c
+++ b/src/H5Oshmesg.c
@@ -28,7 +28,8 @@
#include "H5Opkg.h" /* Object headers */
#include "H5MMprivate.h" /* Memory management */
-static void *H5O_shmesg_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags, const uint8_t *p);
+static void *H5O_shmesg_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags,
+ unsigned *ioflags, const uint8_t *p);
static herr_t H5O_shmesg_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
static void *H5O_shmesg_copy(const void *_mesg, void *_dest);
static size_t H5O_shmesg_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
@@ -76,7 +77,7 @@ const H5O_msg_class_t H5O_MSG_SHMESG[1] = {{
*/
static void *
H5O_shmesg_decode(H5F_t *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
- const uint8_t *p)
+ unsigned UNUSED *ioflags, const uint8_t *p)
{
H5O_shmesg_table_t *mesg; /* Native message */
void *ret_value; /* Return value */
@@ -87,7 +88,7 @@ H5O_shmesg_decode(H5F_t *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
HDassert(f);
HDassert(p);
- if(NULL == (mesg = H5MM_calloc(sizeof(H5O_shmesg_table_t))))
+ if(NULL == (mesg = (H5O_shmesg_table_t *)H5MM_calloc(sizeof(H5O_shmesg_table_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for shared message table message")
/* Retrieve version, table address, and number of indexes */
@@ -162,7 +163,7 @@ H5O_shmesg_copy(const void *_mesg, void *_dest)
/* Sanity check */
HDassert(mesg);
- if(!dest && NULL == (dest = H5MM_malloc(sizeof(H5O_shmesg_table_t))))
+ if(!dest && NULL == (dest = (H5O_shmesg_table_t *)H5MM_malloc(sizeof(H5O_shmesg_table_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for shared message table message")
/* All this message requires is a shallow copy */
diff --git a/src/H5Ostab.c b/src/H5Ostab.c
index 978b9c5..9524f43 100644
--- a/src/H5Ostab.c
+++ b/src/H5Ostab.c
@@ -36,7 +36,8 @@
/* PRIVATE PROTOTYPES */
-static void *H5O_stab_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags, const uint8_t *p);
+static void *H5O_stab_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags,
+ unsigned *ioflags, const uint8_t *p);
static herr_t H5O_stab_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
static void *H5O_stab_copy(const void *_mesg, void *_dest);
static size_t H5O_stab_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
@@ -96,34 +97,34 @@ H5FL_DEFINE_STATIC(H5O_stab_t);
*/
static void *
H5O_stab_decode(H5F_t *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags,
- const uint8_t *p)
+ unsigned UNUSED *ioflags, const uint8_t *p)
{
- H5O_stab_t *stab=NULL;
+ H5O_stab_t *stab = NULL;
void *ret_value; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5O_stab_decode);
+ FUNC_ENTER_NOAPI_NOINIT(H5O_stab_decode)
/* check args */
- assert(f);
- assert(p);
+ HDassert(f);
+ HDassert(p);
/* decode */
- if (NULL==(stab = H5FL_CALLOC(H5O_stab_t)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
+ if(NULL == (stab = H5FL_CALLOC(H5O_stab_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
H5F_addr_decode(f, &p, &(stab->btree_addr));
H5F_addr_decode(f, &p, &(stab->heap_addr));
/* Set return value */
- ret_value=stab;
+ ret_value = stab;
done:
- if(ret_value==NULL) {
- if(stab!=NULL)
- H5FL_FREE(H5O_stab_t,stab);
+ if(ret_value == NULL) {
+ if(stab != NULL)
+ (void)H5FL_FREE(H5O_stab_t,stab);
} /* end if */
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5O_stab_decode() */
/*-------------------------------------------------------------------------
@@ -246,16 +247,16 @@ H5O_stab_size(const H5F_t *f, hbool_t UNUSED disable_shared, const void UNUSED *
*-------------------------------------------------------------------------
*/
static herr_t
-H5O_stab_free (void *mesg)
+H5O_stab_free(void *mesg)
{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_stab_free);
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_stab_free)
- assert (mesg);
+ HDassert(mesg);
- H5FL_FREE(H5O_stab_t,mesg);
+ (void)H5FL_FREE(H5O_stab_t, mesg);
- FUNC_LEAVE_NOAPI(SUCCEED);
-}
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5O_stab_free() */
/*-------------------------------------------------------------------------
@@ -282,7 +283,7 @@ H5O_stab_delete(H5F_t *f, hid_t dxpl_id, H5O_t UNUSED *open_oh, void *mesg)
HDassert(mesg);
/* Free the file space for the symbol table */
- if(H5G_stab_delete(f, dxpl_id, mesg) < 0)
+ if(H5G_stab_delete(f, dxpl_id, (const H5O_stab_t *)mesg) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to free symbol table")
done:
@@ -338,7 +339,7 @@ H5O_stab_copy_file(H5F_t *file_src, void *native_src, H5F_t *file_dst,
done:
if(!ret_value)
if(stab_dst)
- H5FL_FREE(H5O_stab_t, stab_dst);
+ (void)H5FL_FREE(H5O_stab_t, stab_dst);
FUNC_LEAVE_NOAPI(ret_value)
} /* H5O_stab_copy_file() */
@@ -386,7 +387,7 @@ H5O_stab_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src, H5O_loc
udata.cpy_info = cpy_info;
/* Iterate over objects in group, copying them */
- if((H5B_iterate(src_oloc->file, dxpl_id, H5B_SNODE, H5G_node_copy, stab_src->btree_addr, &udata)) < 0)
+ if((H5B_iterate(src_oloc->file, dxpl_id, H5B_SNODE, stab_src->btree_addr, H5G_node_copy, &udata)) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "iteration operator failed")
done:
diff --git a/src/H5Otest.c b/src/H5Otest.c
index 359c312..8116ffa 100644
--- a/src/H5Otest.c
+++ b/src/H5Otest.c
@@ -107,7 +107,7 @@ H5O_is_attr_dense_test(hid_t oid)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found")
/* Get the object header */
- if(NULL == (oh = H5AC_protect(oloc->file, H5AC_ind_dxpl_id, H5AC_OHDR, oloc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = (H5O_t *)H5AC_protect(oloc->file, H5AC_ind_dxpl_id, H5AC_OHDR, oloc->addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
/* Check for attribute info stored */
@@ -169,7 +169,7 @@ H5O_is_attr_empty_test(hid_t oid)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found")
/* Get the object header */
- if(NULL == (oh = H5AC_protect(oloc->file, H5AC_ind_dxpl_id, H5AC_OHDR, oloc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = (H5O_t *)H5AC_protect(oloc->file, H5AC_ind_dxpl_id, H5AC_OHDR, oloc->addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
/* Check for attribute info stored */
@@ -247,7 +247,7 @@ H5O_num_attrs_test(hid_t oid, hsize_t *nattrs)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found")
/* Get the object header */
- if(NULL == (oh = H5AC_protect(oloc->file, H5AC_ind_dxpl_id, H5AC_OHDR, oloc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = (H5O_t *)H5AC_protect(oloc->file, H5AC_ind_dxpl_id, H5AC_OHDR, oloc->addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
/* Check for attribute info stored */
@@ -322,7 +322,7 @@ H5O_attr_dense_info_test(hid_t oid, hsize_t *name_count, hsize_t *corder_count)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found")
/* Get the object header */
- if(NULL == (oh = H5AC_protect(oloc->file, H5AC_ind_dxpl_id, H5AC_OHDR, oloc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = (H5O_t *)H5AC_protect(oloc->file, H5AC_ind_dxpl_id, H5AC_OHDR, oloc->addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
/* Check for attribute info stored */
@@ -395,7 +395,7 @@ H5O_check_msg_marked_test(hid_t oid, hbool_t flag_val)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found")
/* Get the object header */
- if(NULL == (oh = H5AC_protect(oloc->file, H5AC_ind_dxpl_id, H5AC_OHDR, oloc->addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = (H5O_t *)H5AC_protect(oloc->file, H5AC_ind_dxpl_id, H5AC_OHDR, oloc->addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
/* Locate "unknown" message */
diff --git a/src/H5Ounknown.c b/src/H5Ounknown.c
index 5b0a38a..fe31a6d 100644
--- a/src/H5Ounknown.c
+++ b/src/H5Ounknown.c
@@ -82,7 +82,7 @@ H5O_unknown_free(void *mesg)
HDassert(mesg);
- H5FL_FREE(H5O_unknown_t, mesg);
+ (void)H5FL_FREE(H5O_unknown_t, mesg);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5O_unknown_free() */
diff --git a/src/H5P.c b/src/H5P.c
index c6a762c..212b308 100644
--- a/src/H5P.c
+++ b/src/H5P.c
@@ -128,7 +128,7 @@ H5Pcopy(hid_t id)
/* Compare property lists */
if(H5I_GENPROP_LST == H5I_get_type(id)) {
- if((ret_value = H5P_copy_plist(obj)) < 0)
+ if((ret_value = H5P_copy_plist((H5P_genplist_t *)obj, TRUE)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "can't copy property list");
} /* end if */
/* Must be property classes */
@@ -136,11 +136,11 @@ H5Pcopy(hid_t id)
H5P_genclass_t *copy_class; /* Copy of class */
/* Copy the class */
- if((copy_class = H5P_copy_pclass(obj)) == NULL)
+ if((copy_class = H5P_copy_pclass((H5P_genclass_t *)obj)) == NULL)
HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "can't copy property class");
/* Get an atom for the copied class */
- if((ret_value = H5I_register(H5I_GENPROP_CLS, copy_class)) < 0) {
+ if((ret_value = H5I_register(H5I_GENPROP_CLS, copy_class, TRUE)) < 0) {
H5P_close_class(copy_class);
HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "unable to atomize property list class");
} /* end if */
@@ -196,39 +196,39 @@ H5Pcreate_class(hid_t parent, const char *name,
H5P_genclass_t *pclass = NULL; /* Property list class created */
hid_t ret_value; /* Return value */
- FUNC_ENTER_API(H5Pcreate_class, FAIL);
+ FUNC_ENTER_API(H5Pcreate_class, FAIL)
H5TRACE8("i", "i*sx*xx*xx*x", parent, name, cls_create, create_data, cls_copy,
copy_data, cls_close, close_data);
/* Check arguments. */
if(H5P_DEFAULT!=parent && (H5I_GENPROP_CLS!=H5I_get_type(parent)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list class");
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list class")
if(!name || !*name)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid class name");
- if((create_data!=NULL && cls_create==NULL)
- || (copy_data!=NULL && cls_copy==NULL)
- || (close_data!=NULL && cls_close==NULL))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "data specified, but no callback provided");
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid class name")
+ if((create_data != NULL && cls_create == NULL)
+ || (copy_data != NULL && cls_copy == NULL)
+ || (close_data != NULL && cls_close == NULL))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "data specified, but no callback provided")
/* Get the pointer to the parent class */
- if(parent==H5P_DEFAULT)
- par_class=NULL;
- else if(NULL == (par_class = H5I_object(parent)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't retrieve parent class");
+ if(parent == H5P_DEFAULT)
+ par_class = NULL;
+ else if(NULL == (par_class = (H5P_genclass_t *)H5I_object(parent)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't retrieve parent class")
/* Create the new property list class */
- if(NULL==(pclass=H5P_create_class(par_class, name, 0, cls_create, create_data, cls_copy, copy_data, cls_close, close_data)))
- HGOTO_ERROR(H5E_PLIST, H5E_CANTCREATE, FAIL, "unable to create property list class");
+ if(NULL == (pclass = H5P_create_class(par_class, name, 0, cls_create, create_data, cls_copy, copy_data, cls_close, close_data)))
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTCREATE, FAIL, "unable to create property list class")
/* Get an atom for the class */
- if((ret_value = H5I_register(H5I_GENPROP_CLS, pclass)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "unable to atomize property list class");
+ if((ret_value = H5I_register(H5I_GENPROP_CLS, pclass, TRUE)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "unable to atomize property list class")
done:
- if(ret_value<0 && pclass)
+ if(ret_value < 0 && pclass)
H5P_close_class(pclass);
- FUNC_LEAVE_API(ret_value);
+ FUNC_LEAVE_API(ret_value)
} /* H5Pcreate_class() */
@@ -264,11 +264,11 @@ H5Pcreate(hid_t cls_id)
H5TRACE1("i", "i", cls_id);
/* Check arguments. */
- if(NULL == (pclass = H5I_object_verify(cls_id, H5I_GENPROP_CLS)))
+ if(NULL == (pclass = (H5P_genclass_t *)H5I_object_verify(cls_id, H5I_GENPROP_CLS)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list class");
/* Create the new property list */
- if((ret_value = H5P_create_id(pclass)) < 0)
+ if((ret_value = H5P_create_id(pclass, TRUE)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTCREATE, FAIL, "unable to create property list");
done:
@@ -445,7 +445,7 @@ H5Pregister2(hid_t cls_id, const char *name, size_t size, void *def_value,
prp_set, prp_get, prp_delete, prp_copy, prp_cmp, prp_close);
/* Check arguments. */
- if(NULL == (pclass = H5I_object_verify(cls_id, H5I_GENPROP_CLS)))
+ if(NULL == (pclass = (H5P_genclass_t *)H5I_object_verify(cls_id, H5I_GENPROP_CLS)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list class");
if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid class name");
@@ -614,7 +614,7 @@ H5Pinsert2(hid_t plist_id, const char *name, size_t size, void *value,
prp_delete, prp_copy, prp_cmp, prp_close);
/* Check arguments. */
- if(NULL == (plist = H5I_object_verify(plist_id, H5I_GENPROP_LST)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object_verify(plist_id, H5I_GENPROP_LST)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid property name")
@@ -671,7 +671,7 @@ H5Pset(hid_t plist_id, const char *name, void *value)
H5TRACE3("e", "i*s*x", plist_id, name, value);
/* Check arguments. */
- if(NULL == (plist = H5I_object_verify(plist_id, H5I_GENPROP_LST)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object_verify(plist_id, H5I_GENPROP_LST)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list");
if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid property name");
@@ -727,14 +727,14 @@ H5Pexist(hid_t id, const char *name)
/* Check for the existance of the property in the list or class */
if(H5I_GENPROP_LST == H5I_get_type(id)) {
- if(NULL == (plist = H5I_object(id)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list");
if((ret_value = H5P_exist_plist(plist, name)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "property does not exist in list");
} /* end if */
else
if(H5I_GENPROP_CLS == H5I_get_type(id)) {
- if(NULL == (pclass = H5I_object(id)))
+ if(NULL == (pclass = (H5P_genclass_t *)H5I_object(id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property class");
if((ret_value = H5P_exist_pclass(pclass, name)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "property does not exist in class");
@@ -789,7 +789,7 @@ H5Pget_size(hid_t id, const char *name, size_t *size)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid property size");
if(H5I_GENPROP_LST == H5I_get_type(id)) {
- if(NULL == (plist = H5I_object(id)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list");
/* Check the property size */
@@ -798,7 +798,7 @@ H5Pget_size(hid_t id, const char *name, size_t *size)
} /* end if */
else
if(H5I_GENPROP_CLS == H5I_get_type(id)) {
- if(NULL == (pclass = H5I_object(id)))
+ if(NULL == (pclass = (H5P_genclass_t *)H5I_object(id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list");
/* Check the property size */
@@ -844,7 +844,7 @@ H5Pget_class(hid_t plist_id)
H5TRACE1("i", "i", plist_id);
/* Check arguments. */
- if(NULL == (plist = H5I_object_verify(plist_id, H5I_GENPROP_LST)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object_verify(plist_id, H5I_GENPROP_LST)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list");
/* Retrieve the property list class */
@@ -856,7 +856,7 @@ H5Pget_class(hid_t plist_id)
HGOTO_ERROR (H5E_PLIST, H5E_CANTINIT, FAIL,"Can't increment class ID ref count");
/* Get an atom for the class */
- if((ret_value = H5I_register(H5I_GENPROP_CLS, pclass)) < 0)
+ if((ret_value = H5I_register(H5I_GENPROP_CLS, pclass, TRUE)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "unable to atomize property list class");
done:
@@ -907,14 +907,14 @@ H5Pget_nprops(hid_t id, size_t *nprops)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid property nprops pointer");
if(H5I_GENPROP_LST == H5I_get_type(id)) {
- if(NULL == (plist = H5I_object(id)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list");
if(H5P_get_nprops_plist(plist, nprops) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "unable to query # of properties in plist");
} /* end if */
else
if(H5I_GENPROP_CLS == H5I_get_type(id)) {
- if(NULL == (pclass = H5I_object(id)))
+ if(NULL == (pclass = (H5P_genclass_t *)H5I_object(id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property class");
if(H5P_get_nprops_pclass(pclass, nprops, FALSE) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "unable to query # of properties in pclass");
@@ -967,12 +967,12 @@ H5Pequal(hid_t id1, hid_t id2)
/* Compare property lists */
if(H5I_GENPROP_LST == H5I_get_type(id1)) {
- if(H5P_cmp_plist(obj1, obj2) == 0)
+ if(H5P_cmp_plist((const H5P_genplist_t *)obj1, (const H5P_genplist_t *)obj2) == 0)
ret_value = TRUE;
} /* end if */
/* Must be property classes */
else {
- if(H5P_cmp_class(obj1, obj2) == 0)
+ if(H5P_cmp_class((const H5P_genclass_t *)obj1, (const H5P_genclass_t *)obj2) == 0)
ret_value = TRUE;
} /* end else */
@@ -1152,7 +1152,7 @@ H5Pget(hid_t plist_id, const char *name, void *value)
H5TRACE3("e", "i*s*x", plist_id, name, value);
/* Check arguments. */
- if(NULL == (plist = H5I_object_verify(plist_id, H5I_GENPROP_LST)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object_verify(plist_id, H5I_GENPROP_LST)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list");
if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid property name");
@@ -1204,7 +1204,7 @@ H5Premove(hid_t plist_id, const char *name)
H5TRACE2("e", "i*s", plist_id, name);
/* Check arguments. */
- if(NULL == (plist = H5I_object_verify(plist_id, H5I_GENPROP_LST)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object_verify(plist_id, H5I_GENPROP_LST)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list");
if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid property name");
@@ -1283,7 +1283,7 @@ H5Pcopy_prop(hid_t dst_id, hid_t src_id, const char *name)
} /* end if */
/* Must be property classes */
else {
- if(H5P_copy_prop_pclass(dst_obj, src_obj, name) < 0)
+ if(H5P_copy_prop_pclass((H5P_genclass_t *)dst_obj, (H5P_genclass_t *)src_obj, name) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "can't copy property between classes");
} /* end else */
@@ -1323,7 +1323,7 @@ H5Punregister(hid_t pclass_id, const char *name)
H5TRACE2("e", "i*s", pclass_id, name);
/* Check arguments. */
- if(NULL == (pclass = H5I_object_verify(pclass_id, H5I_GENPROP_CLS)))
+ if(NULL == (pclass = (H5P_genclass_t *)H5I_object_verify(pclass_id, H5I_GENPROP_CLS)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list class");
if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid property name");
@@ -1374,7 +1374,7 @@ H5Pclose(hid_t plist_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list");
/* Close the property list */
- if(H5I_dec_ref(plist_id) < 0)
+ if(H5I_dec_ref(plist_id, TRUE) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTFREE, FAIL, "can't close");
done:
@@ -1411,7 +1411,7 @@ H5Pget_class_name(hid_t pclass_id)
FUNC_ENTER_API(H5Pget_class_name, NULL);
/* Check arguments. */
- if(NULL == (pclass = H5I_object_verify(pclass_id, H5I_GENPROP_CLS)))
+ if(NULL == (pclass = (H5P_genclass_t *)H5I_object_verify(pclass_id, H5I_GENPROP_CLS)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a property class");
/* Get the property list class name */
@@ -1446,33 +1446,33 @@ hid_t
H5Pget_class_parent(hid_t pclass_id)
{
H5P_genclass_t *pclass; /* Property class to query */
- H5P_genclass_t *parent=NULL; /* Parent's property class */
+ H5P_genclass_t *parent = NULL; /* Parent's property class */
hid_t ret_value; /* return value */
- FUNC_ENTER_API(H5Pget_class_parent, FAIL);
+ FUNC_ENTER_API(H5Pget_class_parent, FAIL)
H5TRACE1("i", "i", pclass_id);
/* Check arguments. */
- if(NULL == (pclass = H5I_object_verify(pclass_id, H5I_GENPROP_CLS)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property class");
+ if(NULL == (pclass = (H5P_genclass_t *)H5I_object_verify(pclass_id, H5I_GENPROP_CLS)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property class")
/* Retrieve the property class's parent */
- if((parent = H5P_get_class_parent(pclass)) == NULL)
- HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "unable to query class of property list");
+ if(NULL == (parent = H5P_get_class_parent(pclass)))
+ HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "unable to query class of property list")
/* Increment the outstanding references to the class object */
if(H5P_access_class(parent, H5P_MOD_INC_REF) < 0)
- HGOTO_ERROR (H5E_PLIST, H5E_CANTINIT, FAIL,"Can't increment class ID ref count");
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL,"Can't increment class ID ref count")
/* Get an atom for the class */
- if((ret_value = H5I_register(H5I_GENPROP_CLS, parent)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "unable to atomize property list class");
+ if((ret_value = H5I_register(H5I_GENPROP_CLS, parent, TRUE)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "unable to atomize property list class")
done:
- if(ret_value<0 && parent)
+ if(ret_value < 0 && parent)
H5P_close_class(parent);
- FUNC_LEAVE_API(ret_value);
+ FUNC_LEAVE_API(ret_value)
} /* H5Pget_class_parent() */
@@ -1507,7 +1507,7 @@ H5Pclose_class(hid_t cls_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list class");
/* Close the property list class */
- if(H5I_dec_ref(cls_id) < 0)
+ if(H5I_dec_ref(cls_id, TRUE) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTFREE, FAIL, "can't close");
done:
diff --git a/src/H5Pdapl.c b/src/H5Pdapl.c
new file mode 100644
index 0000000..a4d036d
--- /dev/null
+++ b/src/H5Pdapl.c
@@ -0,0 +1,273 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5Pdapl.c
+ * October 27, 2008
+ * Neil Fortner <nfortne2@hdfgroup.org>
+ *
+ * Purpose: Dataset access property list class routines
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+#define H5P_PACKAGE /*suppress error about including H5Ppkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Dprivate.h" /* Datasets */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fprivate.h" /* Files */
+#include "H5Iprivate.h" /* IDs */
+#include "H5Ppkg.h" /* Property lists */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+/* ========= Dataset Access properties ============ */
+/* Definitions for size of raw data chunk cache(slots) */
+#define H5D_ACS_DATA_CACHE_NUM_SLOTS_SIZE sizeof(size_t)
+#define H5D_ACS_DATA_CACHE_NUM_SLOTS_DEF H5D_CHUNK_CACHE_NSLOTS_DEFAULT
+/* Definition for size of raw data chunk cache(bytes) */
+#define H5D_ACS_DATA_CACHE_BYTE_SIZE_SIZE sizeof(size_t)
+#define H5D_ACS_DATA_CACHE_BYTE_SIZE_DEF H5D_CHUNK_CACHE_NBYTES_DEFAULT
+/* Definition for preemption read chunks first */
+#define H5D_ACS_PREEMPT_READ_CHUNKS_SIZE sizeof(double)
+#define H5D_ACS_PREEMPT_READ_CHUNKS_DEF H5D_CHUNK_CACHE_W0_DEFAULT
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+/* Property class callbacks */
+static herr_t H5P_dacc_reg_prop(H5P_genclass_t *pclass);
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+/* Dataset access property list class library initialization object */
+const H5P_libclass_t H5P_CLS_DACC[1] = {{
+ "dataset access", /* Class name for debugging */
+ &H5P_CLS_LINK_ACCESS_g, /* Parent class ID */
+ &H5P_CLS_DATASET_ACCESS_g, /* Pointer to class ID */
+ &H5P_LST_DATASET_ACCESS_g, /* Pointer to default property list ID */
+ H5P_dacc_reg_prop, /* Default property registration routine */
+ NULL, /* Class creation callback */
+ NULL, /* Class creation callback info */
+ NULL, /* Class copy callback */
+ NULL, /* Class copy callback info */
+ NULL, /* Class close callback */
+ NULL /* Class close callback info */
+}};
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5P_dacc_reg_prop
+ *
+ * Purpose: Register the dataset access property list class's
+ * properties
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * October 27, 2008
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5P_dacc_reg_prop(H5P_genclass_t *pclass)
+{
+ size_t rdcc_nslots = H5D_ACS_DATA_CACHE_NUM_SLOTS_DEF; /* Default raw data chunk cache # of slots */
+ size_t rdcc_nbytes = H5D_ACS_DATA_CACHE_BYTE_SIZE_DEF; /* Default raw data chunk cache # of bytes */
+ double rdcc_w0 = H5D_ACS_PREEMPT_READ_CHUNKS_DEF; /* Default raw data chunk cache dirty ratio */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5P_dacc_reg_prop)
+
+ /* Register the size of raw data chunk cache (elements) */
+ if(H5P_register(pclass, H5D_ACS_DATA_CACHE_NUM_SLOTS_NAME, H5D_ACS_DATA_CACHE_NUM_SLOTS_SIZE, &rdcc_nslots, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+
+ /* Register the size of raw data chunk cache(bytes) */
+ if(H5P_register(pclass, H5D_ACS_DATA_CACHE_BYTE_SIZE_NAME, H5D_ACS_DATA_CACHE_BYTE_SIZE_SIZE, &rdcc_nbytes, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+
+ /* Register the preemption for reading chunks */
+ if(H5P_register(pclass, H5D_ACS_PREEMPT_READ_CHUNKS_NAME, H5D_ACS_PREEMPT_READ_CHUNKS_SIZE, &rdcc_w0, 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_dacc_reg_prop() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Pset_chunk_cache
+ *
+ * Purpose: Set the number of objects in the meta data cache and the
+ * maximum number of chunks and bytes in the raw data chunk cache.
+ * Once set, these values will override the values in the file access
+ * property list. Each of thhese values can be individually unset
+ * (or not set at all) by passing the macros:
+ * H5D_CHUNK_CACHE_NCHUNKS_DEFAULT,
+ * H5D_CHUNK_CACHE_NBYTES_DEFAULT, and/or
+ * H5D_CHUNK_CACHE_W0_DEFAULT
+ * as appropriate.
+ *
+ * The RDCC_W0 value should be between 0 and 1 inclusive and
+ * indicates how much chunks that have been fully read or fully
+ * written are favored for preemption. A value of zero means
+ * fully read or written chunks are treated no differently than
+ * other chunks (the preemption is strictly LRU) while a value
+ * of one means fully read chunks are always preempted before
+ * other chunks.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * Monday, October 27, 2008
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pset_chunk_cache(hid_t dapl_id, size_t rdcc_nslots, size_t rdcc_nbytes, double rdcc_w0)
+{
+ H5P_genplist_t *plist; /* Property list pointer */
+ herr_t ret_value = SUCCEED; /* return value */
+
+ FUNC_ENTER_API(H5Pset_chunk_cache, FAIL);
+ H5TRACE4("e", "izzd", dapl_id, rdcc_nslots, rdcc_nbytes, rdcc_w0);
+
+ /* Check arguments. Note that we allow negative values - they are
+ * considered to "unset" the property. */
+ if (rdcc_w0 > 1.0)
+ HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "raw data cache w0 value must be between 0.0 and 1.0 inclusive, or H5D_CHUNK_CACHE_W0_DEFAULT");
+
+ /* Get the plist structure */
+ if (NULL == (plist = H5P_object_verify(dapl_id,H5P_DATASET_ACCESS)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID");
+
+ /* Set sizes */
+ if (H5P_set(plist, H5D_ACS_DATA_CACHE_NUM_SLOTS_NAME, &rdcc_nslots) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET,FAIL, "can't set data cache number of chunks");
+ if (H5P_set(plist, H5D_ACS_DATA_CACHE_BYTE_SIZE_NAME, &rdcc_nbytes) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET,FAIL, "can't set data cache byte size");
+ if (H5P_set(plist, H5D_ACS_PREEMPT_READ_CHUNKS_NAME, &rdcc_w0) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET,FAIL, "can't set preempt read chunks");
+
+done:
+ FUNC_LEAVE_API(ret_value);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Pget_chunk_cache
+ *
+ * Purpose: Retrieves the maximum possible number of elements in the meta
+ * data cache and the maximum possible number of elements and
+ * bytes and the RDCC_W0 value in the raw data chunk cache. Any
+ * (or all) arguments may be null pointers in which case the
+ * corresponding datum is not returned. If these properties have
+ * not been set on this property list, the default values for a
+ * file access property list are returned.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * Monday, October 27, 2008
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pget_chunk_cache(hid_t dapl_id, size_t *rdcc_nslots, size_t *rdcc_nbytes, double *rdcc_w0)
+{
+ H5P_genplist_t *plist; /* Property list pointer */
+ H5P_genplist_t *def_plist; /* Default file access property list */
+ herr_t ret_value = SUCCEED; /* return value */
+
+ FUNC_ENTER_API(H5Pget_chunk_cache, FAIL);
+ H5TRACE4("e", "i*z*z*d", dapl_id, rdcc_nslots, rdcc_nbytes, rdcc_w0);
+
+ /* Get the plist structure */
+ if (NULL == (plist = H5P_object_verify(dapl_id, H5P_DATASET_ACCESS)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID");
+
+ /* Get default file access plist */
+ if (NULL == (def_plist = (H5P_genplist_t *)H5I_object(H5P_FILE_ACCESS_DEFAULT)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for default fapl ID");
+
+ /* Get the properties. If a property is set to the default value, the value
+ * from the default fapl is used. */
+ if (rdcc_nslots) {
+ if (H5P_get(plist, H5D_ACS_DATA_CACHE_NUM_SLOTS_NAME, rdcc_nslots) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET,FAIL, "can't get data cache number of slots");
+ if (*rdcc_nslots == H5D_CHUNK_CACHE_NSLOTS_DEFAULT)
+ if (H5P_get(def_plist, H5F_ACS_DATA_CACHE_NUM_SLOTS_NAME, rdcc_nslots) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET,FAIL, "can't get default data cache number of slots");
+ } /* end if */
+ if (rdcc_nbytes) {
+ if (H5P_get(plist, H5D_ACS_DATA_CACHE_BYTE_SIZE_NAME, rdcc_nbytes) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET,FAIL, "can't get data cache byte size");
+ if (*rdcc_nbytes == H5D_CHUNK_CACHE_NBYTES_DEFAULT)
+ if (H5P_get(def_plist, H5F_ACS_DATA_CACHE_BYTE_SIZE_NAME, rdcc_nbytes) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET,FAIL, "can't get default data cache byte size");
+ } /* end if */
+ if (rdcc_w0) {
+ if (H5P_get(plist, H5D_ACS_PREEMPT_READ_CHUNKS_NAME, rdcc_w0) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET,FAIL, "can't get preempt read chunks");
+ if (*rdcc_w0 < 0)
+ if (H5P_get(def_plist, H5F_ACS_PREEMPT_READ_CHUNKS_NAME, rdcc_w0) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET,FAIL, "can't get default preempt read chunks");
+ } /* end if */
+
+done:
+ FUNC_LEAVE_API(ret_value);
+}
diff --git a/src/H5Pdcpl.c b/src/H5Pdcpl.c
index 97323dc..c523544 100644
--- a/src/H5Pdcpl.c
+++ b/src/H5Pdcpl.c
@@ -55,7 +55,7 @@
#define H5D_CRT_CHUNK_DIM_SIZE sizeof(unsigned)
#define H5D_CRT_CHUNK_DIM_DEF 1
/* Definitions for chunk size */
-#define H5D_CRT_CHUNK_SIZE_SIZE sizeof(size_t[H5O_LAYOUT_NDIMS])
+#define H5D_CRT_CHUNK_SIZE_SIZE sizeof(uint32_t[H5O_LAYOUT_NDIMS])
#define H5D_CRT_CHUNK_SIZE_DEF {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,\
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
/* Definitions for fill value. size=0 means fill value will be 0 as
@@ -148,7 +148,7 @@ H5P_dcrt_reg_prop(H5P_genclass_t *pclass)
{
H5D_layout_t layout = H5D_CRT_LAYOUT_DEF; /* Default storage layout */
unsigned chunk_ndims = H5D_CRT_CHUNK_DIM_DEF; /* Default rank for chunks */
- size_t chunk_size[H5O_LAYOUT_NDIMS] = H5D_CRT_CHUNK_SIZE_DEF; /* Default chunk size */
+ uint32_t chunk_size[H5O_LAYOUT_NDIMS] = H5D_CRT_CHUNK_SIZE_DEF; /* Default chunk size */
H5O_fill_t fill = H5D_CRT_FILL_VALUE_DEF; /* Default fill value */
unsigned alloc_time_state = H5D_CRT_ALLOC_TIME_STATE_DEF; /* Default allocation time state */
H5O_efl_t efl = H5D_CRT_EXT_FILE_LIST_DEF; /* Default external file list */
@@ -222,9 +222,9 @@ H5P_dcrt_copy(hid_t dst_plist_id, hid_t src_plist_id, void UNUSED *copy_data)
FUNC_ENTER_NOAPI_NOINIT(H5P_dcrt_copy)
/* Verify property list IDs */
- if(NULL == (dst_plist = H5I_object(dst_plist_id)))
+ if(NULL == (dst_plist = (H5P_genplist_t *)H5I_object(dst_plist_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list")
- if(NULL == (src_plist = H5I_object(src_plist_id)))
+ if(NULL == (src_plist = (H5P_genplist_t *)H5I_object(src_plist_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list")
/* Get the fill value, external file list, and data pipeline properties
@@ -253,7 +253,7 @@ H5P_dcrt_copy(hid_t dst_plist_id, hid_t src_plist_id, void UNUSED *copy_data)
{
dst_efl.slot[i].name_offset = 0;
}
-
+
}
@@ -302,7 +302,7 @@ H5P_dcrt_close(hid_t dcpl_id, void UNUSED *close_data)
FUNC_ENTER_NOAPI_NOINIT(H5P_dcrt_close)
/* Check arguments */
- if(NULL == (plist = H5I_object(dcpl_id)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(dcpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list")
/* Get the fill value, external file list, and data pipeline properties
@@ -645,7 +645,7 @@ herr_t
H5Pset_layout(hid_t plist_id, H5D_layout_t layout)
{
H5P_genplist_t *plist; /* Property list pointer */
- herr_t ret_value=SUCCEED; /* return value */
+ herr_t ret_value = SUCCEED; /* return value */
FUNC_ENTER_API(H5Pset_layout, FAIL)
H5TRACE2("e", "iDl", plist_id, layout);
@@ -655,7 +655,7 @@ H5Pset_layout(hid_t plist_id, H5D_layout_t layout)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "raw data layout method is not valid")
/* Get the plist structure */
- if(NULL == (plist = H5P_object_verify(plist_id,H5P_DATASET_CREATE)))
+ if(NULL == (plist = H5P_object_verify(plist_id, H5P_DATASET_CREATE)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
/* Set value */
@@ -692,13 +692,13 @@ H5D_layout_t
H5Pget_layout(hid_t plist_id)
{
H5P_genplist_t *plist; /* Property list pointer */
- H5D_layout_t ret_value=H5D_LAYOUT_ERROR;
+ H5D_layout_t ret_value = H5D_LAYOUT_ERROR;
FUNC_ENTER_API(H5Pget_layout, H5D_LAYOUT_ERROR)
H5TRACE1("Dl", "i", plist_id);
/* Get the plist structure */
- if(NULL == (plist = H5P_object_verify(plist_id,H5P_DATASET_CREATE)))
+ if(NULL == (plist = H5P_object_verify(plist_id, H5P_DATASET_CREATE)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, H5D_LAYOUT_ERROR, "can't find object for ID")
/* Get value */
@@ -737,37 +737,43 @@ done:
herr_t
H5Pset_chunk(hid_t plist_id, int ndims, const hsize_t dim[/*ndims*/])
{
- int i;
- size_t real_dims[H5O_LAYOUT_NDIMS]; /* Full-sized array to hold chunk dims */
H5P_genplist_t *plist; /* Property list pointer */
- herr_t ret_value=SUCCEED; /* return value */
+ uint32_t real_dims[H5O_LAYOUT_NDIMS]; /* Full-sized array to hold chunk dims */
+ uint64_t chunk_nelmts; /* Number of elements in chunk */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(H5Pset_chunk, FAIL)
H5TRACE3("e", "iIs*[a1]h", plist_id, ndims, dim);
/* Check arguments */
- if (ndims <= 0)
+ if(ndims <= 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "chunk dimensionality must be positive")
- if (ndims > H5S_MAX_RANK)
+ if(ndims > H5S_MAX_RANK)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "chunk dimensionality is too large")
- if (!dim)
+ if(!dim)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no chunk dimensions specified")
- /* Get the plist structure */
- if(NULL == (plist = H5P_object_verify(plist_id,H5P_DATASET_CREATE)))
- HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
-
- /* Initialize chunk dims to 0s */
- HDmemset(real_dims,0,sizeof(real_dims));
- for (i=0; i<ndims; i++) {
- if (dim[i] == 0)
+ /* Verify & initialize internal chunk dims */
+ HDmemset(real_dims, 0, sizeof(real_dims));
+ chunk_nelmts = 1;
+ for(u = 0; u < (unsigned)ndims; u++) {
+ if(dim[u] == 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "all chunk dimensions must be positive")
- if (dim[i] != (dim[i]&0xffffffff))
+ if(dim[u] != (dim[u] & 0xffffffff))
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "all chunk dimensions must be less than 2^32")
- real_dims[i]=(size_t)dim[i]; /* Store user's chunk dimensions */
+ chunk_nelmts *= dim[u];
+ if(chunk_nelmts > (uint64_t)0xffffffff)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "number of elements in chunk must be < 4GB")
+ real_dims[u] = (uint32_t)dim[u]; /* Store user's chunk dimensions */
} /* end for */
- if(H5P_set_layout (plist, H5D_CHUNKED) < 0)
+ /* Get the plist structure */
+ if(NULL == (plist = H5P_object_verify(plist_id, H5P_DATASET_CREATE)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
+
+ /* Set chunk information in property list */
+ if(H5P_set_layout(plist, H5D_CHUNKED) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set layout")
if(H5P_set(plist, H5D_CRT_CHUNK_DIM_NAME, &ndims) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set chunk dimensionanlity")
@@ -776,7 +782,7 @@ H5Pset_chunk(hid_t plist_id, int ndims, const hsize_t dim[/*ndims*/])
done:
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5Pset_chunk() */
/*-------------------------------------------------------------------------
@@ -815,7 +821,7 @@ H5Pget_chunk(hid_t plist_id, int max_ndims, hsize_t dim[]/*out*/)
H5TRACE3("Is", "iIsx", plist_id, max_ndims, dim);
/* Get the plist structure */
- if(NULL == (plist = H5P_object_verify(plist_id,H5P_DATASET_CREATE)))
+ if(NULL == (plist = H5P_object_verify(plist_id, H5P_DATASET_CREATE)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
if(H5P_get(plist, H5D_CRT_LAYOUT_NAME, &layout) < 0)
@@ -828,22 +834,22 @@ H5Pget_chunk(hid_t plist_id, int max_ndims, hsize_t dim[]/*out*/)
if(dim) {
int i;
- size_t chunk_size[H5O_LAYOUT_NDIMS];
+ uint32_t chunk_size[H5O_LAYOUT_NDIMS];
if(H5P_get(plist, H5D_CRT_CHUNK_SIZE_NAME, chunk_size) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get chunk size")
/* Get the dimension sizes */
- for (i=0; i<ndims && i<max_ndims; i++)
+ for(i = 0; i < ndims && i < max_ndims; i++)
dim[i] = chunk_size[i];
} /* end if */
/* Set the return value */
- ret_value=ndims;
+ ret_value = ndims;
done:
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5Pget_chunk() */
/*-------------------------------------------------------------------------
@@ -883,7 +889,7 @@ H5Pset_external(hid_t plist_id, const char *name, off_t offset, hsize_t size)
hsize_t total, tmp;
H5O_efl_t efl;
H5P_genplist_t *plist; /* Property list pointer */
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(H5Pset_external, FAIL)
H5TRACE4("e", "i*soh", plist_id, name, offset, size);
@@ -897,7 +903,7 @@ H5Pset_external(hid_t plist_id, const char *name, off_t offset, hsize_t size)
HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "zero size")
/* Get the plist structure */
- if(NULL == (plist = H5P_object_verify(plist_id,H5P_DATASET_CREATE)))
+ if(NULL == (plist = H5P_object_verify(plist_id, H5P_DATASET_CREATE)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
if(H5P_get(plist, H5D_CRT_EXT_FILE_LIST_NAME, &efl) < 0)
@@ -915,15 +921,15 @@ H5Pset_external(hid_t plist_id, const char *name, off_t offset, hsize_t size)
/* Add to the list */
- if (efl.nused >= efl.nalloc) {
+ if(efl.nused >= efl.nalloc) {
size_t na = efl.nalloc + H5O_EFL_ALLOC;
- H5O_efl_entry_t *x = H5MM_realloc (efl.slot, na*sizeof(H5O_efl_entry_t));
+ H5O_efl_entry_t *x = (H5O_efl_entry_t *)H5MM_realloc(efl.slot, na * sizeof(H5O_efl_entry_t));
- if (!x)
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ if(!x)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
efl.nalloc = na;
efl.slot = x;
- }
+ } /* end if */
idx = efl.nused;
efl.slot[idx].name_offset = 0; /*not entered into heap yet*/
efl.slot[idx].name = H5MM_xstrdup (name);
@@ -971,7 +977,7 @@ H5Pget_external_count(hid_t plist_id)
H5TRACE1("Is", "i", plist_id);
/* Get the plist structure */
- if(NULL == (plist = H5P_object_verify(plist_id,H5P_DATASET_CREATE)))
+ if(NULL == (plist = H5P_object_verify(plist_id, H5P_DATASET_CREATE)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
/* Get value */
@@ -979,11 +985,11 @@ H5Pget_external_count(hid_t plist_id)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get external file list")
/* Set return value */
- ret_value=(int)efl.nused;
+ ret_value = (int)efl.nused;
done:
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5Pget_external_count() */
/*-------------------------------------------------------------------------
@@ -1023,33 +1029,33 @@ H5Pget_external(hid_t plist_id, unsigned idx, size_t name_size, char *name/*out*
{
H5O_efl_t efl;
H5P_genplist_t *plist; /* Property list pointer */
- herr_t ret_value=SUCCEED; /* return value */
+ herr_t ret_value = SUCCEED; /* return value */
FUNC_ENTER_API(H5Pget_external, FAIL)
H5TRACE6("e", "iIuzxxx", plist_id, idx, name_size, name, offset, size);
/* Get the plist structure */
- if(NULL == (plist = H5P_object_verify(plist_id,H5P_DATASET_CREATE)))
+ if(NULL == (plist = H5P_object_verify(plist_id, H5P_DATASET_CREATE)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
/* Get value */
if(H5P_get(plist, H5D_CRT_EXT_FILE_LIST_NAME, &efl) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get external file list")
- if (idx>=efl.nused)
- HGOTO_ERROR (H5E_ARGS, H5E_BADRANGE, FAIL, "external file index is out of range")
+ if(idx >= efl.nused)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "external file index is out of range")
/* Return values */
- if (name_size>0 && name)
- HDstrncpy (name, efl.slot[idx].name, name_size);
- if (offset)
+ if(name_size>0 && name)
+ HDstrncpy(name, efl.slot[idx].name, name_size);
+ if(offset)
*offset = efl.slot[idx].offset;
- if (size)
+ if(size)
*size = efl.slot[idx].size;
done:
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5Pget_external() */
/*-------------------------------------------------------------------------
@@ -1171,7 +1177,7 @@ H5Pmodify_filter(hid_t plist_id, H5Z_filter_t filter, unsigned int flags,
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no client data values supplied")
/* Get the plist structure */
- if(NULL == (plist = H5P_object_verify(plist_id,H5P_DATASET_CREATE)))
+ if(NULL == (plist = H5P_object_verify(plist_id, H5P_DATASET_CREATE)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
/* Modify the filter parameters of the I/O pipeline */
@@ -1246,7 +1252,7 @@ H5Pset_filter(hid_t plist_id, H5Z_filter_t filter, unsigned int flags,
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no client data values supplied")
/* Get the plist structure */
- if(NULL == (plist = H5P_object_verify(plist_id,H5P_DATASET_CREATE)))
+ if(NULL == (plist = H5P_object_verify(plist_id, H5P_DATASET_CREATE)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
/* Get the pipeline property to append to */
@@ -1856,7 +1862,7 @@ H5Pset_shuffle(hid_t plist_id)
HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list")
/* Get the plist structure */
- if(NULL == (plist = H5I_object(plist_id)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(plist_id)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
/* Add the filter */
@@ -1902,7 +1908,7 @@ H5Pset_nbit(hid_t plist_id)
HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list")
/* Get the plist structure */
- if(NULL == (plist = H5I_object(plist_id)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(plist_id)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
/* Add the nbit filter */
@@ -1968,7 +1974,7 @@ H5Pset_scaleoffset(hid_t plist_id, H5Z_SO_scale_type_t scale_type, int scale_fac
HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "invalid scale type")
/* Get the plist structure */
- if(NULL == (plist = H5I_object(plist_id)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(plist_id)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
/* Set parameters for the filter
@@ -2028,7 +2034,7 @@ H5Pset_fletcher32(hid_t plist_id)
if(H5P_get(plist, H5D_CRT_DATA_PIPELINE_NAME, &pline) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get pipeline")
if(H5Z_append(&pline, H5Z_FILTER_FLETCHER32, H5Z_FLAG_MANDATORY, (size_t)0, NULL) < 0)
- HGOTO_ERROR(H5E_PLINE, H5E_CANTINIT, FAIL, "unable to add deflate filter to pipeline")
+ HGOTO_ERROR(H5E_PLINE, H5E_CANTINIT, FAIL, "unable to add fletcher32 filter to pipeline")
if(H5P_set(plist, H5D_CRT_DATA_PIPELINE_NAME, &pline) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_CANTINIT, FAIL, "unable to set pipeline")
@@ -2087,12 +2093,12 @@ H5Pset_fill_value(hid_t plist_id, hid_t type_id, const void *value)
H5T_path_t *tpath; /* Conversion information */
/* Retrieve pointer to datatype */
- if(NULL == (type = H5I_object_verify(type_id, H5I_DATATYPE)))
+ if(NULL == (type = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
/* Set the fill value */
if(NULL == (fill.type = H5T_copy(type, H5T_COPY_TRANSIENT)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy datatype")
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "can't copy datatype")
fill.size = H5T_get_size(type);
if(NULL == (fill.buf = H5MM_malloc((size_t)fill.size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "memory allocation failed for fill value")
@@ -2113,13 +2119,13 @@ H5Pset_fill_value(hid_t plist_id, hid_t type_id, const void *value)
/* Convert the fill value */
if(H5T_convert(tpath, type_id, type_id, (size_t)1, (size_t)0, (size_t)0, fill.buf, bkg_buf, H5AC_ind_dxpl_id) < 0) {
if(bkg_buf)
- H5FL_BLK_FREE(type_conv, bkg_buf);
+ (void)H5FL_BLK_FREE(type_conv, bkg_buf);
HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "datatype conversion failed")
} /* end if */
/* Release the background buffer */
if(bkg_buf)
- H5FL_BLK_FREE(type_conv, bkg_buf);
+ (void)H5FL_BLK_FREE(type_conv, bkg_buf);
} /* end if */
} /* end if */
else
@@ -2186,7 +2192,7 @@ H5P_get_fill_value(H5P_genplist_t *plist, const H5T_t *type, void *value/*out*/,
*/
if(NULL == (tpath = H5T_path_find(fill.type, type, NULL, NULL, dxpl_id, FALSE)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert between src and dst datatypes")
- if((src_id = H5I_register(H5I_DATATYPE, H5T_copy(fill.type, H5T_COPY_TRANSIENT))) < 0)
+ if((src_id = H5I_register(H5I_DATATYPE, H5T_copy(fill.type, H5T_COPY_TRANSIENT), FALSE)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy/register datatype")
/*
@@ -2208,7 +2214,7 @@ H5P_get_fill_value(H5P_genplist_t *plist, const H5T_t *type, void *value/*out*/,
HDmemcpy(buf, fill.buf, H5T_get_size(fill.type));
/* Do the conversion */
- if((dst_id = H5I_register(H5I_DATATYPE, H5T_copy(type, H5T_COPY_TRANSIENT))) < 0)
+ if((dst_id = H5I_register(H5I_DATATYPE, H5T_copy(type, H5T_COPY_TRANSIENT), FALSE)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy/register datatype")
if(H5T_convert(tpath, src_id, dst_id, (size_t)1, (size_t)0, (size_t)0, buf, bkg, dxpl_id) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "datatype conversion failed")
@@ -2221,9 +2227,9 @@ done:
if(bkg != value)
H5MM_xfree(bkg);
if(src_id >= 0)
- H5I_dec_ref(src_id);
+ H5I_dec_ref(src_id, FALSE);
if(dst_id >= 0)
- H5I_dec_ref(dst_id);
+ H5I_dec_ref(dst_id, FALSE);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5P_get_fill_value() */
@@ -2256,7 +2262,7 @@ H5Pget_fill_value(hid_t plist_id, hid_t type_id, void *value/*out*/)
H5TRACE3("e", "iix", plist_id, type_id, value);
/* Check arguments */
- if(NULL == (type = H5I_object_verify(type_id, H5I_DATATYPE)))
+ if(NULL == (type = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
if(!value)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,"no fill value output buffer")
@@ -2722,8 +2728,6 @@ H5Pget_filter_by_id1(hid_t plist_id, H5Z_filter_t id, unsigned int *flags/*out*/
size_t *cd_nelmts/*in_out*/, unsigned cd_values[]/*out*/,
size_t namelen, char name[]/*out*/)
{
- H5O_pline_t pline; /* Filter pipeline */
- H5Z_filter_info_t *filter; /* Pointer to filter information */
H5P_genplist_t *plist; /* Property list pointer */
herr_t ret_value = SUCCEED; /* Return value */
diff --git a/src/H5Pdeprec.c b/src/H5Pdeprec.c
index 1234735..208fcb2 100644
--- a/src/H5Pdeprec.c
+++ b/src/H5Pdeprec.c
@@ -257,7 +257,7 @@ H5Pregister1(hid_t cls_id, const char *name, size_t size, void *def_value,
prp_set, prp_get, prp_delete, prp_copy, prp_close);
/* Check arguments. */
- if(NULL == (pclass = H5I_object_verify(cls_id, H5I_GENPROP_CLS)))
+ if(NULL == (pclass = (H5P_genclass_t *)H5I_object_verify(cls_id, H5I_GENPROP_CLS)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list class");
if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid class name");
@@ -426,7 +426,7 @@ H5Pinsert1(hid_t plist_id, const char *name, size_t size, void *value,
prp_delete, prp_copy, prp_close);
/* Check arguments. */
- if(NULL == (plist = H5I_object_verify(plist_id, H5I_GENPROP_LST)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object_verify(plist_id, H5I_GENPROP_LST)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid property name")
diff --git a/src/H5Pdxpl.c b/src/H5Pdxpl.c
index 6affcad..efbdfe7 100644
--- a/src/H5Pdxpl.c
+++ b/src/H5Pdxpl.c
@@ -90,9 +90,6 @@
/* Definitions for I/O transfer mode property */
#define H5D_XFER_IO_XFER_MODE_SIZE sizeof(H5FD_mpio_xfer_t)
#define H5D_XFER_IO_XFER_MODE_DEF H5FD_MPIO_INDEPENDENT
-/* Definitions for I/O optimization transfer mode property(using MPI-IO independent IO with file set view) */
-#define H5D_XFER_IO_XFER_OPT_MODE_SIZE sizeof(H5FD_mpio_collective_opt_t)
-#define H5D_XFER_IO_XFER_OPT_MODE_DEF H5FD_MPIO_COLLECTIVE_IO
/* Definitions for optimization of MPI-IO transfer mode property */
#define H5D_XFER_MPIO_COLLECTIVE_OPT_SIZE sizeof(H5FD_mpio_collective_opt_t)
#define H5D_XFER_MPIO_COLLECTIVE_OPT_DEF H5FD_MPIO_COLLECTIVE_IO
@@ -199,7 +196,6 @@ H5P_dxfr_reg_prop(H5P_genclass_t *pclass)
size_t def_hyp_vec_size = H5D_XFER_HYPER_VECTOR_SIZE_DEF; /* Default value for vector size */
#ifdef H5_HAVE_PARALLEL
H5FD_mpio_xfer_t def_io_xfer_mode = H5D_XFER_IO_XFER_MODE_DEF; /* Default value for I/O transfer mode */
- H5FD_mpio_collective_opt_t def_io_xfer_opt_mode = H5D_XFER_IO_XFER_OPT_MODE_DEF;
H5FD_mpio_chunk_opt_t def_mpio_chunk_opt_mode = H5D_XFER_MPIO_CHUNK_OPT_HARD_DEF;
H5FD_mpio_collective_opt_t def_mpio_collective_opt_mode = H5D_XFER_MPIO_COLLECTIVE_OPT_DEF;
unsigned def_mpio_chunk_opt_num = H5D_XFER_MPIO_CHUNK_OPT_NUM_DEF;
@@ -265,8 +261,6 @@ H5P_dxfr_reg_prop(H5P_genclass_t *pclass)
/* Register the I/O transfer mode property */
if(H5P_register(pclass, H5D_XFER_IO_XFER_MODE_NAME, H5D_XFER_IO_XFER_MODE_SIZE, &def_io_xfer_mode, 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, H5D_XFER_IO_XFER_OPT_MODE_NAME, H5D_XFER_IO_XFER_OPT_MODE_SIZE, &def_io_xfer_opt_mode, 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, H5D_XFER_MPIO_COLLECTIVE_OPT_NAME, H5D_XFER_MPIO_COLLECTIVE_OPT_SIZE, &def_mpio_collective_opt_mode, 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, H5D_XFER_MPIO_CHUNK_OPT_HARD_NAME, H5D_XFER_MPIO_CHUNK_OPT_HARD_SIZE, &def_mpio_chunk_opt_mode, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0)
@@ -329,7 +323,7 @@ H5P_dxfr_create(hid_t dxpl_id, void UNUSED *create_data)
FUNC_ENTER_NOAPI_NOINIT(H5P_dxfr_create)
/* Check arguments */
- if(NULL == (plist = H5I_object(dxpl_id)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list")
/* Get the driver information */
@@ -378,9 +372,9 @@ H5P_dxfr_copy(hid_t dst_dxpl_id, hid_t src_dxpl_id, void UNUSED *copy_data)
FUNC_ENTER_NOAPI_NOINIT(H5P_dxfr_copy)
- if(NULL == (dst_plist = H5I_object(dst_dxpl_id)))
+ if(NULL == (dst_plist = (H5P_genplist_t *)H5I_object(dst_dxpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list")
- if(NULL == (src_plist = H5I_object(src_dxpl_id)))
+ if(NULL == (src_plist = (H5P_genplist_t *)H5I_object(src_dxpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list")
/* Get values from old property list */
@@ -430,7 +424,7 @@ H5P_dxfr_close(hid_t dxpl_id, void UNUSED *close_data)
FUNC_ENTER_NOAPI_NOINIT(H5P_dxfr_close)
/* Check arguments */
- if(NULL == (plist = H5I_object(dxpl_id)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list")
if(H5P_get(plist, H5D_XFER_VFL_ID_NAME, &driver_id) < 0)
@@ -578,7 +572,7 @@ H5Pset_data_transform(hid_t plist_id, const char *expression)
/* See if a data transform is already set, and free it if it is */
if(H5P_get(plist, H5D_XFER_XFORM_NAME, &data_xform_prop) >= 0)
H5Z_xform_destroy(data_xform_prop);
-
+
/* Create data transform info from expression */
if(NULL == (data_xform_prop = H5Z_xform_create(expression)))
HGOTO_ERROR(H5E_PLINE, H5E_NOSPACE, FAIL, "unable to create data transform info")
diff --git a/src/H5Pfapl.c b/src/H5Pfapl.c
index 81dba0c..c51f750 100644
--- a/src/H5Pfapl.c
+++ b/src/H5Pfapl.c
@@ -57,9 +57,9 @@
/* Definitions for the initial metadata cache resize configuration */
#define H5F_ACS_META_CACHE_INIT_CONFIG_SIZE sizeof(H5AC_cache_config_t)
#define H5F_ACS_META_CACHE_INIT_CONFIG_DEF H5AC__DEFAULT_CACHE_CONFIG
-/* Definitions for size of raw data chunk cache(elements) */
-#define H5F_ACS_DATA_CACHE_ELMT_SIZE_SIZE sizeof(size_t)
-#define H5F_ACS_DATA_CACHE_ELMT_SIZE_DEF 521
+/* Definitions for size of raw data chunk cache(slots) */
+#define H5F_ACS_DATA_CACHE_NUM_SLOTS_SIZE sizeof(size_t)
+#define H5F_ACS_DATA_CACHE_NUM_SLOTS_DEF 521
/* Definition for size of raw data chunk cache(bytes) */
#define H5F_ACS_DATA_CACHE_BYTE_SIZE_SIZE sizeof(size_t)
#define H5F_ACS_DATA_CACHE_BYTE_SIZE_DEF (1024*1024)
@@ -187,7 +187,7 @@ static herr_t
H5P_facc_reg_prop(H5P_genclass_t *pclass)
{
H5AC_cache_config_t mdc_initCacheCfg = H5F_ACS_META_CACHE_INIT_CONFIG_DEF; /* Default metadata cache settings */
- size_t rdcc_nelmts = H5F_ACS_DATA_CACHE_ELMT_SIZE_DEF; /* Default raw data chunk cache # of elements */
+ size_t rdcc_nslots = H5F_ACS_DATA_CACHE_NUM_SLOTS_DEF; /* Default raw data chunk cache # of slots */
size_t rdcc_nbytes = H5F_ACS_DATA_CACHE_BYTE_SIZE_DEF; /* Default raw data chunk cache # of bytes */
double rdcc_w0 = H5F_ACS_PREEMPT_READ_CHUNKS_DEF; /* Default raw data chunk cache dirty ratio */
hsize_t threshold = H5F_ACS_ALIGN_THRHD_DEF; /* Default allocation alignment threshold */
@@ -213,7 +213,7 @@ H5P_facc_reg_prop(H5P_genclass_t *pclass)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
/* Register the size of raw data chunk cache (elements) */
- if(H5P_register(pclass, H5F_ACS_DATA_CACHE_ELMT_SIZE_NAME, H5F_ACS_DATA_CACHE_ELMT_SIZE_SIZE, &rdcc_nelmts, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0)
+ if(H5P_register(pclass, H5F_ACS_DATA_CACHE_NUM_SLOTS_NAME, H5F_ACS_DATA_CACHE_NUM_SLOTS_SIZE, &rdcc_nslots, NULL, NULL, NULL, NULL, NULL, NULL, NULL) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
/* Register the size of raw data chunk cache(bytes) */
@@ -312,7 +312,7 @@ H5P_facc_create(hid_t fapl_id, void UNUSED *copy_data)
FUNC_ENTER_NOAPI_NOINIT(H5P_facc_create)
/* Check argument */
- if(NULL == (plist = H5I_object(fapl_id)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
/* Retrieve driver ID property */
@@ -362,7 +362,7 @@ H5P_facc_copy(hid_t dst_fapl_id, hid_t src_fapl_id, void UNUSED *copy_data)
FUNC_ENTER_NOAPI_NOINIT(H5P_facc_copy)
/* Get driver ID from source property list */
- if(NULL == (src_plist = H5I_object(src_fapl_id)))
+ if(NULL == (src_plist = (H5P_genplist_t *)H5I_object(src_fapl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list")
if(H5P_get(src_plist, H5F_ACS_FILE_DRV_ID_NAME, &driver_id) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get driver ID")
@@ -376,7 +376,7 @@ H5P_facc_copy(hid_t dst_fapl_id, hid_t src_fapl_id, void UNUSED *copy_data)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get driver info")
/* Set the driver for the destination property list */
- if(NULL == (dst_plist = H5I_object(dst_fapl_id)))
+ if(NULL == (dst_plist = (H5P_genplist_t *)H5I_object(dst_fapl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list")
if(H5FD_fapl_open(dst_plist, driver_id, driver_info) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set driver")
@@ -413,7 +413,7 @@ H5P_facc_close(hid_t fapl_id, void UNUSED *close_data)
FUNC_ENTER_NOAPI(H5P_facc_close, FAIL)
/* Check argument */
- if(NULL == (plist = H5I_object(fapl_id)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
/* Get driver ID property */
@@ -577,17 +577,17 @@ H5P_set_driver(H5P_genplist_t *plist, hid_t new_driver_id, const void *new_drive
void *driver_info; /* VFL driver info */
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5P_set_driver, FAIL);
+ FUNC_ENTER_NOAPI(H5P_set_driver, FAIL)
- if (NULL==H5I_object_verify(new_driver_id, H5I_VFL))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file driver ID");
+ if(NULL == H5I_object_verify(new_driver_id, H5I_VFL))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file driver ID")
- if( TRUE == H5P_isa_class(plist->plist_id, H5P_FILE_ACCESS) ) {
+ if(TRUE == H5P_isa_class(plist->plist_id, H5P_FILE_ACCESS)) {
/* Get the current driver information */
if(H5P_get(plist, H5F_ACS_FILE_DRV_ID_NAME, &driver_id) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get driver ID");
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get driver ID")
if(H5P_get(plist, H5F_ACS_FILE_DRV_INFO_NAME, &driver_info) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET,FAIL,"can't get driver info");
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET,FAIL,"can't get driver info")
/* Close the driver for the property list */
if(H5FD_fapl_close(driver_id, driver_info)<0)
@@ -596,26 +596,26 @@ H5P_set_driver(H5P_genplist_t *plist, hid_t new_driver_id, const void *new_drive
/* Set the driver for the property list */
if(H5FD_fapl_open(plist, new_driver_id, new_driver_info)<0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set driver")
- } else if( TRUE == H5P_isa_class(plist->plist_id, H5P_DATASET_XFER) ) {
+ } else if(TRUE == H5P_isa_class(plist->plist_id, H5P_DATASET_XFER)) {
/* Get the current driver information */
- if(H5P_get(plist, H5D_XFER_VFL_ID_NAME, &driver_id)<0)
- HGOTO_ERROR (H5E_PLIST, H5E_CANTGET, FAIL, "can't retrieve VFL driver ID");
- if(H5P_get(plist, H5D_XFER_VFL_INFO_NAME, &driver_info)<0)
- HGOTO_ERROR (H5E_PLIST, H5E_CANTGET, FAIL, "can't retrieve VFL driver info");
+ if(H5P_get(plist, H5D_XFER_VFL_ID_NAME, &driver_id) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't retrieve VFL driver ID")
+ if(H5P_get(plist, H5D_XFER_VFL_INFO_NAME, &driver_info) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't retrieve VFL driver info")
/* Close the driver for the property list */
- if(H5FD_dxpl_close(driver_id, driver_info)<0)
+ if(H5FD_dxpl_close(driver_id, driver_info) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't reset driver")
/* Set the driver for the property list */
- if(H5FD_dxpl_open(plist, new_driver_id, new_driver_info)<0)
+ if(H5FD_dxpl_open(plist, new_driver_id, new_driver_info) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set driver")
} else {
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access or data transfer property list");
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access or data transfer property list")
}
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5P_set_driver() */
@@ -650,23 +650,23 @@ herr_t
H5Pset_driver(hid_t plist_id, hid_t new_driver_id, const void *new_driver_info)
{
H5P_genplist_t *plist; /* Property list pointer */
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_API(H5Pset_driver, FAIL);
+ FUNC_ENTER_API(H5Pset_driver, FAIL)
H5TRACE3("e", "ii*x", plist_id, new_driver_id, new_driver_info);
/* Check arguments */
- if(NULL == (plist = H5I_object_verify(plist_id, H5I_GENPROP_LST)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list");
- if (NULL==H5I_object_verify(new_driver_id, H5I_VFL))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file driver ID");
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object_verify(plist_id, H5I_GENPROP_LST)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
+ if(NULL == H5I_object_verify(new_driver_id, H5I_VFL))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file driver ID")
/* Set the driver */
- if(H5P_set_driver(plist,new_driver_id,new_driver_info)<0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set driver info");
+ if(H5P_set_driver(plist, new_driver_id, new_driver_info) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set driver info")
done:
- FUNC_LEAVE_API(ret_value);
+ FUNC_LEAVE_API(ret_value)
} /* end H5Pset_driver() */
@@ -763,17 +763,17 @@ H5Pget_driver(hid_t plist_id)
H5P_genplist_t *plist; /* Property list pointer */
hid_t ret_value; /* Return value */
- FUNC_ENTER_API(H5Pget_driver, FAIL);
+ FUNC_ENTER_API(H5Pget_driver, FAIL)
H5TRACE1("i", "i", plist_id);
- if(NULL == (plist = H5I_object_verify(plist_id, H5I_GENPROP_LST)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list");
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object_verify(plist_id, H5I_GENPROP_LST)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
ret_value = H5P_get_driver(plist);
done:
- FUNC_LEAVE_API(ret_value);
-}
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Pget_driver() */
/*-------------------------------------------------------------------------
@@ -859,14 +859,14 @@ H5Pget_driver_info(hid_t plist_id)
FUNC_ENTER_API(H5Pget_driver_info, NULL);
- if(NULL == (plist = H5I_object_verify(plist_id, H5I_GENPROP_LST)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a property list");
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object_verify(plist_id, H5I_GENPROP_LST)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a property list")
- if((ret_value=H5P_get_driver_info(plist))==NULL)
- HGOTO_ERROR(H5E_PLIST,H5E_CANTGET,NULL,"can't get driver info");
+ if(NULL == (ret_value = H5P_get_driver_info(plist)))
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get driver info")
done:
- FUNC_LEAVE_API(ret_value);
+ FUNC_LEAVE_API(ret_value)
} /* end H5Pget_driver_info() */
@@ -1213,13 +1213,13 @@ done:
*/
herr_t
H5Pset_cache(hid_t plist_id, int UNUSED mdc_nelmts,
- size_t rdcc_nelmts, size_t rdcc_nbytes, double rdcc_w0)
+ size_t rdcc_nslots, size_t rdcc_nbytes, double rdcc_w0)
{
H5P_genplist_t *plist; /* Property list pointer */
herr_t ret_value=SUCCEED; /* return value */
FUNC_ENTER_API(H5Pset_cache, FAIL);
- H5TRACE5("e", "iIszzd", plist_id, mdc_nelmts, rdcc_nelmts, rdcc_nbytes,
+ H5TRACE5("e", "iIszzd", plist_id, mdc_nelmts, rdcc_nslots, rdcc_nbytes,
rdcc_w0);
/* Check arguments */
@@ -1231,8 +1231,8 @@ H5Pset_cache(hid_t plist_id, int UNUSED mdc_nelmts,
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID");
/* Set sizes */
- if(H5P_set(plist, H5F_ACS_DATA_CACHE_ELMT_SIZE_NAME, &rdcc_nelmts) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET,FAIL, "can't set data cache element size");
+ if(H5P_set(plist, H5F_ACS_DATA_CACHE_NUM_SLOTS_NAME, &rdcc_nslots) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET,FAIL, "can't set data cache number of slots");
if(H5P_set(plist, H5F_ACS_DATA_CACHE_BYTE_SIZE_NAME, &rdcc_nbytes) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET,FAIL, "can't set data cache byte size");
if(H5P_set(plist, H5F_ACS_PREEMPT_READ_CHUNKS_NAME, &rdcc_w0) < 0)
@@ -1273,13 +1273,13 @@ done:
*/
herr_t
H5Pget_cache(hid_t plist_id, int *mdc_nelmts,
- size_t *rdcc_nelmts, size_t *rdcc_nbytes, double *rdcc_w0)
+ size_t *rdcc_nslots, size_t *rdcc_nbytes, double *rdcc_w0)
{
H5P_genplist_t *plist; /* Property list pointer */
herr_t ret_value=SUCCEED; /* return value */
FUNC_ENTER_API(H5Pget_cache, FAIL);
- H5TRACE5("e", "i*Is*z*z*d", plist_id, mdc_nelmts, rdcc_nelmts, rdcc_nbytes,
+ H5TRACE5("e", "i*Is*z*z*d", plist_id, mdc_nelmts, rdcc_nslots, rdcc_nbytes,
rdcc_w0);
/* Get the plist structure */
@@ -1292,9 +1292,9 @@ H5Pget_cache(hid_t plist_id, int *mdc_nelmts,
if (mdc_nelmts)
*mdc_nelmts = 0;
- if (rdcc_nelmts)
- if(H5P_get(plist, H5F_ACS_DATA_CACHE_ELMT_SIZE_NAME, rdcc_nelmts) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET,FAIL, "can't get data cache element size");
+ if (rdcc_nslots)
+ if(H5P_get(plist, H5F_ACS_DATA_CACHE_NUM_SLOTS_NAME, rdcc_nslots) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET,FAIL, "can't get data cache number of slots");
if (rdcc_nbytes)
if(H5P_get(plist, H5F_ACS_DATA_CACHE_BYTE_SIZE_NAME, rdcc_nbytes) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET,FAIL, "can't get data cache byte size");
@@ -1876,76 +1876,163 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5Pset_latest_format
- *
- * Purpose: Indicates that the library should always use the latest version
- * of the file format when creating objects. If this flag is not set,
- * the library will always use the most backwardly compatibly format
- * possible that can store the information about an object.
- *
- * The default value is set to FALSE (creating backwardly compatible files)
+ * Function: H5Pset_libver_bounds
+ *
+ * Purpose: Indicates which versions of the file format the library should
+ * use when creating objects. LOW is the earliest version of the HDF5
+ * library that is guaranteed to be able to access the objects created
+ * (the format of some objects in an HDF5 file may not have changed between
+ * versions of the HDF5 library, possibly allowing earlier versions of the
+ * HDF5 library to access those objects) and HIGH is the latest version
+ * of the library required to access the objects created (later versions
+ * of the HDF5 library will also be able to access those objects).
+ *
+ * LOW is used to require that objects use a more modern format and HIGH
+ * is used to restrict objects from using a more modern format.
+ *
+ * The special values of H5F_FORMAT_EARLIEST and H5F_FORMAT_LATEST can be
+ * used in the following manner: Setting LOW and HIGH to H5F_FORMAT_LATEST
+ * will produce files whose objects use the latest version of the file
+ * format available in the current HDF5 library for each object created.
+ * Setting LOW and HIGH to H5F_FORMAT_EARLIEST will produce files that that
+ * always require the use of the earliest version of the file format for
+ * each object created. [NOTE! LOW=HIGH=H5F_FORMAT_EARLIEST is not
+ * implemented as of version 1.8.0 and setting LOW and HIGH to
+ * H5F_FORMAT_EARLIEST will produce an error currently].
+ *
+ * Currently, the only two valid combinations for this routine are:
+ * LOW = H5F_FORMAT_EARLIEST and HIGH = H5F_FORMAT_LATEST (the default
+ * setting, which creates objects with the ealiest version possible for
+ * each object, but no upper limit on the version allowed to be created if
+ * a newer version of an object's format is required to support a feature
+ * requested with an HDF5 library API routine), and LOW = H5F_FORMAT_LATEST
+ * and HIGH = H5F_FORMAT_LATEST (which is described above).
+ *
+ * The LOW and HIGH values set with this routine at imposed with each
+ * HDF5 library API call that creates objects in the file. API calls that
+ * would violate the LOW or HIGH format bound will fail.
+ *
+ * Setting the LOW and HIGH values will not affect reading/writing existing
+ * objects, only the creation of new objects.
+ *
+ * Note: Eventually we want to add more values to the H5F_libver_t
+ * enumerated type that indicate library release values where the file
+ * format was changed (like "H5F_FORMAT_1_2_0" for the file format changes
+ * in the 1.2.x release branch and possily even "H5F_FORMAT_1_4_2" for
+ * a change mid-way through the 1.4.x release branch, etc).
+ *
+ * Adding more values will allow applications to make settings like the
+ * following:
+ * LOW = H5F_FORMAT_EARLIEST, HIGH = H5F_FORMAT_1_2_0 => Create objects
+ * with the earliest possible format and don't allow any objects
+ * to be created that require a library version greater than 1.2.x
+ * (This is the "make certain that <application> linked with v1.2.x
+ * of the library can read the file produced" use case)
+ *
+ * LOW = H5F_FORMAT_1_4_2, HIGH = H5F_FORMAT_LATEST => create objects
+ * with at least the version of their format that the 1.4.2 library
+ * uses and allow any later version of the object's format
+ * necessary to represent features used.
+ * (This is the "make certain to take advantage of <new feature>
+ * in the file format" use case (maybe <new feature> is smaller
+ * or scales better than an ealier version, which would otherwise
+ * be used))
+ *
+ * LOW = H5F_FORMAT_1_2_0, HIGH = H5F_FORMAT_1_6_0 => creates objects
+ * with at least the version of their format that the 1.2.x library
+ * uses and don't allow any objects to be created that require a
+ * library version greater than 1.6.x.
+ * (Not certain of a particular use case for these settings,
+ * although its probably just the logical combination of the
+ * previous two; it just falls out as possible/logical (if it turns
+ * out to be hard to implement in some way, we can always disallow
+ * it))
+ *
+ * Note #2: We talked about whether to include enum values for only library
+ * versions where the format changed and decided it would be less confusing
+ * for application developers if we include enum values for _all_ library
+ * releases and then map down to the previous actual library release which
+ * had a format change.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
- * Friday, September 9, 2006
+ * Sunday, December 30, 2007
*
*-------------------------------------------------------------------------
*/
herr_t
-H5Pset_latest_format(hid_t plist_id, hbool_t latest)
+H5Pset_libver_bounds(hid_t plist_id, H5F_libver_t low,
+ H5F_libver_t high)
{
H5P_genplist_t *plist; /* Property list pointer */
+ hbool_t latest; /* Whether to use the latest version or not */
herr_t ret_value = SUCCEED; /* return value */
- FUNC_ENTER_API(H5Pset_latest_format, FAIL)
- H5TRACE2("e", "ib", plist_id, latest);
+ FUNC_ENTER_API(H5Pset_libver_bounds, FAIL)
+ H5TRACE3("e", "iFvFv", plist_id, low, high);
+
+ /* Check args */
+ /* (Note that this is _really_ restricted right now, we'll want to loosen
+ * this up more as we add features - QAK)
+ */
+ if(high != H5F_LIBVER_LATEST)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid high library version bound")
/* Get the plist structure */
if(NULL == (plist = H5P_object_verify(plist_id, H5P_FILE_ACCESS)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
/* Set values */
+ latest = (low == H5F_LIBVER_LATEST) ? TRUE : FALSE;
if(H5P_set(plist, H5F_ACS_LATEST_FORMAT_NAME, &latest) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set 'latest format' flag")
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set library version bounds")
done:
FUNC_LEAVE_API(ret_value)
-} /* end H5Pset_latest_format() */
+} /* end H5Pset_libver_bounds() */
/*-------------------------------------------------------------------------
- * Function: H5Pget_latest_format
+ * Function: H5Pget_libver_bounds
*
- * Purpose: Returns the current settings for the 'latest format' flag
+ * Purpose: Returns the current settings for the library version format bounds
* from a file access property list.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
- * Friday, September 9, 2006
+ * Thursday, January 3, 2008
*
*-------------------------------------------------------------------------
*/
herr_t
-H5Pget_latest_format(hid_t plist_id, hbool_t *latest/*out*/)
+H5Pget_libver_bounds(hid_t plist_id, H5F_libver_t *low/*out*/,
+ H5F_libver_t *high/*out*/)
{
H5P_genplist_t *plist; /* Property list pointer */
+ hbool_t latest; /* Whether to use the latest version or not */
herr_t ret_value = SUCCEED; /* return value */
- FUNC_ENTER_API(H5Pget_latest_format, FAIL)
- H5TRACE2("e", "ix", plist_id, latest);
+ FUNC_ENTER_API(H5Pget_libver_bounds, FAIL)
+ H5TRACE3("e", "ixx", plist_id, low, high);
/* Get the plist structure */
if(NULL == (plist = H5P_object_verify(plist_id, H5P_FILE_ACCESS)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
/* Get value */
- if(latest)
- if(H5P_get(plist, H5F_ACS_LATEST_FORMAT_NAME, latest) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get 'latest format' flag")
+ if(H5P_get(plist, H5F_ACS_LATEST_FORMAT_NAME, &latest) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get library version bounds")
+
+ /* Check for setting values to return */
+ /* (Again, this is restricted now, we'll need to open it up later -QAK) */
+ if(low)
+ *low = latest ? H5F_LIBVER_LATEST : H5F_LIBVER_EARLIEST;
+ if(high)
+ *high = H5F_LIBVER_LATEST;
done:
FUNC_LEAVE_API(ret_value)
-} /* end H5Pget_latest_format() */
+} /* end H5Pget_libver_bounds() */
diff --git a/src/H5Pfcpl.c b/src/H5Pfcpl.c
index 6345961..a7956e7 100644
--- a/src/H5Pfcpl.c
+++ b/src/H5Pfcpl.c
@@ -53,7 +53,7 @@
#define H5F_CRT_SYM_LEAF_SIZE sizeof(unsigned)
/* Definitions for the 1/2 rank for btree internal nodes */
#define H5F_CRT_BTREE_RANK_SIZE sizeof(unsigned[H5B_NUM_BTREE_ID])
-#define H5F_CRT_BTREE_RANK_DEF {HDF5_BTREE_SNODE_IK_DEF,HDF5_BTREE_ISTORE_IK_DEF}
+#define H5F_CRT_BTREE_RANK_DEF {HDF5_BTREE_SNODE_IK_DEF,HDF5_BTREE_CHUNK_IK_DEF}
/* Definitions for byte number in an address */
#define H5F_CRT_ADDR_BYTE_NUM_SIZE sizeof(size_t)
#define H5F_CRT_ADDR_BYTE_NUM_DEF H5F_OBJ_ADDR_SIZE
@@ -100,7 +100,7 @@ static herr_t H5P_fcrt_reg_prop(H5P_genclass_t *pclass);
/* File creation property list class library initialization object */
const H5P_libclass_t H5P_CLS_FCRT[1] = {{
- "file create", /* Class name for debugging */
+ "file create", /* Class name for debugging */
&H5P_CLS_GROUP_CREATE_g, /* Parent class ID */
&H5P_CLS_FILE_CREATE_g, /* Pointer to class ID */
&H5P_LST_FILE_CREATE_g, /* Pointer to default property list ID */
@@ -593,7 +593,7 @@ H5Pset_istore_k(hid_t plist_id, unsigned ik)
/* Set value */
if(H5P_get(plist, H5F_CRT_BTREE_RANK_NAME, btree_k) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get rank for btree interanl nodes");
- btree_k[H5B_ISTORE_ID] = ik;
+ btree_k[H5B_CHUNK_ID] = ik;
if(H5P_set(plist, H5F_CRT_BTREE_RANK_NAME, btree_k) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set rank for btree interanl nodes");
@@ -641,7 +641,7 @@ H5Pget_istore_k(hid_t plist_id, unsigned *ik /*out */ )
if(ik) {
if(H5P_get(plist, H5F_CRT_BTREE_RANK_NAME, btree_k) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get rank for btree interanl nodes");
- *ik = btree_k[H5B_ISTORE_ID];
+ *ik = btree_k[H5B_CHUNK_ID];
} /* end if */
done:
@@ -757,7 +757,7 @@ H5Pset_shared_mesg_index(hid_t plist_id, unsigned index_num, unsigned mesg_type_
H5TRACE4("e", "iIuIuIu", plist_id, index_num, mesg_type_flags, min_mesg_size);
/* Check arguments */
- if(mesg_type_flags > H5O_MESG_ALL_FLAG)
+ if(mesg_type_flags > H5O_SHMESG_ALL_FLAG)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "unrecognized flags in mesg_type_flags");
/* Get the plist structure */
@@ -878,7 +878,7 @@ H5Pset_shared_mesg_phase_change(hid_t plist_id, unsigned max_list, unsigned min_
/* Check that values are sensible. The min_btree value must be no greater
* than the max list plus one.
- *
+ *
* Range check to make certain they will fit into encoded form.
*/
if(max_list + 1 < min_btree)
diff --git a/src/H5Pint.c b/src/H5Pint.c
index 46eb293..b8c7b4c 100644
--- a/src/H5Pint.c
+++ b/src/H5Pint.c
@@ -142,22 +142,6 @@ const H5P_libclass_t H5P_CLS_GACC[1] = {{
NULL /* Class close callback info */
}};
-/* Dataset access property list class library initialization object */
-/* (move to proper source code file when used for real) */
-const H5P_libclass_t H5P_CLS_DACC[1] = {{
- "dataset access", /* Class name for debugging */
- &H5P_CLS_LINK_ACCESS_g, /* Parent class ID */
- &H5P_CLS_DATASET_ACCESS_g, /* Pointer to class ID */
- &H5P_LST_DATASET_ACCESS_g, /* Pointer to default property list ID */
- NULL, /* Default property registration routine */
- NULL, /* Class creation callback */
- NULL, /* Class creation callback info */
- NULL, /* Class copy callback */
- NULL, /* Class copy callback info */
- NULL, /* Class close callback */
- NULL /* Class close callback info */
-}};
-
/* Datatype creation property list class library initialization object */
/* (move to proper source code file when used for real) */
const H5P_libclass_t H5P_CLS_TCRT[1] = {{
@@ -200,6 +184,7 @@ H5_DLLVAR const H5P_libclass_t H5P_CLS_OCPY[1]; /* Object copy */
H5_DLLVAR const H5P_libclass_t H5P_CLS_FCRT[1]; /* File creation */
H5_DLLVAR const H5P_libclass_t H5P_CLS_FACC[1]; /* File access */
H5_DLLVAR const H5P_libclass_t H5P_CLS_DCRT[1]; /* Dataset creation */
+H5_DLLVAR const H5P_libclass_t H5P_CLS_DACC[1]; /* Dataset access */
H5_DLLVAR const H5P_libclass_t H5P_CLS_DXFR[1]; /* Data transfer */
H5_DLLVAR const H5P_libclass_t H5P_CLS_FMNT[1]; /* File mount */
H5_DLLVAR const H5P_libclass_t H5P_CLS_ACRT[1]; /* Attribute creation */
@@ -406,7 +391,7 @@ H5P_init_interface(void)
/* Check for parent class */
if(lib_class->par_class_id) {
/* Get the pointer to the parent class */
- if(NULL == (par_pclass = H5I_object(*lib_class->par_class_id)))
+ if(NULL == (par_pclass = (H5P_genclass_t *)H5I_object(*lib_class->par_class_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list class")
} /* end if */
@@ -419,13 +404,13 @@ H5P_init_interface(void)
HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "can't register properties")
/* Register the new class */
- if((*lib_class->class_id = H5I_register(H5I_GENPROP_CLS, new_pclass)) < 0)
+ if((*lib_class->class_id = H5I_register(H5I_GENPROP_CLS, new_pclass, FALSE)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "can't register property list class")
/* Only register the default property list if it hasn't been created yet */
if(lib_class->def_plist_id && *lib_class->def_plist_id == (-1)) {
/* Register the default property list for the new class*/
- if((*lib_class->def_plist_id = H5P_create_id(new_pclass)) < 0)
+ if((*lib_class->def_plist_id = H5P_create_id(new_pclass, FALSE)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "can't register default property list for class")
} /* end if */
@@ -482,7 +467,7 @@ H5P_term_interface(void)
if(n) {
/* Clear the lists */
if(nlist>0) {
- H5I_clear_type(H5I_GENPROP_LST, FALSE);
+ H5I_clear_type(H5I_GENPROP_LST, FALSE, FALSE);
/* Reset the default property lists, if they've been closed */
if(H5I_nmembers(H5I_GENPROP_LST)==0) {
@@ -505,7 +490,7 @@ H5P_term_interface(void)
/* Only attempt to close the classes after all the lists are closed */
if(nlist==0 && nclass>0) {
- H5I_clear_type(H5I_GENPROP_CLS, FALSE);
+ H5I_clear_type(H5I_GENPROP_CLS, FALSE, FALSE);
/* Reset the default property lists, if they've been closed */
if(H5I_nmembers(H5I_GENPROP_CLS)==0) {
@@ -588,7 +573,7 @@ H5P_copy_pclass(H5P_genclass_t *pclass)
curr_node=H5SL_first(pclass->props);
while(curr_node!=NULL) {
/* Make a copy of the class's property */
- if((pcopy=H5P_dup_prop(H5SL_item(curr_node),H5P_PROP_WITHIN_CLASS)) == NULL)
+ if(NULL == (pcopy = H5P_dup_prop((H5P_genprop_t *)H5SL_item(curr_node), H5P_PROP_WITHIN_CLASS)))
HGOTO_ERROR (H5E_PLIST, H5E_CANTCOPY, NULL,"Can't copy property");
/* Insert the initialized property into the property list */
@@ -636,7 +621,7 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
hid_t
-H5P_copy_plist(H5P_genplist_t *old_plist)
+H5P_copy_plist(H5P_genplist_t *old_plist, hbool_t app_ref)
{
H5P_genclass_t *tclass; /* Temporary class pointer */
H5P_genplist_t *new_plist=NULL; /* New property list generated from copy */
@@ -712,11 +697,11 @@ H5P_copy_plist(H5P_genplist_t *old_plist)
curr_node=H5SL_first(old_plist->props);
while(curr_node) {
/* Get a pointer to the node's property */
- tmp=H5SL_item(curr_node);
+ tmp = (H5P_genprop_t *)H5SL_item(curr_node);
/* Make a copy of the list's property */
- if((new_prop=H5P_dup_prop(tmp,H5P_PROP_WITHIN_LIST)) == NULL)
- HGOTO_ERROR (H5E_PLIST, H5E_CANTCOPY, FAIL,"Can't copy property");
+ if(NULL == (new_prop = H5P_dup_prop(tmp, H5P_PROP_WITHIN_LIST)))
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL,"Can't copy property")
/* Call property copy callback, if it exists */
if(new_prop->copy) {
@@ -757,7 +742,7 @@ H5P_copy_plist(H5P_genplist_t *old_plist)
curr_node=H5SL_first(tclass->props);
while(curr_node!=NULL) {
/* Get pointer to property from node */
- tmp=H5SL_item(curr_node);
+ tmp = (H5P_genprop_t *)H5SL_item(curr_node);
/* Only "copy" properties we haven't seen before */
if(nseen==0 || H5SL_search(seen,tmp->name) == NULL) {
@@ -793,7 +778,7 @@ H5P_copy_plist(H5P_genplist_t *old_plist)
HGOTO_ERROR (H5E_PLIST, H5E_CANTINIT, FAIL,"Can't increment class ref count");
/* Get an atom for the property list */
- if((new_plist_id = H5I_register(H5I_GENPROP_LST, new_plist)) < 0)
+ if((new_plist_id = H5I_register(H5I_GENPROP_LST, new_plist, app_ref)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "unable to atomize property list");
/* Save the property list ID in the property list struct, for use in the property class's 'close' callback */
@@ -848,27 +833,27 @@ done:
static H5P_genprop_t *
H5P_dup_prop(H5P_genprop_t *oprop, H5P_prop_within_t type)
{
- H5P_genprop_t *prop=NULL; /* Pointer to new property copied */
+ H5P_genprop_t *prop = NULL; /* Pointer to new property copied */
H5P_genprop_t *ret_value; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5P_dup_prop);
+ FUNC_ENTER_NOAPI_NOINIT(H5P_dup_prop)
- assert(oprop);
- assert(type!=H5P_PROP_WITHIN_UNKNOWN);
+ HDassert(oprop);
+ HDassert(type != H5P_PROP_WITHIN_UNKNOWN);
/* Allocate the new property */
- if(NULL==(prop = H5FL_MALLOC (H5P_genprop_t)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
+ if(NULL == (prop = H5FL_MALLOC(H5P_genprop_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Copy basic property information */
- HDmemcpy(prop,oprop,sizeof(H5P_genprop_t));
+ HDmemcpy(prop, oprop, sizeof(H5P_genprop_t));
/* Check if we should duplicate the name or share it */
/* Duplicating property for a class */
- if(type==H5P_PROP_WITHIN_CLASS) {
- assert(oprop->type==H5P_PROP_WITHIN_CLASS);
- assert(oprop->shared_name==0);
+ if(type == H5P_PROP_WITHIN_CLASS) {
+ HDassert(oprop->type == H5P_PROP_WITHIN_CLASS);
+ HDassert(oprop->shared_name == 0);
/* Duplicate name */
prop->name = H5MM_xstrdup(oprop->name);
@@ -878,48 +863,48 @@ H5P_dup_prop(H5P_genprop_t *oprop, H5P_prop_within_t type)
/* Check if we are duplicating a property from a list or a class */
/* Duplicating a property from a list */
- if(oprop->type==H5P_PROP_WITHIN_LIST) {
+ if(oprop->type == H5P_PROP_WITHIN_LIST) {
/* If the old property's name wasn't shared, we have to copy it here also */
if(!oprop->shared_name)
prop->name = H5MM_xstrdup(oprop->name);
} /* end if */
/* Duplicating a property from a class */
else {
- assert(oprop->type==H5P_PROP_WITHIN_CLASS);
- assert(oprop->shared_name==0);
+ HDassert(oprop->type == H5P_PROP_WITHIN_CLASS);
+ HDassert(oprop->shared_name == 0);
/* Share the name */
- prop->shared_name=1;
+ prop->shared_name = 1;
/* Set the type */
- prop->type=type;
+ prop->type = type;
} /* end else */
} /* end else */
/* Duplicate current value, if it exists */
- if(oprop->value!=NULL) {
- assert(prop->size>0);
- if(NULL==(prop->value = H5MM_malloc (prop->size)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
- HDmemcpy(prop->value,oprop->value,prop->size);
+ if(oprop->value != NULL) {
+ HDassert(prop->size > 0);
+ if(NULL == (prop->value = H5MM_malloc(prop->size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ HDmemcpy(prop->value, oprop->value, prop->size);
} /* end if */
/* Set return value */
- ret_value=prop;
+ ret_value = prop;
done:
/* Free any resources allocated */
- if(ret_value==NULL) {
- if(prop!=NULL) {
- if(prop->name!=NULL)
+ if(ret_value == NULL) {
+ if(prop != NULL) {
+ if(prop->name != NULL)
H5MM_xfree(prop->name);
- if(prop->value!=NULL)
+ if(prop->value != NULL)
H5MM_xfree(prop->value);
- H5FL_FREE(H5P_genprop_t,prop);
+ (void)H5FL_FREE(H5P_genprop_t, prop);
} /* end if */
} /* end if */
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* H5P_dup_prop() */
@@ -1014,7 +999,7 @@ done:
H5MM_xfree(prop->name);
if(prop->value!=NULL)
H5MM_xfree(prop->value);
- H5FL_FREE(H5P_genprop_t,prop);
+ (void)H5FL_FREE(H5P_genprop_t, prop);
} /* end if */
} /* end if */
@@ -1083,40 +1068,40 @@ H5P_find_prop_plist(H5P_genplist_t *plist, const char *name)
{
H5P_genprop_t *ret_value; /* Property pointer return value */
- FUNC_ENTER_NOAPI_NOINIT(H5P_find_prop_plist);
+ FUNC_ENTER_NOAPI_NOINIT(H5P_find_prop_plist)
- assert(plist);
- assert(name);
+ HDassert(plist);
+ HDassert(name);
/* Check if the property has been deleted from list */
- if(H5SL_search(plist->del,name)!=NULL) {
- HGOTO_ERROR(H5E_PLIST,H5E_NOTFOUND,NULL,"can't find property in skip list");
+ if(H5SL_search(plist->del,name) != NULL) {
+ HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, NULL, "can't find property in skip list")
} /* end if */
else {
/* Get the property data from the skip list */
- if((ret_value=H5SL_search(plist->props,name)) == NULL) {
+ if(NULL == (ret_value = (H5P_genprop_t *)H5SL_search(plist->props, name))) {
H5P_genclass_t *tclass; /* Temporary class pointer */
/* Couldn't find property in list itself, start searching through class info */
- tclass=plist->pclass;
- while(tclass!=NULL) {
+ tclass = plist->pclass;
+ while(tclass != NULL) {
/* Find the property in the class */
- if((ret_value=H5SL_search(tclass->props,name))!=NULL)
+ if(NULL != (ret_value = (H5P_genprop_t *)H5SL_search(tclass->props, name)))
/* Got pointer to property - leave now */
break;
/* Go up to parent class */
- tclass=tclass->parent;
+ tclass = tclass->parent;
} /* end while */
/* Check if we haven't found the property */
- if(ret_value==NULL)
- HGOTO_ERROR(H5E_PLIST,H5E_NOTFOUND,NULL,"can't find property in skip list");
+ if(ret_value == NULL)
+ HGOTO_ERROR(H5E_PLIST,H5E_NOTFOUND,NULL,"can't find property in skip list")
} /* end else */
} /* end else */
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* H5P_find_prop_plist() */
@@ -1143,17 +1128,17 @@ H5P_find_prop_pclass(H5P_genclass_t *pclass, const char *name)
{
H5P_genprop_t *ret_value; /* Property pointer return value */
- FUNC_ENTER_NOAPI_NOINIT(H5P_find_prop_pclass);
+ FUNC_ENTER_NOAPI_NOINIT(H5P_find_prop_pclass)
- assert(pclass);
- assert(name);
+ HDassert(pclass);
+ HDassert(name);
/* Get the property from the skip list */
- if((ret_value=H5SL_search(pclass->props,name)) == NULL)
- HGOTO_ERROR(H5E_PLIST,H5E_NOTFOUND,NULL,"can't find property in skip list");
+ if(NULL == (ret_value = (H5P_genprop_t *)H5SL_search(pclass->props, name)))
+ HGOTO_ERROR(H5E_PLIST,H5E_NOTFOUND,NULL,"can't find property in skip list")
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* H5P_find_prop_pclass() */
@@ -1190,7 +1175,7 @@ H5P_free_prop(H5P_genprop_t *prop)
if(prop->shared_name==0)
H5MM_xfree(prop->name);
- H5FL_FREE(H5P_genprop_t,prop);
+ (void)H5FL_FREE(H5P_genprop_t, prop);
FUNC_LEAVE_NOAPI(SUCCEED);
} /* H5P_free_prop() */
@@ -1336,7 +1321,8 @@ H5P_access_class(H5P_genclass_t *pclass, H5P_class_mod_t mod)
case H5P_MOD_ERR:
case H5P_MOD_MAX:
- assert(0 && "Invalid H5P class modification");
+ default:
+ HDassert(0 && "Invalid H5P class modification");
} /* end switch */
/* Check if we can release the class information now */
@@ -1353,7 +1339,7 @@ H5P_access_class(H5P_genclass_t *pclass, H5P_class_mod_t mod)
H5SL_destroy(pclass->props,H5P_free_prop_cb,&make_cb);
} /* end if */
- H5FL_FREE(H5P_genclass_t,pclass);
+ (void)H5FL_FREE(H5P_genclass_t, pclass);
/* Reduce the number of dependent classes on parent class also */
if(par_class!=NULL)
@@ -1500,7 +1486,7 @@ done:
/* Free any resources allocated */
if(ret_value==NULL)
if(pclass!=NULL)
- H5FL_FREE(H5P_genclass_t,pclass);
+ (void)H5FL_FREE(H5P_genclass_t, pclass);
FUNC_LEAVE_NOAPI(ret_value)
} /* H5P_create_class() */
@@ -1586,7 +1572,7 @@ H5P_create(H5P_genclass_t *pclass)
curr_node=H5SL_first(tclass->props);
while(curr_node!=NULL) {
/* Get pointer to property from node */
- tmp=H5SL_item(curr_node);
+ tmp = (H5P_genprop_t *)H5SL_item(curr_node);
/* Only "create" properties we haven't seen before */
if(H5SL_search(seen,tmp->name) == NULL) {
@@ -1641,7 +1627,7 @@ done:
H5SL_close(plist->del);
/* Release the property list itself */
- H5FL_FREE(H5P_genplist_t,plist);
+ (void)H5FL_FREE(H5P_genplist_t, plist);
} /* end if */
} /* end if */
@@ -1672,7 +1658,7 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
hid_t
-H5P_create_id(H5P_genclass_t *pclass)
+H5P_create_id(H5P_genclass_t *pclass, hbool_t app_ref)
{
H5P_genplist_t *plist=NULL; /* Property list created */
hid_t plist_id=FAIL; /* Property list ID */
@@ -1687,7 +1673,7 @@ H5P_create_id(H5P_genclass_t *pclass)
HGOTO_ERROR(H5E_PLIST, H5E_CANTCREATE, FAIL, "unable to create property list");
/* Get an atom for the property list */
- if((plist_id = H5I_register(H5I_GENPROP_LST, plist)) < 0)
+ if((plist_id = H5I_register(H5I_GENPROP_LST, plist, app_ref)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "unable to atomize property list");
/* Save the property list ID in the property list struct, for use in the property class's 'close' callback */
@@ -1908,10 +1894,10 @@ H5P_register(H5P_genclass_t *pclass, const char *name, size_t size,
/* Walk through the properties in the old class */
curr_node=H5SL_first(pclass->props);
- while(curr_node!=NULL) {
+ while(curr_node != NULL) {
/* Make a copy of the class's property */
- if((pcopy=H5P_dup_prop(H5SL_item(curr_node),H5P_PROP_WITHIN_CLASS)) == NULL)
- HGOTO_ERROR (H5E_PLIST, H5E_CANTCOPY, FAIL,"Can't copy property");
+ if(NULL == (pcopy = H5P_dup_prop((H5P_genprop_t *)H5SL_item(curr_node), H5P_PROP_WITHIN_CLASS)))
+ HGOTO_ERROR (H5E_PLIST, H5E_CANTCOPY, FAIL, "Can't copy property")
/* Insert the initialized property into the property list */
if(H5P_add_prop(new_class->props,pcopy) < 0)
@@ -1950,7 +1936,7 @@ done:
H5MM_xfree(new_prop->name);
if(new_prop->value!=NULL)
H5MM_xfree(new_prop->value);
- H5FL_FREE(H5P_genprop_t,new_prop);
+ (void)H5FL_FREE(H5P_genprop_t, new_prop);
} /* end if */
} /* end if */
FUNC_LEAVE_NOAPI(ret_value);
@@ -2162,7 +2148,7 @@ done:
H5MM_xfree(new_prop->name);
if(new_prop->value!=NULL)
H5MM_xfree(new_prop->value);
- H5FL_FREE(H5P_genprop_t,new_prop);
+ (void)H5FL_FREE(H5P_genprop_t, new_prop);
} /* end if */
} /* end if */
@@ -2219,7 +2205,7 @@ H5P_set(H5P_genplist_t *plist, const char *name, const void *value)
HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "property doesn't exist");
/* Find property in changed list */
- if((prop=H5SL_search(plist->props,name))!=NULL) {
+ if(NULL != (prop = (H5P_genprop_t *)H5SL_search(plist->props, name))) {
/* Check for property size >0 */
if(prop->size==0)
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "property has zero size");
@@ -2258,7 +2244,7 @@ H5P_set(H5P_genplist_t *plist, const char *name, const void *value)
while(tclass!=NULL) {
if(tclass->nprops>0) {
/* Find the property in the class */
- if((prop=H5SL_search(tclass->props,name))!=NULL) {
+ if((prop = (H5P_genprop_t *)H5SL_search(tclass->props,name))!=NULL) {
H5P_genprop_t *pcopy; /* Copy of property to insert into skip list */
/* Check for property size >0 */
@@ -2821,8 +2807,8 @@ H5P_cmp_class(const H5P_genclass_t *pclass1, const H5P_genclass_t *pclass2)
if(tnode1 != NULL && tnode2 == NULL) HGOTO_DONE(1);
/* Compare the two properties */
- prop1 = H5SL_item(tnode1);
- prop2 = H5SL_item(tnode2);
+ prop1 = (H5P_genprop_t *)H5SL_item(tnode1);
+ prop2 = (H5P_genprop_t *)H5SL_item(tnode2);
if((cmp_value = H5P_cmp_prop(prop1, prop2)) != 0)
HGOTO_DONE(cmp_value);
@@ -2893,8 +2879,8 @@ H5P_cmp_plist(const H5P_genplist_t *plist1, const H5P_genplist_t *plist2)
if(tnode1 != NULL && tnode2 == NULL) HGOTO_DONE(1);
/* Compare the two deleted properties */
- name1 = H5SL_item(tnode1);
- name2 = H5SL_item(tnode2);
+ name1 = (const char *)H5SL_item(tnode1);
+ name2 = (const char *)H5SL_item(tnode2);
if((cmp_value = HDstrcmp(name1, name2)) != 0)
HGOTO_DONE(cmp_value);
@@ -2921,8 +2907,8 @@ H5P_cmp_plist(const H5P_genplist_t *plist1, const H5P_genplist_t *plist2)
if(tnode1 != NULL && tnode2 == NULL) HGOTO_DONE(1);
/* Compare the two properties */
- prop1 = H5SL_item(tnode1);
- prop2 = H5SL_item(tnode2);
+ prop1 = (H5P_genprop_t *)H5SL_item(tnode1);
+ prop2 = (H5P_genprop_t *)H5SL_item(tnode2);
if((cmp_value = H5P_cmp_prop(prop1, prop2)) != 0)
HGOTO_DONE(cmp_value);
@@ -3027,9 +3013,9 @@ H5P_isa_class(hid_t plist_id, hid_t pclass_id)
FUNC_ENTER_NOAPI(H5P_isa_class, FAIL);
/* Check arguments. */
- if(NULL == (plist = H5I_object_verify(plist_id, H5I_GENPROP_LST)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object_verify(plist_id, H5I_GENPROP_LST)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list");
- if(NULL == (pclass = H5I_object_verify(pclass_id, H5I_GENPROP_CLS)))
+ if(NULL == (pclass = (H5P_genclass_t *)H5I_object_verify(pclass_id, H5I_GENPROP_CLS)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property class");
/* Compare the property list's class against the other class */
@@ -3069,23 +3055,23 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-void *
+H5P_genplist_t *
H5P_object_verify(hid_t plist_id, hid_t pclass_id)
{
- void *ret_value; /* return value */
+ H5P_genplist_t *ret_value; /* return value */
- FUNC_ENTER_NOAPI(H5P_object_verify, NULL);
+ FUNC_ENTER_NOAPI(H5P_object_verify, NULL)
/* Compare the property list's class against the other class */
if(H5P_isa_class(plist_id, pclass_id) != TRUE)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, NULL, "property list is not a member of the class");
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, NULL, "property list is not a member of the class")
/* Get the plist structure */
- if(NULL == (ret_value = H5I_object(plist_id)))
- HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, NULL, "can't find object for ID");
+ if(NULL == (ret_value = (H5P_genplist_t *)H5I_object(plist_id)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, NULL, "can't find object for ID")
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* H5P_object_verify() */
@@ -3157,7 +3143,7 @@ H5P_iterate_plist(hid_t plist_id, int *idx, H5P_iterate_t iter_func, void *iter_
HDassert(iter_func);
/* Get the property list object */
- if(NULL == (plist = H5I_object_verify(plist_id, H5I_GENPROP_LST)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object_verify(plist_id, H5I_GENPROP_LST)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list");
/* Create the skip list to hold names of properties already seen */
@@ -3169,7 +3155,7 @@ H5P_iterate_plist(hid_t plist_id, int *idx, H5P_iterate_t iter_func, void *iter_
curr_node = H5SL_first(plist->props);
while(curr_node != NULL) {
/* Get pointer to property from node */
- tmp = H5SL_item(curr_node);
+ tmp = (H5P_genprop_t *)H5SL_item(curr_node);
/* Check if we've found the correctly indexed property */
if(curr_idx>=*idx) {
@@ -3200,7 +3186,7 @@ H5P_iterate_plist(hid_t plist_id, int *idx, H5P_iterate_t iter_func, void *iter_
curr_node=H5SL_first(tclass->props);
while(curr_node!=NULL) {
/* Get pointer to property from node */
- tmp=H5SL_item(curr_node);
+ tmp = (H5P_genprop_t *)H5SL_item(curr_node);
/* Only call iterator callback for properties we haven't seen
* before and that haven't been deleted
@@ -3313,7 +3299,7 @@ H5P_iterate_pclass(hid_t pclass_id, int *idx, H5P_iterate_t iter_func, void *ite
assert(iter_func);
/* Get the property list object */
- if(NULL == (pclass = H5I_object_verify(pclass_id, H5I_GENPROP_CLS)))
+ if(NULL == (pclass = (H5P_genclass_t *)H5I_object_verify(pclass_id, H5I_GENPROP_CLS)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property class");
/* Cycle through the properties and call the callback */
@@ -3322,7 +3308,7 @@ H5P_iterate_pclass(hid_t pclass_id, int *idx, H5P_iterate_t iter_func, void *ite
while(curr_node!=NULL) {
if(curr_idx>=*idx) {
/* Get the property for the node */
- prop=H5SL_item(curr_node);
+ prop = (H5P_genprop_t *)H5SL_item(curr_node);
/* Call the callback function */
ret_value=(*iter_func)(pclass_id,prop->name,iter_data);
@@ -3556,7 +3542,7 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
herr_t
-H5P_get(H5P_genplist_t *plist, const char *name, void *value)
+H5P_get(const H5P_genplist_t *plist, const char *name, void *value)
{
H5P_genclass_t *tclass; /* Temporary class pointer */
H5P_genprop_t *prop; /* Temporary property pointer */
@@ -3573,7 +3559,7 @@ H5P_get(H5P_genplist_t *plist, const char *name, void *value)
HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "property doesn't exist");
/* Find property */
- if((prop=H5SL_search(plist->props,name))!=NULL) {
+ if((prop = (H5P_genprop_t *)H5SL_search(plist->props,name))!=NULL) {
/* Check for property size >0 */
if(prop->size==0)
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "property has zero size");
@@ -3610,7 +3596,7 @@ H5P_get(H5P_genplist_t *plist, const char *name, void *value)
while(tclass!=NULL) {
if(tclass->nprops>0) {
/* Find the property in the class */
- if((prop=H5SL_search(tclass->props,name))!=NULL) {
+ if((prop = (H5P_genprop_t *)H5SL_search(tclass->props,name))!=NULL) {
/* Check for property size >0 */
if(prop->size==0)
HGOTO_ERROR(H5E_PLIST,H5E_BADVALUE,FAIL,"property has zero size");
@@ -3719,7 +3705,7 @@ H5P_remove(hid_t plist_id, H5P_genplist_t *plist, const char *name)
HGOTO_ERROR(H5E_PLIST,H5E_NOTFOUND,FAIL,"can't find property in skip list");
/* Get the property node from the changed property skip list */
- if((prop=H5SL_search(plist->props,name))!=NULL) {
+ if((prop = (H5P_genprop_t *)H5SL_search(plist->props,name))!=NULL) {
/* Pass value to 'close' callback, if it exists */
if(prop->del!=NULL) {
/* Call user's callback */
@@ -3851,7 +3837,7 @@ H5P_copy_prop_plist(hid_t dst_id, hid_t src_id, const char *name)
assert(name);
/* Get the objects to operate on */
- if(NULL == (src_plist = H5I_object(src_id)) || NULL == (dst_plist = H5I_object(dst_id)))
+ if(NULL == (src_plist = (H5P_genplist_t *)H5I_object(src_id)) || NULL == (dst_plist = (H5P_genplist_t *)H5I_object(dst_id)))
HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "property object doesn't exist");
/* If the property exists in the destination alread */
@@ -4011,7 +3997,7 @@ H5P_unregister(H5P_genclass_t *pclass, const char *name)
assert(name);
/* Get the property node from the skip list */
- if((prop=H5SL_search(pclass->props,name)) == NULL)
+ if((prop = (H5P_genprop_t *)H5SL_search(pclass->props,name)) == NULL)
HGOTO_ERROR(H5E_PLIST,H5E_NOTFOUND,FAIL,"can't find property in skip list");
/* Remove the property from the skip list */
@@ -4094,7 +4080,7 @@ H5P_close(void *_plist)
curr_node=H5SL_first(plist->props);
while(curr_node!=NULL) {
/* Get pointer to property from node */
- tmp=H5SL_item(curr_node);
+ tmp = (H5P_genprop_t *)H5SL_item(curr_node);
/* Call property close callback, if it exists */
if(tmp->close) {
@@ -4127,7 +4113,7 @@ H5P_close(void *_plist)
curr_node=H5SL_first(tclass->props);
while(curr_node!=NULL) {
/* Get pointer to property from node */
- tmp=H5SL_item(curr_node);
+ tmp = (H5P_genprop_t *)H5SL_item(curr_node);
/* Only "delete" properties we haven't seen before
* and that haven't already been deleted
@@ -4183,11 +4169,11 @@ H5P_close(void *_plist)
H5SL_destroy(plist->props,H5P_free_prop_cb,&make_cb);
/* Destroy property list object */
- H5FL_FREE(H5P_genplist_t,plist);
+ (void)H5FL_FREE(H5P_genplist_t, plist);
done:
/* Release the skip list of 'seen' properties */
- if(seen!=NULL)
+ if(seen != NULL)
H5SL_close(seen);
FUNC_LEAVE_NOAPI(ret_value);
@@ -4276,7 +4262,7 @@ H5P_get_class_path(H5P_genclass_t *pclass)
/* Allocate enough space for the parent class's path, plus the '/'
* separator, this class's name and the string terminator
*/
- if(NULL==(ret_value=H5MM_malloc(par_path_len+1+my_path_len+1)))
+ if(NULL == (ret_value = (char *)H5MM_malloc(par_path_len + 1 + my_path_len + 1)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for class name");
/* Build the full path for this class */
@@ -4320,24 +4306,24 @@ done:
H5P_genclass_t *
H5P_open_class_path(const char *path)
{
- char *tmp_path=NULL; /* Temporary copy of the path */
+ char *tmp_path = NULL; /* Temporary copy of the path */
char *curr_name; /* Pointer to current component of path name */
char *delimit; /* Pointer to path delimiter during traversal */
H5P_genclass_t *curr_class; /* Pointer to class during path traversal */
H5P_genclass_t *ret_value; /* Return value */
H5P_check_class_t check_info; /* Structure to hold the information for checking duplicate names */
- FUNC_ENTER_NOAPI_NOINIT(H5P_open_class_path);
+ FUNC_ENTER_NOAPI_NOINIT(H5P_open_class_path)
- assert(path);
+ HDassert(path);
/* Duplicate the path to use */
- tmp_path=H5MM_xstrdup(path);
- assert(tmp_path);
+ tmp_path = H5MM_xstrdup(path);
+ HDassert(tmp_path);
/* Find the generic property class with this full path */
- curr_name=tmp_path;
- curr_class=NULL;
+ curr_name = tmp_path;
+ curr_class = NULL;
while((delimit=HDstrchr(curr_name,'/'))!=NULL) {
/* Change the delimiter to terminate the string */
*delimit='\0';
@@ -4347,7 +4333,7 @@ H5P_open_class_path(const char *path)
check_info.name=curr_name;
/* Find the class with this name & parent by iterating over the open classes */
- if((curr_class=H5I_search(H5I_GENPROP_CLS,H5P_check_class,&check_info)) == NULL)
+ if(NULL == (curr_class = (H5P_genclass_t *)H5I_search(H5I_GENPROP_CLS, H5P_check_class, &check_info, FALSE)))
HGOTO_ERROR (H5E_PLIST, H5E_NOTFOUND, NULL, "can't locate class");
/* Advance the pointer in the path to the start of the next component */
@@ -4357,22 +4343,22 @@ H5P_open_class_path(const char *path)
/* Should be pointing to the last component in the path name now... */
/* Set up the search structure */
- check_info.parent=curr_class;
- check_info.name=curr_name;
+ check_info.parent = curr_class;
+ check_info.name = curr_name;
/* Find the class with this name & parent by iterating over the open classes */
- if((curr_class=H5I_search(H5I_GENPROP_CLS,H5P_check_class,&check_info)) == NULL)
- HGOTO_ERROR (H5E_PLIST, H5E_NOTFOUND, NULL, "can't locate class");
+ if(NULL == (curr_class = (H5P_genclass_t *)H5I_search(H5I_GENPROP_CLS, H5P_check_class, &check_info, FALSE)))
+ HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, NULL, "can't locate class")
/* Copy it */
- if((ret_value=H5P_copy_pclass(curr_class)) == NULL)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, NULL, "can't copy property class");
+ if(NULL == (ret_value = H5P_copy_pclass(curr_class)))
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, NULL, "can't copy property class")
done:
/* Free the duplicated path */
H5MM_xfree(tmp_path);
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* H5P_open_class_path() */
diff --git a/src/H5Plapl.c b/src/H5Plapl.c
index 8987c49..e3f2333 100644
--- a/src/H5Plapl.c
+++ b/src/H5Plapl.c
@@ -55,6 +55,13 @@
#define H5L_ACS_ELINK_PREFIX_COPY H5P_lacc_elink_pref_copy
#define H5L_ACS_ELINK_PREFIX_CLOSE H5P_lacc_elink_pref_close
+/* Definitions for setting fapl of external link access */
+#define H5L_ACS_ELINK_FAPL_SIZE sizeof(hid_t)
+#define H5L_ACS_ELINK_FAPL_DEF H5P_DEFAULT
+#define H5L_ACS_ELINK_FAPL_DEL H5P_lacc_elink_fapl_del
+#define H5L_ACS_ELINK_FAPL_COPY H5P_lacc_elink_fapl_copy
+#define H5L_ACS_ELINK_FAPL_CLOSE H5P_lacc_elink_fapl_close
+
/******************/
/* Local Typedefs */
/******************/
@@ -77,6 +84,10 @@ static herr_t H5P_lacc_elink_pref_del(hid_t prop_id, const char* name, size_t si
static herr_t H5P_lacc_elink_pref_copy(const char* name, size_t size, void* value);
static herr_t H5P_lacc_elink_pref_close(const char* name, size_t size, void* value);
+static herr_t H5P_lacc_elink_fapl_del(hid_t prop_id, const char* name, size_t size, void* value);
+static herr_t H5P_lacc_elink_fapl_copy(const char* name, size_t size, void* value);
+static herr_t H5P_lacc_elink_fapl_close(const char* name, size_t size, void* value);
+
/*********************/
/* Package Variables */
@@ -118,14 +129,20 @@ const H5P_libclass_t H5P_CLS_LACC[1] = {{
*
* Programmer: Quincey Koziol
* October 31, 2006
+ *
+ * Modifications:
+ * Vailin Choi, Sept. 12th 2008
+ * Register the setting of file access property list for link access
+ *
*-------------------------------------------------------------------------
*/
static herr_t
H5P_lacc_reg_prop(H5P_genclass_t *pclass)
{
- size_t nlinks = H5L_ACS_NLINKS_DEF; /* Default number of soft links to traverse */
+ size_t nlinks = H5L_ACS_NLINKS_DEF; /* Default number of soft links to traverse */
char *elink_prefix = H5L_ACS_ELINK_PREFIX_DEF; /* Default external link prefix string */
- herr_t ret_value = SUCCEED; /* Return value */
+ hid_t def_fapl_id = H5L_ACS_ELINK_FAPL_DEF; /* Default fapl for external link access */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5P_lacc_reg_prop)
@@ -139,11 +156,125 @@ H5P_lacc_reg_prop(H5P_genclass_t *pclass)
&elink_prefix, NULL, NULL, NULL, H5L_ACS_ELINK_PREFIX_DEL, H5L_ACS_ELINK_PREFIX_COPY, NULL, H5L_ACS_ELINK_PREFIX_CLOSE) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+ /* Register fapl for link access */
+ if(H5P_register(pclass, H5L_ACS_ELINK_FAPL_NAME, H5L_ACS_ELINK_FAPL_SIZE, &def_fapl_id, NULL, NULL, NULL, H5L_ACS_ELINK_FAPL_DEL, H5L_ACS_ELINK_FAPL_COPY, NULL, H5L_ACS_ELINK_FAPL_CLOSE) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5P_lacc_reg_prop() */
+/*--------------------------------------------------------------------------
+ * Function: H5P_lacc_elink_fapl_del
+ *
+ * Purpose: Close the FAPL for link access
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Vailin Choi
+ * Tuesday, Sept 23, 2008
+ *
+ *--------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static herr_t
+H5P_lacc_elink_fapl_del(hid_t UNUSED prop_id, const char UNUSED *name, size_t UNUSED size, void *value)
+{
+ hid_t l_fapl_id;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(H5P_lacc_elink_fapl_del, FAIL)
+
+ HDassert(value);
+
+ l_fapl_id = (*(const hid_t *)value);
+
+ if((l_fapl_id > H5P_DEFAULT) && (H5I_dec_ref(l_fapl_id, FALSE) < 0))
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTRELEASE, FAIL, "unable to close atom for file access property list")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P_lacc_elink_fapl_del() */
+
+
+/*--------------------------------------------------------------------------
+ * Function: H5P_lacc_elink_fapl_copy
+ *
+ * Purpose: Copy the FAPL for link access
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Vailin Choi
+ * Tuesday, Sept 23, 2008
+ *
+ *--------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static herr_t
+H5P_lacc_elink_fapl_copy(const char UNUSED *name, size_t UNUSED size, void *value)
+{
+ hid_t l_fapl_id;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(H5P_lacc_elink_fapl_copy, FAIL)
+
+ HDassert(value);
+
+ l_fapl_id = (*(const hid_t *)value);
+
+ if(l_fapl_id > H5P_DEFAULT) {
+ H5P_genplist_t *l_fapl_plist;
+
+ if(NULL == (l_fapl_plist = (H5P_genplist_t *)H5P_object_verify(l_fapl_id, H5P_FILE_ACCESS)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list")
+
+ if(((*(hid_t *)value) = H5P_copy_plist(l_fapl_plist, FALSE)) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_CANTINIT, FAIL, "unable to copy file access properties")
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P_lacc_elink_fapl_copy() */
+
+
+/*--------------------------------------------------------------------------
+ * Function: H5P_lacc_elink_fapl_close
+ *
+ * Purpose: Close the FAPL for link access
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Vailin Choi
+ * Tuesday, Sept 23, 2008
+ *
+ *---------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+herr_t
+H5P_lacc_elink_fapl_close(const char UNUSED *name, size_t UNUSED size, void *value)
+{
+ hid_t l_fapl_id;
+ herr_t ret_value = SUCCEED;
+
+int ref_count;
+ FUNC_ENTER_NOAPI(H5P_lacc_elink_fapl_close, FAIL)
+
+ HDassert(value);
+
+ l_fapl_id = (*(const hid_t *)value);
+
+ if((l_fapl_id > H5P_DEFAULT) && (H5I_dec_ref(l_fapl_id, FALSE) < 0))
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTRELEASE, FAIL, "unable to close atom for file access property list")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5P_lacc_elink_fapl_close() */
+
+
/*-------------------------------------------------------------------------
* Function: H5P_lacc_elink_pref_del
*
@@ -315,7 +446,7 @@ done:
* Purpose: Set a prefix to be applied to the path of any external links
* traversed. The prefix is appended to the filename stored
* in the external link.
- *
+ *
* Return: Non-negative on success/Negative on failure
*
* Programmer: James Laird
@@ -412,3 +543,96 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Pget_elink_prefix() */
+/*-------------------------------------------------------------------------
+ * Function: H5Pset_elink_fapl
+ *
+ * Purpose: Sets the file access property list for link access
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer:
+ * Vailin Choi; Tuesday, September 12th, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pset_elink_fapl(hid_t lapl_id, hid_t fapl_id)
+{
+ H5P_genplist_t *plist, *l_fapl_plist, *fapl_plist; /* Property list pointer */
+ hid_t l_fapl_id, new_fapl_id;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(H5Pset_elink_fapl, FAIL)
+ H5TRACE2("e", "ii", lapl_id, fapl_id);
+
+ /* Check arguments */
+ if(NULL == (plist = H5P_object_verify(lapl_id, H5P_LINK_ACCESS)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a link access property list");
+
+ /* Get the current file access property list for the link access */
+ if(H5P_get(plist, H5L_ACS_ELINK_FAPL_NAME, &l_fapl_id) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get fapl")
+
+ /* Close the current file access property list if set */
+ if((l_fapl_id > H5P_DEFAULT) && (H5I_dec_ref(l_fapl_id, FALSE) < 0))
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTRELEASE, FAIL, "unable to close atom for file access property list")
+
+ if (NULL==(fapl_plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list");
+
+ /* Make a copy of the property list for FAPL_ID */
+ if((new_fapl_id = H5P_copy_plist(fapl_plist, FALSE)) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_CANTINIT, FAIL, "unable to copy file access properties")
+
+ /* Set the file access property list for the link access */
+ if(H5P_set(plist, H5L_ACS_ELINK_FAPL_NAME, &new_fapl_id) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set fapl for link")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Pset_elink_fapl() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Pget_elink_fapl
+ *
+ * Purpose: Gets the file access property list identifier that is
+ * set for link access property.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer:
+ * Vailin Choi; Tuesday, September 12th, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5Pget_elink_fapl(hid_t lapl_id)
+{
+ H5P_genplist_t *plist, *fapl_plist; /* Property list pointer */
+ hid_t l_fapl_id;
+ hid_t ret_value=FAIL; /* Return value */
+
+ FUNC_ENTER_API(H5Pget_elink_fapl, FAIL)
+ H5TRACE1("i", "i", lapl_id);
+
+ /* Get the plist structure */
+ if(NULL == (plist = H5P_object_verify(lapl_id, H5P_LINK_ACCESS)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
+
+ if(H5P_get(plist, H5L_ACS_ELINK_FAPL_NAME, &l_fapl_id) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get fapl for links")
+
+ if(l_fapl_id > H5P_DEFAULT) {
+ if(NULL==(fapl_plist = H5P_object_verify(l_fapl_id, H5P_FILE_ACCESS)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list");
+
+ if((ret_value = H5P_copy_plist(fapl_plist, TRUE)) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_CANTINIT, FAIL, "unable to copy file access properties")
+ } else
+ ret_value = l_fapl_id;
+
+done:
+ FUNC_LEAVE_API(ret_value);
+} /* end H5Pget_elink_fapl() */
+
diff --git a/src/H5Pprivate.h b/src/H5Pprivate.h
index a96df21..885249d 100644
--- a/src/H5Pprivate.h
+++ b/src/H5Pprivate.h
@@ -57,9 +57,9 @@ H5_DLL herr_t H5P_init(void);
/* Internal versions of API routines */
H5_DLL herr_t H5P_close(void *_plist);
-H5_DLL hid_t H5P_create_id(H5P_genclass_t *pclass);
-H5_DLL hid_t H5P_copy_plist(H5P_genplist_t *old_plist);
-H5_DLL herr_t H5P_get(H5P_genplist_t *plist, const char *name, void *value);
+H5_DLL hid_t H5P_create_id(H5P_genclass_t *pclass, hbool_t app_ref);
+H5_DLL hid_t H5P_copy_plist(H5P_genplist_t *old_plist, hbool_t app_ref);
+H5_DLL herr_t H5P_get(const H5P_genplist_t *plist, const char *name, void *value);
H5_DLL herr_t H5P_set(H5P_genplist_t *plist, const char *name, const void *value);
H5_DLL herr_t H5P_insert(H5P_genplist_t *plist, const char *name, size_t size,
void *value, H5P_prp_set_func_t prp_set, H5P_prp_get_func_t prp_get,
@@ -89,7 +89,7 @@ H5_DLL int H5P_fill_value_cmp(const void *value1, const void *value2,
/* *SPECIAL* Don't make more of these! -QAK */
H5_DLL htri_t H5P_isa_class(hid_t plist_id, hid_t pclass_id);
-H5_DLL void *H5P_object_verify(hid_t plist_id, hid_t pclass_id);
+H5_DLL H5P_genplist_t *H5P_object_verify(hid_t plist_id, hid_t pclass_id);
/* Private functions to "peek" at properties of a certain type */
H5_DLL unsigned H5P_peek_unsigned(H5P_genplist_t *plist, const char *name);
diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h
index f1e98af..498eecc 100644
--- a/src/H5Ppublic.h
+++ b/src/H5Ppublic.h
@@ -245,11 +245,11 @@ H5_DLL herr_t H5Pget_family_offset(hid_t fapl_id, hsize_t *offset);
H5_DLL herr_t H5Pset_multi_type(hid_t fapl_id, H5FD_mem_t type);
H5_DLL herr_t H5Pget_multi_type(hid_t fapl_id, H5FD_mem_t *type);
H5_DLL herr_t H5Pset_cache(hid_t plist_id, int mdc_nelmts,
- size_t rdcc_nelmts, size_t rdcc_nbytes,
+ size_t rdcc_nslots, size_t rdcc_nbytes,
double rdcc_w0);
H5_DLL herr_t H5Pget_cache(hid_t plist_id,
int *mdc_nelmts, /* out */
- size_t *rdcc_nelmts/*out*/,
+ size_t *rdcc_nslots/*out*/,
size_t *rdcc_nbytes/*out*/, double *rdcc_w0);
H5_DLL herr_t H5Pset_mdc_config(hid_t plist_id,
H5AC_cache_config_t * config_ptr);
@@ -265,13 +265,15 @@ H5_DLL herr_t H5Pset_sieve_buf_size(hid_t fapl_id, size_t size);
H5_DLL herr_t H5Pget_sieve_buf_size(hid_t fapl_id, size_t *size/*out*/);
H5_DLL herr_t H5Pset_small_data_block_size(hid_t fapl_id, hsize_t size);
H5_DLL herr_t H5Pget_small_data_block_size(hid_t fapl_id, hsize_t *size/*out*/);
-H5_DLL herr_t H5Pset_latest_format(hid_t plist_id, hbool_t latest);
-H5_DLL herr_t H5Pget_latest_format(hid_t plist_id, hbool_t *latest);
+H5_DLL herr_t H5Pset_libver_bounds(hid_t plist_id, H5F_libver_t low,
+ H5F_libver_t high);
+H5_DLL herr_t H5Pget_libver_bounds(hid_t plist_id, H5F_libver_t *low,
+ H5F_libver_t *high);
/* Dataset creation property list (DCPL) routines */
H5_DLL herr_t H5Pset_layout(hid_t plist_id, H5D_layout_t layout);
H5_DLL H5D_layout_t H5Pget_layout(hid_t plist_id);
-H5_DLL herr_t H5Pset_chunk(hid_t plist_id, int ndims, const hsize_t dim[]);
+H5_DLL herr_t H5Pset_chunk(hid_t plist_id, int ndims, const hsize_t dim[/*ndims*/]);
H5_DLL int H5Pget_chunk(hid_t plist_id, int max_ndims, hsize_t dim[]/*out*/);
H5_DLL herr_t H5Pset_external(hid_t plist_id, const char *name, off_t offset,
hsize_t size);
@@ -317,6 +319,14 @@ H5_DLL herr_t H5Pset_fill_time(hid_t plist_id, H5D_fill_time_t fill_time);
H5_DLL herr_t H5Pget_fill_time(hid_t plist_id, H5D_fill_time_t
*fill_time/*out*/);
+/* Dataset access property list (DAPL) routines */
+H5_DLL herr_t H5Pset_chunk_cache(hid_t dapl_id, size_t rdcc_nslots,
+ size_t rdcc_nbytes, double rdcc_w0);
+H5_DLL herr_t H5Pget_chunk_cache(hid_t dapl_id,
+ size_t *rdcc_nslots/*out*/,
+ size_t *rdcc_nbytes/*out*/,
+ double *rdcc_w0/*out*/);
+
/* Dataset xfer property list (DXPL) routines */
H5_DLL herr_t H5Pset_data_transform(hid_t plist_id, const char* expression);
H5_DLL ssize_t H5Pget_data_transform(hid_t plist_id, char* expression /*out*/, size_t size);
@@ -372,13 +382,15 @@ H5_DLL herr_t H5Pset_nlinks(hid_t plist_id, size_t nlinks);
H5_DLL herr_t H5Pget_nlinks(hid_t plist_id, size_t *nlinks);
H5_DLL herr_t H5Pset_elink_prefix(hid_t plist_id, const char *prefix);
H5_DLL ssize_t H5Pget_elink_prefix(hid_t plist_id, char *prefix, size_t size);
+H5_DLL hid_t H5Pget_elink_fapl(hid_t lapl_id);
+H5_DLL herr_t H5Pset_elink_fapl(hid_t lapl_id, hid_t fapl_id);
/* Object copy property list (OCPYPL) routines */
H5_DLL herr_t H5Pset_copy_object(hid_t plist_id, unsigned crt_intmd);
H5_DLL herr_t H5Pget_copy_object(hid_t plist_id, unsigned *crt_intmd /*out*/);
/* Symbols defined for compatibility with previous versions of the HDF5 API.
- *
+ *
* Use of these symbols is deprecated.
*/
#ifndef H5_NO_DEPRECATED_SYMBOLS
diff --git a/src/H5Ptest.c b/src/H5Ptest.c
index 4a3bca5..575d6d3 100644
--- a/src/H5Ptest.c
+++ b/src/H5Ptest.c
@@ -63,18 +63,18 @@ H5P_get_class_path_test(hid_t pclass_id)
H5P_genclass_t *pclass; /* Property class to query */
char *ret_value; /* return value */
- FUNC_ENTER_NOAPI(H5P_get_class_path_test, NULL);
+ FUNC_ENTER_NOAPI(H5P_get_class_path_test, NULL)
/* Check arguments. */
- if (NULL == (pclass = H5I_object_verify(pclass_id, H5I_GENPROP_CLS)))
+ if(NULL == (pclass = (H5P_genclass_t *)H5I_object_verify(pclass_id, H5I_GENPROP_CLS)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a property class");
/* Get the property list class path */
- if ((ret_value=H5P_get_class_path(pclass))==NULL)
- HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, NULL, "unable to query full path of class");
+ if(NULL == (ret_value = H5P_get_class_path(pclass)))
+ HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, NULL, "unable to query full path of class")
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* H5P_get_class_path_test() */
@@ -115,7 +115,7 @@ H5P_open_class_path_test(const char *path)
HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "unable to find class with full path");
/* Get an atom for the class */
- if ((ret_value=H5I_register(H5I_GENPROP_CLS, pclass))<0)
+ if ((ret_value=H5I_register(H5I_GENPROP_CLS, pclass, TRUE))<0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "unable to atomize property list class");
done:
@@ -149,13 +149,13 @@ H5P_reset_external_file_test(hid_t dcpl_id)
H5P_genplist_t *plist; /* Property list */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5P_reset_external_file_test, FAIL);
+ FUNC_ENTER_NOAPI(H5P_reset_external_file_test, FAIL)
/* Check arguments */
- if(NULL == (plist = H5I_object(dcpl_id)))
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(dcpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list")
-
- /* get external file list */
+
+ /* get external file list */
if(H5P_get(plist, H5D_CRT_EXT_FILE_LIST_NAME, &efl) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get external file list")
@@ -163,11 +163,11 @@ H5P_reset_external_file_test(hid_t dcpl_id)
if(H5O_msg_reset(H5O_EFL_ID, &efl) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "can't release external file list info")
- /* set external file list */
+ /* set external file list */
if(H5P_set(plist, H5D_CRT_EXT_FILE_LIST_NAME, &efl) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get external file list")
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* H5P_reset_external_file_test() */
diff --git a/src/H5R.c b/src/H5R.c
index 627626b..933f983 100644
--- a/src/H5R.c
+++ b/src/H5R.c
@@ -37,7 +37,8 @@
/* Static functions */
static herr_t H5R_create(void *ref, H5G_loc_t *loc, const char *name,
H5R_type_t ref_type, H5S_t *space, hid_t dxpl_id);
-static hid_t H5R_dereference(H5F_t *file, hid_t dxpl_id, H5R_type_t ref_type, const void *_ref);
+static hid_t H5R_dereference(H5F_t *file, hid_t dxpl_id, H5R_type_t ref_type,
+ const void *_ref, hbool_t app_ref);
static H5S_t * H5R_get_region(H5F_t *file, hid_t dxpl_id, const void *_ref);
static ssize_t H5R_get_name(H5F_t *file, hid_t lapl_id, hid_t dxpl_id, hid_t id,
H5R_type_t ref_type, const void *_ref, char *name, size_t size);
@@ -123,7 +124,7 @@ H5R_term_interface(void)
if (H5_interface_initialize_g) {
if ((n=H5I_nmembers(H5I_REFERENCE))) {
- H5I_clear_type(H5I_REFERENCE, FALSE);
+ H5I_clear_type(H5I_REFERENCE, FALSE, FALSE);
} else {
H5I_dec_type_ref(H5I_REFERENCE);
H5_interface_initialize_g = 0;
@@ -235,7 +236,7 @@ H5R_create(void *_ref, H5G_loc_t *loc, const char *name, H5R_type_t ref_type, H5
/* Allocate the space to store the serialized information */
H5_CHECK_OVERFLOW(buf_size, hssize_t, size_t);
- if(NULL == (buf = H5MM_malloc((size_t)buf_size)))
+ if(NULL == (buf = (uint8_t *)H5MM_malloc((size_t)buf_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Serialize information for dataset OID into heap buffer */
@@ -264,7 +265,7 @@ H5R_create(void *_ref, H5G_loc_t *loc, const char *name, H5R_type_t ref_type, H5
case H5R_BADTYPE:
case H5R_MAXTYPE:
default:
- assert("unknown reference type" && 0);
+ HDassert("unknown reference type" && 0);
HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, FAIL, "internal error (unknown reference type)")
} /* end switch */
@@ -307,7 +308,7 @@ herr_t
H5Rcreate(void *ref, hid_t loc_id, const char *name, H5R_type_t ref_type, hid_t space_id)
{
H5G_loc_t loc; /* File location */
- H5S_t *space = NULL; /* Pointer to dataspace containing region */
+ H5S_t *space; /* Pointer to dataspace containing region */
herr_t ret_value; /* Return value */
FUNC_ENTER_API(H5Rcreate, FAIL)
@@ -324,7 +325,7 @@ H5Rcreate(void *ref, hid_t loc_id, const char *name, H5R_type_t ref_type, hid_t
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference type")
if(ref_type != H5R_OBJECT && ref_type != H5R_DATASET_REGION)
HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "reference type not supported")
- if(space_id != (-1) && (NULL == (space = H5I_object_verify(space_id, H5I_DATASPACE))))
+ if(space_id != (-1) && (NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE))))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
/* Create reference */
@@ -359,7 +360,7 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
static hid_t
-H5R_dereference(H5F_t *file, hid_t dxpl_id, H5R_type_t ref_type, const void *_ref)
+H5R_dereference(H5F_t *file, hid_t dxpl_id, H5R_type_t ref_type, const void *_ref, hbool_t app_ref)
{
H5O_loc_t oloc; /* Object location */
H5G_name_t path; /* Path of object */
@@ -394,7 +395,7 @@ H5R_dereference(H5F_t *file, hid_t dxpl_id, H5R_type_t ref_type, const void *_re
INT32DECODE(p, hobjid.idx);
/* Get the dataset region from the heap (allocate inside routine) */
- if((buf = H5HG_read(oloc.file, dxpl_id, &hobjid, NULL, NULL)) == NULL)
+ if(NULL == (buf = (uint8_t *)H5HG_read(oloc.file, dxpl_id, &hobjid, NULL, NULL)))
HGOTO_ERROR(H5E_REFERENCE, H5E_READERROR, FAIL, "Unable to read dataset region information")
/* Get the object oid for the dataset */
@@ -432,11 +433,11 @@ H5R_dereference(H5F_t *file, hid_t dxpl_id, H5R_type_t ref_type, const void *_re
{
H5G_t *group; /* Pointer to group to open */
- if((group = H5G_open(&loc, dxpl_id)) == NULL)
+ if(NULL == (group = H5G_open(&loc, dxpl_id)))
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "not found")
/* Create an atom for the group */
- if((ret_value = H5I_register(H5I_GROUP, group)) < 0) {
+ if((ret_value = H5I_register(H5I_GROUP, group, app_ref)) < 0) {
H5G_close(group);
HGOTO_ERROR(H5E_SYM, H5E_CANTREGISTER, FAIL, "can't register group")
} /* end if */
@@ -447,11 +448,11 @@ H5R_dereference(H5F_t *file, hid_t dxpl_id, H5R_type_t ref_type, const void *_re
{
H5T_t *type; /* Pointer to datatype to open */
- if((type = H5T_open(&loc, dxpl_id)) == NULL)
+ if(NULL == (type = H5T_open(&loc, dxpl_id)))
HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, FAIL, "not found")
/* Create an atom for the datatype */
- if((ret_value = H5I_register(H5I_DATATYPE, type)) < 0) {
+ if((ret_value = H5I_register(H5I_DATATYPE, type, app_ref)) < 0) {
H5T_close(type);
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "can't register datatype")
} /* end if */
@@ -460,14 +461,15 @@ H5R_dereference(H5F_t *file, hid_t dxpl_id, H5R_type_t ref_type, const void *_re
case H5O_TYPE_DATASET:
{
+ hid_t dapl_id = H5P_DATASET_ACCESS_DEFAULT; /* dapl to use to open dataset */
H5D_t *dset; /* Pointer to dataset to open */
/* Open the dataset */
- if((dset = H5D_open(&loc, dxpl_id)) == NULL)
+ if(NULL == (dset = H5D_open(&loc, dapl_id, dxpl_id)))
HGOTO_ERROR(H5E_DATASET, H5E_NOTFOUND, FAIL, "not found")
/* Create an atom for the dataset */
- if((ret_value = H5I_register(H5I_DATASET, dset)) < 0) {
+ if((ret_value = H5I_register(H5I_DATASET, dset, app_ref)) < 0) {
H5D_close(dset);
HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "can't register dataset")
} /* end if */
@@ -527,7 +529,7 @@ H5Rdereference(hid_t id, H5R_type_t ref_type, const void *_ref)
file = loc.oloc->file;
/* Create reference */
- if((ret_value = H5R_dereference(file, H5AC_dxpl_id, ref_type, _ref)) < 0)
+ if((ret_value = H5R_dereference(file, H5AC_dxpl_id, ref_type, _ref, TRUE)) < 0)
HGOTO_ERROR(H5E_REFERENCE, H5E_CANTINIT, FAIL, "unable dereference object")
done:
@@ -580,7 +582,7 @@ H5R_get_region(H5F_t *file, hid_t dxpl_id, const void *_ref)
INT32DECODE(p, hobjid.idx);
/* Get the dataset region from the heap (allocate inside routine) */
- if((buf = H5HG_read(oloc.file, dxpl_id, &hobjid, NULL, NULL)) == NULL)
+ if((buf = (uint8_t *)H5HG_read(oloc.file, dxpl_id, &hobjid, NULL, NULL)) == NULL)
HGOTO_ERROR(H5E_REFERENCE, H5E_READERROR, NULL, "Unable to read dataset region information")
/* Get the object oid for the dataset */
@@ -650,7 +652,7 @@ H5Rget_region(hid_t id, H5R_type_t ref_type, const void *ref)
HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCREATE, FAIL, "unable to create dataspace")
/* Atomize */
- if((ret_value = H5I_register (H5I_DATASPACE, space)) < 0)
+ if((ret_value = H5I_register (H5I_DATASPACE, space, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace atom")
done:
@@ -714,7 +716,7 @@ H5R_get_obj_type(H5F_t *file, hid_t dxpl_id, H5R_type_t ref_type,
INT32DECODE(p, hobjid.idx);
/* Get the dataset region from the heap (allocate inside routine) */
- if((buf = H5HG_read(oloc.file, dxpl_id, &hobjid, NULL, NULL)) == NULL)
+ if((buf = (uint8_t *)H5HG_read(oloc.file, dxpl_id, &hobjid, NULL, NULL)) == NULL)
HGOTO_ERROR(H5E_REFERENCE, H5E_READERROR, FAIL, "Unable to read dataset region information")
/* Get the object oid for the dataset */
@@ -861,7 +863,7 @@ H5R_get_name(H5F_t *f, hid_t lapl_id, hid_t dxpl_id, hid_t id, H5R_type_t ref_ty
INT32DECODE(p, hobjid.idx);
/* Get the dataset region from the heap (allocate inside routine) */
- if((buf = H5HG_read(oloc.file, dxpl_id, &hobjid, NULL, NULL)) == NULL)
+ if((buf = (uint8_t *)H5HG_read(oloc.file, dxpl_id, &hobjid, NULL, NULL)) == NULL)
HGOTO_ERROR(H5E_REFERENCE, H5E_READERROR, FAIL, "Unable to read dataset region information")
/* Get the object oid for the dataset */
@@ -881,17 +883,17 @@ H5R_get_name(H5F_t *f, hid_t lapl_id, hid_t dxpl_id, hid_t id, H5R_type_t ref_ty
} /* end switch */
/* Retrieve file ID for name search */
- if((file_id = H5I_get_file_id(id)) < 0)
+ if((file_id = H5I_get_file_id(id, FALSE)) < 0)
HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "can't retrieve file ID")
/* Get name, length, etc. */
- if((ret_value = H5G_get_refobj_name(file_id, lapl_id, dxpl_id, &oloc, name, size)) < 0)
+ if((ret_value = H5G_get_name_by_addr(file_id, lapl_id, dxpl_id, &oloc, name, size)) < 0)
HGOTO_ERROR(H5E_REFERENCE, H5E_CANTGET, FAIL, "can't determine name")
done:
/* Close file ID used for search */
if(file_id > 0)
- if(H5I_dec_ref(file_id) < 0)
+ if(H5I_dec_ref(file_id, FALSE) < 0)
HDONE_ERROR(H5E_REFERENCE, H5E_CANTCLOSEFILE, FAIL, "can't determine name")
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5RC.c b/src/H5RC.c
index 25a08a5..49e26a8 100644
--- a/src/H5RC.c
+++ b/src/H5RC.c
@@ -99,29 +99,29 @@ done:
herr_t
H5RC_decr(H5RC_t *rc)
{
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5RC_decr,FAIL);
+ FUNC_ENTER_NOAPI(H5RC_decr, FAIL)
/* Sanity check */
HDassert(rc);
HDassert(rc->o);
- HDassert(rc->n>0);
+ HDassert(rc->n > 0);
HDassert(rc->free_func);
/* Decrement reference count */
rc->n--;
/* Check if we should delete this object now */
- if(rc->n==0) {
- if((rc->free_func)(rc->o)<0) {
- H5FL_FREE(H5RC_t,rc);
- HGOTO_ERROR(H5E_RS,H5E_CANTFREE,FAIL,"memory release failed");
+ if(rc->n == 0) {
+ if((rc->free_func)(rc->o) < 0) {
+ (void)H5FL_FREE(H5RC_t, rc);
+ HGOTO_ERROR(H5E_RS, H5E_CANTFREE, FAIL, "memory release failed")
} /* end if */
- H5FL_FREE(H5RC_t,rc);
+ (void)H5FL_FREE(H5RC_t, rc);
} /* end if */
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5RC_decr() */
diff --git a/src/H5RS.c b/src/H5RS.c
index 065d05f..0142c1f 100644
--- a/src/H5RS.c
+++ b/src/H5RS.c
@@ -221,20 +221,20 @@ done:
herr_t
H5RS_decr(H5RS_str_t *rs)
{
- FUNC_ENTER_NOAPI_NOFUNC(H5RS_decr);
+ FUNC_ENTER_NOAPI_NOFUNC(H5RS_decr)
/* Sanity check */
- assert(rs);
- assert(rs->n > 0);
+ HDassert(rs);
+ HDassert(rs->n > 0);
/* Decrement reference count for string */
- if((--rs->n)==0) {
+ if((--rs->n) == 0) {
if(!rs->wrapped)
- (void)H5FL_BLK_FREE(str_buf,rs->s);
- H5FL_FREE(H5RS_str_t,rs);
+ (void)H5FL_BLK_FREE(str_buf, rs->s);
+ (void)H5FL_FREE(H5RS_str_t, rs);
} /* end if */
- FUNC_LEAVE_NOAPI(SUCCEED);
+ FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5RS_decr() */
diff --git a/src/H5Rpublic.h b/src/H5Rpublic.h
index 975104e..04d319b 100644
--- a/src/H5Rpublic.h
+++ b/src/H5Rpublic.h
@@ -68,7 +68,7 @@ H5_DLL ssize_t H5Rget_name(hid_t loc_id, H5R_type_t ref_type, const void *ref,
char *name/*out*/, size_t size);
/* Symbols defined for compatibility with previous versions of the HDF5 API.
- *
+ *
* Use of these symbols is deprecated.
*/
#ifndef H5_NO_DEPRECATED_SYMBOLS
diff --git a/src/H5S.c b/src/H5S.c
index f990925..7214415 100644
--- a/src/H5S.c
+++ b/src/H5S.c
@@ -43,19 +43,6 @@ static herr_t H5S_set_extent_simple (H5S_t *space, unsigned rank,
static htri_t H5S_is_simple(const H5S_t *sdim);
static herr_t H5S_encode(H5S_t *obj, unsigned char *buf, size_t *nalloc);
static H5S_t *H5S_decode(const unsigned char *buf);
-static htri_t H5S_extent_equal(const H5S_t *ds1, const H5S_t *ds2);
-
-#ifdef H5S_DEBUG
-/* Names of the selection names, for debugging */
-static const char *H5S_sel_names[]={
- "none", "point", "hyperslab", "all"
-};
-
-/* The path table, variable length */
-static H5S_iostats_t **H5S_iostats_g = NULL;
-static size_t H5S_aiostats_g = 0; /*entries allocated*/
-static size_t H5S_niostats_g = 0; /*entries used*/
-#endif /* H5S_DEBUG */
#ifdef H5_HAVE_PARALLEL
/* Global vars whose value can be set from environment variable also */
@@ -87,9 +74,9 @@ DESCRIPTION
static herr_t
H5S_init_interface(void)
{
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5S_init_interface);
+ FUNC_ENTER_NOAPI_NOINIT(H5S_init_interface)
/* Initialize the atom group for the file IDs */
if(H5I_register_type(H5I_DATASPACE, (size_t)H5I_DATASPACEID_HASHSIZE, H5S_RESERVED_ATOMS, (H5I_free_t)H5S_close) < 0)
@@ -105,8 +92,8 @@ H5S_init_interface(void)
#endif /* H5_HAVE_PARALLEL */
done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S_init_interface() */
/*--------------------------------------------------------------------------
@@ -129,156 +116,26 @@ done:
int
H5S_term_interface(void)
{
- int n=0;
-#ifdef H5S_DEBUG
- size_t i;
- int j, nprints=0;
- H5S_iostats_t *path=NULL;
- char buf[256];
-#endif /* H5S_DEBUG */
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_term_interface);
-
- if (H5_interface_initialize_g) {
- if ((n=H5I_nmembers(H5I_DATASPACE))) {
- H5I_clear_type(H5I_DATASPACE, FALSE);
- } else {
-#ifdef H5S_DEBUG
- /*
- * Print statistics about each conversion path.
- */
- if (H5DEBUG(S)) {
- for (i=0; i<H5S_niostats_g; i++) {
- path = H5S_iostats_g[i];
- for (j=0; j<2; j++) {
- if (0==path->stats[j].gath_ncalls &&
- 0==path->stats[j].scat_ncalls &&
- 0==path->stats[j].bkg_ncalls &&
- 0==path->stats[j].read_ncalls &&
- 0==path->stats[j].write_ncalls) {
- continue;
- }
- if (0==nprints++) {
- fprintf(H5DEBUG(S), "H5S: data space conversion "
- "statistics:\n");
- fprintf(H5DEBUG(S),
- " %-16s %10s %10s %8s %8s %8s %10s\n",
- "Memory <> File", "Bytes", "Calls",
- "User", "System", "Elapsed", "Bandwidth");
- fprintf(H5DEBUG(S),
- " %-16s %10s %10s %8s %8s %8s %10s\n",
- "--------------", "-----", "-----",
- "----", "------", "-------", "---------");
- }
-
- /* Summary */
- sprintf(buf, "%s %c %s",
- H5S_sel_names[path->mtype], 0==j?'>':'<', H5S_sel_names[path->ftype]);
- fprintf(H5DEBUG(S), " %-16s\n", buf);
-
- /* Gather */
- if (path->stats[j].gath_ncalls) {
- H5_bandwidth(buf,
- (double)(path->stats[j].gath_nbytes),
- path->stats[j].gath_timer.etime);
- HDfprintf(H5DEBUG(S),
- " %16s %10Hu %10Hu %8.2f %8.2f %8.2f "
- "%10s\n", "gather",
- path->stats[j].gath_nbytes,
- path->stats[j].gath_ncalls,
- path->stats[j].gath_timer.utime,
- path->stats[j].gath_timer.stime,
- path->stats[j].gath_timer.etime,
- buf);
- }
-
- /* Scatter */
- if (path->stats[j].scat_ncalls) {
- H5_bandwidth(buf,
- (double)(path->stats[j].scat_nbytes),
- path->stats[j].scat_timer.etime);
- HDfprintf(H5DEBUG(S),
- " %16s %10Hu %10Hu %8.2f %8.2f %8.2f "
- "%10s\n", "scatter",
- path->stats[j].scat_nbytes,
- path->stats[j].scat_ncalls,
- path->stats[j].scat_timer.utime,
- path->stats[j].scat_timer.stime,
- path->stats[j].scat_timer.etime,
- buf);
- }
-
- /* Background */
- if (path->stats[j].bkg_ncalls) {
- H5_bandwidth(buf,
- (double)(path->stats[j].bkg_nbytes),
- path->stats[j].bkg_timer.etime);
- HDfprintf(H5DEBUG(S),
- " %16s %10Hu %10Hu %8.2f %8.2f %8.2f "
- "%10s\n", "background",
- path->stats[j].bkg_nbytes,
- path->stats[j].bkg_ncalls,
- path->stats[j].bkg_timer.utime,
- path->stats[j].bkg_timer.stime,
- path->stats[j].bkg_timer.etime,
- buf);
- }
-
- /* Read */
- if (path->stats[j].read_ncalls) {
- H5_bandwidth(buf,
- (double)(path->stats[j].read_nbytes),
- path->stats[j].read_timer.etime);
- HDfprintf(H5DEBUG(S),
- " %16s %10Hu %10Hu %8.2f %8.2f %8.2f "
- "%10s\n", "read",
- path->stats[j].read_nbytes,
- path->stats[j].read_ncalls,
- path->stats[j].read_timer.utime,
- path->stats[j].read_timer.stime,
- path->stats[j].read_timer.etime,
- buf);
- }
-
- /* Write */
- if (path->stats[j].write_ncalls) {
- H5_bandwidth(buf,
- (double)(path->stats[j].write_nbytes),
- path->stats[j].write_timer.etime);
- HDfprintf(H5DEBUG(S),
- " %16s %10Hu %10Hu %8.2f %8.2f %8.2f "
- "%10s\n", "write",
- path->stats[j].write_nbytes,
- path->stats[j].write_ncalls,
- path->stats[j].write_timer.utime,
- path->stats[j].write_timer.stime,
- path->stats[j].write_timer.etime,
- buf);
- }
- }
- }
- }
-#endif /* H5S_DEBUG */
+ int n = 0;
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_term_interface)
+
+ if(H5_interface_initialize_g) {
+ if((n = H5I_nmembers(H5I_DATASPACE))) {
+ H5I_clear_type(H5I_DATASPACE, FALSE, FALSE);
+ } /* end if */
+ else {
/* Free data types */
H5I_dec_type_ref(H5I_DATASPACE);
-#ifdef H5S_DEBUG
- /* Clear/free conversion table */
- for (i=0; i<H5S_niostats_g; i++)
- H5MM_xfree(H5S_iostats_g[i]);
- H5S_iostats_g = H5MM_xfree(H5S_iostats_g);
- H5S_niostats_g = H5S_aiostats_g = 0;
-#endif /* H5S_DEBUG */
-
/* Shut down interface */
H5_interface_initialize_g = 0;
n = 1; /*H5I*/
- }
- }
+ } /* end else */
+ } /* end if */
- FUNC_LEAVE_NOAPI(n);
-}
+ FUNC_LEAVE_NOAPI(n)
+} /* end H5S_term_interface() */
/*--------------------------------------------------------------------------
@@ -392,7 +249,7 @@ H5Screate(H5S_class_t type)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "unable to create dataspace")
/* Atomize */
- if((ret_value = H5I_register (H5I_DATASPACE, new_ds)) < 0)
+ if((ret_value = H5I_register (H5I_DATASPACE, new_ds, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register data space atom")
done:
@@ -467,7 +324,7 @@ H5S_close(H5S_t *ds)
H5S_extent_release(&ds->extent);
/* Release the main structure */
- H5FL_FREE(H5S_t, ds);
+ (void)H5FL_FREE(H5S_t, ds);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -503,7 +360,7 @@ H5Sclose(hid_t space_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space")
/* When the reference count reaches zero the resources are freed */
- if (H5I_dec_ref(space_id) < 0)
+ if (H5I_dec_ref(space_id, TRUE) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "problem freeing id")
done:
@@ -542,11 +399,11 @@ H5Scopy(hid_t space_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space")
/* Copy */
- if (NULL==(dst=H5S_copy (src, FALSE)))
+ if (NULL == (dst = H5S_copy(src, FALSE, TRUE)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to copy data space")
/* Atomize */
- if ((ret_value=H5I_register (H5I_DATASPACE, dst))<0)
+ if ((ret_value=H5I_register (H5I_DATASPACE, dst, TRUE))<0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register data space atom")
done:
@@ -580,22 +437,22 @@ H5Sextent_copy(hid_t dst_id,hid_t src_id)
H5S_t *dst;
hid_t ret_value = SUCCEED;
- FUNC_ENTER_API(H5Sextent_copy, FAIL);
+ FUNC_ENTER_API(H5Sextent_copy, FAIL)
H5TRACE2("e", "ii", dst_id, src_id);
/* Check args */
- if (NULL==(src=(H5S_t *)H5I_object_verify(src_id, H5I_DATASPACE)))
+ if(NULL == (src = (H5S_t *)H5I_object_verify(src_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space")
- if (NULL==(dst=(H5S_t *)H5I_object_verify(dst_id, H5I_DATASPACE)))
+ if(NULL == (dst = (H5S_t *)H5I_object_verify(dst_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space")
/* Copy */
- if (H5S_extent_copy(&(dst->extent),&(src->extent))<0)
+ if(H5S_extent_copy(&(dst->extent), &(src->extent), TRUE) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy extent")
done:
- FUNC_LEAVE_API(ret_value);
-}
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Sextent_copy() */
/*-------------------------------------------------------------------------
@@ -613,7 +470,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5S_extent_copy(H5S_extent_t *dst, const H5S_extent_t *src)
+H5S_extent_copy(H5S_extent_t *dst, const H5S_extent_t *src, hbool_t copy_max)
{
unsigned u;
herr_t ret_value = SUCCEED; /* Return value */
@@ -641,13 +498,13 @@ H5S_extent_copy(H5S_extent_t *dst, const H5S_extent_t *src)
} /* end if */
else
dst->size = NULL;
- if(src->max) {
+ if(copy_max && src->max) {
dst->max = (hsize_t *)H5FL_ARR_MALLOC(hsize_t, (size_t)src->rank);
for(u = 0; u < src->rank; u++)
dst->max[u] = src->max[u];
} /* end if */
else
- dst->max=NULL;
+ dst->max = NULL;
break;
default:
@@ -686,7 +543,7 @@ done:
*-------------------------------------------------------------------------
*/
H5S_t *
-H5S_copy(const H5S_t *src, hbool_t share_selection)
+H5S_copy(const H5S_t *src, hbool_t share_selection, hbool_t copy_max)
{
H5S_t *dst = NULL;
H5S_t *ret_value; /* Return value */
@@ -697,7 +554,7 @@ H5S_copy(const H5S_t *src, hbool_t share_selection)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Copy the source dataspace's extent */
- if(H5S_extent_copy(&(dst->extent), &(src->extent)) < 0)
+ if(H5S_extent_copy(&(dst->extent), &(src->extent), copy_max) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, NULL, "can't copy extent")
/* Copy the source dataspace's selection */
@@ -1055,27 +912,20 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5S_write(H5O_loc_t *loc, const H5S_t *ds, hbool_t update_time, hid_t dxpl_id)
+H5S_write(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned update_flags, H5S_t *ds)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5S_write, FAIL)
- HDassert(loc);
+ HDassert(f);
+ HDassert(oh);
HDassert(ds);
+ HDassert(H5S_GET_EXTENT_TYPE(ds) >= 0);
- switch(H5S_GET_EXTENT_TYPE(ds)) {
- case H5S_NULL:
- case H5S_SCALAR:
- case H5S_SIMPLE:
- if(H5O_msg_write(loc, H5O_SDSPACE_ID, 0, update_time, &(ds->extent), dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't update simple dataspace message")
- break;
-
- default:
- HDassert("unknown dataspace class" && 0);
- break;
- } /* end switch */
+ /* Write the current dataspace extent to the dataspace message */
+ if(H5O_msg_write_oh(f, dxpl_id, oh, H5O_SDSPACE_ID, 0, update_flags, &(ds->extent)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't update simple dataspace message")
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1103,7 +953,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5S_append(H5F_t *f, hid_t dxpl_id, struct H5O_t *oh, const H5S_t *ds)
+H5S_append(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5S_t *ds)
{
herr_t ret_value = SUCCEED; /* Return value */
@@ -1112,19 +962,11 @@ H5S_append(H5F_t *f, hid_t dxpl_id, struct H5O_t *oh, const H5S_t *ds)
HDassert(f);
HDassert(oh);
HDassert(ds);
+ HDassert(H5S_GET_EXTENT_TYPE(ds) >= 0);
- switch (H5S_GET_EXTENT_TYPE(ds)) {
- case H5S_NULL:
- case H5S_SCALAR:
- case H5S_SIMPLE:
- if(H5O_msg_append(f, dxpl_id, oh, H5O_SDSPACE_ID, 0, 0, &(ds->extent)) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't update simple data space message")
- break;
-
- default:
- assert("unknown data space class" && 0);
- break;
- }
+ /* Add the dataspace message to the object header */
+ if(H5O_msg_append_oh(f, dxpl_id, oh, H5O_SDSPACE_ID, 0, 0, &(ds->extent)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't add simple dataspace message")
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1172,7 +1014,7 @@ H5S_read(const H5O_loc_t *loc, hid_t dxpl_id)
done:
if(ret_value == NULL) {
if(ds != NULL)
- H5FL_FREE(H5S_t, ds);
+ (void)H5FL_FREE(H5S_t, ds);
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
@@ -1388,6 +1230,7 @@ H5S_set_extent_simple(H5S_t *space, unsigned rank, const hsize_t *dims,
/* Set offset to zeros */
for(u = 0; u < space->extent.rank; u++)
space->select.offset[u] = 0;
+ space->select.offset_changed = FALSE;
/* If the selection is 'all', update the number of elements selected */
if(H5S_GET_SELECT_TYPE(space) == H5S_SEL_ALL)
@@ -1398,105 +1241,6 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5S_set_extent_simple() */
-#ifdef H5S_DEBUG
-
-/*-------------------------------------------------------------------------
- * Function: H5S_find
- *
- * Purpose: Given two data spaces (MEM_SPACE and FILE_SPACE) this
- * function returns a pointer to the conversion path information,
- * creating a new conversion path entry if necessary.
- *
- * Return: Success: Ptr to a conversion path entry
- *
- * Failure: NULL
- *
- * Programmer: Robb Matzke
- * Wednesday, January 21, 1998
- *
- * Modifications:
- *
- * Quincey Koziol
- * Instead of returning a point into the data space conversion table we
- * copy all the information into a user-supplied CONV buffer and return
- * non-negative on success or negative on failure.
- *
- * Robb Matzke, 11 Aug 1998
- * Returns a pointer into the conversion path table. A path entry
- * contains pointers to the memory and file half of the conversion (the
- * pointers registered in the H5S_fconv_g[] and H5S_mconv_g[] tables)
- * along with other data whose scope is the conversion path (like path
- * statistics).
- *
- * John Mainzer, 8/30/04
- * Modified code to check with all other processes that have the
- * file open before OKing collective I/O.
- *
- *-------------------------------------------------------------------------
- */
-H5S_iostats_t *
-H5S_find (const H5S_t *mem_space, const H5S_t *file_space)
-{
- H5S_iostats_t *path=NULL; /* Space conversion path */
- size_t u; /* Index variable */
- H5S_iostats_t *ret_value; /* Return value */
-
- FUNC_ENTER_NOAPI(H5S_find, NULL);
-
- /* Check args */
- assert (mem_space && (H5S_SIMPLE==H5S_GET_EXTENT_TYPE(mem_space) ||
- H5S_NULL==H5S_GET_EXTENT_TYPE(mem_space) ||
- H5S_SCALAR==H5S_GET_EXTENT_TYPE(mem_space)));
- assert (file_space && (H5S_SIMPLE==H5S_GET_EXTENT_TYPE(file_space) ||
- H5S_NULL==H5S_GET_EXTENT_TYPE(file_space) ||
- H5S_SCALAR==H5S_GET_EXTENT_TYPE(file_space)));
-
- /*
- * Is this path already present in the data space conversion path table?
- * If so then return a pointer to that entry.
- */
- for (u=0; u<H5S_niostats_g; u++)
- if (H5S_iostats_g[u]->ftype==H5S_GET_SELECT_TYPE(file_space) &&
- H5S_iostats_g[u]->mtype==H5S_GET_SELECT_TYPE(mem_space))
- HGOTO_DONE(H5S_iostats_g[u]);
-
- /*
- * The path wasn't found. Create a new path.
- */
- if (NULL==(path = H5MM_calloc(sizeof(*path))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for data space conversion path")
-
- /* Initialize file & memory conversion functions */
- path->ftype = H5S_GET_SELECT_TYPE(file_space);
- path->mtype = H5S_GET_SELECT_TYPE(mem_space);
-
- /*
- * Add the new path to the table.
- */
- if (H5S_niostats_g>=H5S_aiostats_g) {
- size_t n = MAX(10, 2*H5S_aiostats_g);
- H5S_iostats_t **p = H5MM_realloc(H5S_iostats_g, n*sizeof(H5S_iostats_g[0]));
-
- if (NULL==p)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for data space conversion path table")
- H5S_aiostats_g = n;
- H5S_iostats_g = p;
- } /* end if */
- H5S_iostats_g[H5S_niostats_g++] = path;
-
- /* Set the return value */
- ret_value=path;
-
-done:
- if(ret_value==NULL) {
- if(path!=NULL)
- H5MM_xfree(path);
- } /* end if */
-
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5S_find() */
-#endif /* H5S_DEBUG */
-
/*-------------------------------------------------------------------------
* Function: H5Screate_simple
@@ -1564,7 +1308,7 @@ H5Screate_simple(int rank, const hsize_t dims[/*rank*/],
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create simple dataspace")
/* Atomize */
- if ((ret_value=H5I_register (H5I_DATASPACE, space))<0)
+ if ((ret_value=H5I_register (H5I_DATASPACE, space, TRUE))<0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace ID")
done:
@@ -1765,7 +1509,7 @@ H5Sdecode(const void *buf)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDECODE, FAIL, "can't decode object")
/* Register the type and return the ID */
- if((ret_value = H5I_register(H5I_DATASPACE, ds)) < 0)
+ if((ret_value = H5I_register(H5I_DATASPACE, ds, TRUE)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTREGISTER, FAIL, "unable to register dataspace")
done:
@@ -1832,7 +1576,7 @@ H5S_decode(const unsigned char *buf)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, NULL, "can't copy object")
if(H5S_extent_release(extent) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTDELETE, NULL, "can't release previous dataspace")
- H5FL_FREE(H5S_extent_t, extent);
+ (void)H5FL_FREE(H5S_extent_t, extent);
/* Initialize to "all" selection. Deserialization relies on valid existing selection. */
if(H5S_select_all(ds, FALSE) < 0)
@@ -2188,7 +1932,7 @@ done:
DESCRIPTION
Compare two dataspaces if their extents are identical.
--------------------------------------------------------------------------*/
-static htri_t
+htri_t
H5S_extent_equal(const H5S_t *ds1, const H5S_t *ds2)
{
unsigned u; /* Local index variable */
diff --git a/src/H5SL.c b/src/H5SL.c
index 53c0f2d..fe810d1 100644
--- a/src/H5SL.c
+++ b/src/H5SL.c
@@ -58,8 +58,8 @@
/* Local Macros */
/* Define the code template for insertions for the "OP" in the H5SL_LOCATE macro */
-#define H5SL_LOCATE_INSERT_FOUND(SLIST,X,UPDATE,I) \
- HGOTO_ERROR(H5E_SLIST,H5E_CANTINSERT,NULL,"can't insert duplicate key");
+#define H5SL_LOCATE_INSERT_FOUND(SLIST, X, UPDATE, I) \
+ HGOTO_ERROR(H5E_SLIST, H5E_CANTINSERT, NULL, "can't insert duplicate key")
/* Define the code template for removals for the "OP" in the H5SL_LOCATE macro */
/* (NOTE: the code in H5SL_remove_first() is largely the same, fix bugs in both places) */
@@ -83,68 +83,100 @@
HGOTO_DONE(tmp);
/* Define the code template for searches for the "OP" in the H5SL_LOCATE macro */
-#define H5SL_LOCATE_SEARCH_FOUND(SLIST,X,UPDATE,I) \
+#define H5SL_LOCATE_SEARCH_FOUND(SLIST, X, UPDATE, I) \
HGOTO_DONE(X->item);
/* Define the code template for finds for the "OP" in the H5SL_LOCATE macro */
-#define H5SL_LOCATE_FIND_FOUND(SLIST,X,UPDATE,I) \
+#define H5SL_LOCATE_FIND_FOUND(SLIST, X, UPDATE, I) \
HGOTO_DONE(X);
-/* Define a code template for updating the "update" vector for the "DOUPDATE" in the H5SL_LOCATE macro */
-#define H5SL_LOCATE_YES_UPDATE(X,UPDATE,I) \
- UPDATE[I]=&X->forward[I];
-/* Define a code template for _NOT_ updating the "update" vector for the "DOUPDATE" in the H5SL_LOCATE macro */
-#define H5SL_LOCATE_NO_UPDATE(X,UPDATE,I)
+/* Define a code template for "OP"s that update the "update" vector for the H5SL_LOCATE macro */
+#define H5SL_LOCATE_INSERT_UPDATE(X, UPDATE, I) \
+ UPDATE[I] = &X->forward[I];
+#define H5SL_LOCATE_REMOVE_UPDATE(X, UPDATE, I) \
+ UPDATE[I] = &X->forward[I];
+
+/* Define a code template for "OP"s that _DON'T_ update the "update" vector for the H5SL_LOCATE macro */
+#define H5SL_LOCATE_SEARCH_UPDATE(X, UPDATE, I)
+#define H5SL_LOCATE_FIND_UPDATE(X, UPDATE, I)
+
/* Define a code template for comparing scalar keys for the "CMP" in the H5SL_LOCATE macro */
-#define H5SL_LOCATE_SCALAR_CMP(TYPE,PKEY1,PKEY2) \
- (*(TYPE *)PKEY1<*(TYPE *)PKEY2)
+#define H5SL_LOCATE_SCALAR_CMP(TYPE, PNODE, PKEY, HASHVAL) \
+ (*(TYPE *)((PNODE)->key) < *(TYPE *)PKEY)
/* Define a code template for comparing string keys for the "CMP" in the H5SL_LOCATE macro */
-#define H5SL_LOCATE_STRING_CMP(TYPE,PKEY1,PKEY2) \
- (HDstrcmp(PKEY1,PKEY2)<0)
+#define H5SL_LOCATE_STRING_CMP(TYPE, PNODE, PKEY, HASHVAL) \
+ (((PNODE)->hashval == HASHVAL) ? (HDstrcmp((PNODE)->key, PKEY) < 0) : ((PNODE)->hashval < HASHVAL))
+
+/* Define a code template for comparing H5_obj_t keys for the "CMP" in the H5SL_LOCATE macro */
+#define H5SL_LOCATE_OBJ_CMP(TYPE, PNODE, PKEY, HASHVAL) \
+ ((((TYPE *)((PNODE)->key))->fileno < ((TYPE *)PKEY)->fileno) ? TRUE : (((TYPE *)((PNODE)->key))->addr < ((TYPE *)PKEY)->addr))
+
/* Define a code template for comparing scalar keys for the "EQ" in the H5SL_LOCATE macro */
-#define H5SL_LOCATE_SCALAR_EQ(TYPE,PKEY1,PKEY2) \
- (*(TYPE *)PKEY1==*(TYPE *)PKEY2)
+#define H5SL_LOCATE_SCALAR_EQ(TYPE, PNODE, PKEY, HASHVAL) \
+ (*(TYPE *)((PNODE)->key) == *(TYPE *)PKEY)
/* Define a code template for comparing string keys for the "EQ" in the H5SL_LOCATE macro */
-#define H5SL_LOCATE_STRING_EQ(TYPE,PKEY1,PKEY2) \
- (HDstrcmp(PKEY1,PKEY2)==0)
+#define H5SL_LOCATE_STRING_EQ(TYPE, PNODE, PKEY, HASHVAL) \
+ (((PNODE)->hashval == HASHVAL) && (HDstrcmp(((PNODE)->key), PKEY) == 0))
+
+/* Define a code template for comparing H5_obj_t keys for the "EQ" in the H5SL_LOCATE macro */
+#define H5SL_LOCATE_OBJ_EQ(TYPE, PNODE, PKEY, HASHVAL) \
+ ((((TYPE *)((PNODE)->key))->fileno == ((TYPE *)PKEY)->fileno) && (((TYPE *)((PNODE)->key))->addr == ((TYPE *)PKEY)->addr))
+
+
+/* Define a code template for initializing the hash value for scalar keys for the "HASHINIT" in the H5SL_LOCATE macro */
+#define H5SL_LOCATE_SCALAR_HASHINIT(KEY, HASHVAL)
+
+/* Define a code template for initializing the hash value for string keys for the "HASHINIT" in the H5SL_LOCATE macro */
+#define H5SL_LOCATE_STRING_HASHINIT(KEY, HASHVAL) \
+ HASHVAL = H5_hash_string(KEY);
+
+/* Define a code template for initializing the hash value for H5_obj_t keys for the "HASHINIT" in the H5SL_LOCATE macro */
+#define H5SL_LOCATE_OBJ_HASHINIT(KEY, HASHVAL)
+
/* Macro used to find node for operation */
-#define H5SL_LOCATE(OP,DOUPDATE,CMP,SLIST,X,UPDATE,I,TYPE,KEY,CHECKED) \
- CHECKED=NULL; \
- for(I=(int)SLIST->curr_level; I>=0; I--) { \
- if(X->forward[I]!=CHECKED) { \
- while(X->forward[I] && H5_GLUE3(H5SL_LOCATE_,CMP,_CMP)(TYPE,X->forward[I]->key,KEY) ) \
- X=X->forward[I]; \
- CHECKED=X->forward[I]; \
+#define H5SL_LOCATE(OP, CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL) \
+{ \
+ H5SL_node_t *_checked; /* Pointer to last node checked */ \
+ int _i; /* Local index variable */ \
+ \
+ _checked = NULL; \
+ H5_GLUE3(H5SL_LOCATE_,CMP,_HASHINIT)(KEY, HASHVAL) \
+ for(_i = (int)SLIST->curr_level; _i >= 0; _i--) { \
+ if(X->forward[_i] != _checked) { \
+ while(X->forward[_i] && H5_GLUE3(H5SL_LOCATE_,CMP,_CMP)(TYPE, X->forward[_i], KEY, HASHVAL) ) \
+ X = X->forward[_i]; \
+ _checked = X->forward[_i]; \
} /* end if */ \
- H5_GLUE3(H5SL_LOCATE_,DOUPDATE,_UPDATE)(X,UPDATE,I) \
+ H5_GLUE3(H5SL_LOCATE_,OP,_UPDATE)(X, UPDATE, _i) \
} /* end for */ \
- X=X->forward[0]; \
- if(X!=NULL && H5_GLUE3(H5SL_LOCATE_,CMP,_EQ)(TYPE,X->key,KEY) ) { \
+ X = X->forward[0]; \
+ if(X != NULL && H5_GLUE3(H5SL_LOCATE_,CMP,_EQ)(TYPE, X, KEY, HASHVAL) ) { \
/* What to do when a node is found */ \
- H5_GLUE3(H5SL_LOCATE_,OP,_FOUND)(SLIST,X,UPDATE,I) \
- } /* end if */
+ H5_GLUE3(H5SL_LOCATE_,OP,_FOUND)(SLIST, X, UPDATE, _i) \
+ } /* end if */ \
+}
/* Macro used to insert node */
-#define H5SL_INSERT(CMP, SLIST, X, UPDATE, I, TYPE, KEY, CHECKED) \
- H5SL_LOCATE(INSERT, YES, CMP, SLIST, X, UPDATE, I, TYPE, KEY, CHECKED)
+#define H5SL_INSERT(CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL) \
+ H5SL_LOCATE(INSERT, CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL)
/* Macro used to remove node */
-#define H5SL_REMOVE(CMP, SLIST, X, UPDATE, I, TYPE, KEY, CHECKED) \
- H5SL_LOCATE(REMOVE, YES, CMP, SLIST, X, UPDATE, I, TYPE, KEY, CHECKED)
+#define H5SL_REMOVE(CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL) \
+ H5SL_LOCATE(REMOVE, CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL)
/* Macro used to search for node */
-#define H5SL_SEARCH(CMP, SLIST, X, UPDATE, I, TYPE, KEY, CHECKED) \
- H5SL_LOCATE(SEARCH, NO, CMP, SLIST, X, UPDATE, I, TYPE, KEY, CHECKED)
+#define H5SL_SEARCH(CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL) \
+ H5SL_LOCATE(SEARCH, CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL)
/* Macro used to find a node */
-#define H5SL_FIND(CMP, SLIST, X, UPDATE, I, TYPE, KEY, CHECKED) \
- H5SL_LOCATE(FIND, NO, CMP, SLIST, X, UPDATE, I, TYPE, KEY, CHECKED)
+#define H5SL_FIND(CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL) \
+ H5SL_LOCATE(FIND, CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL)
/* Private typedefs & structs */
@@ -154,6 +186,7 @@ struct H5SL_node_t {
const void *key; /* Pointer to node's key */
void *item; /* Pointer to node's item */
size_t level; /* The level of this node */
+ uint32_t hashval; /* Hash value for key (only for strings, currently) */
struct H5SL_node_t **forward; /* Array of forward pointers from this node */
struct H5SL_node_t *backward; /* Backward pointer from this node */
};
@@ -175,7 +208,7 @@ struct H5SL_t {
/* Static functions */
static size_t H5SL_random_level(int p1, size_t max_level);
-static H5SL_node_t * H5SL_new_node(size_t lvl, void *item, const void *key);
+static H5SL_node_t * H5SL_new_node(size_t lvl, void *item, const void *key, uint32_t hashval);
static H5SL_node_t *H5SL_insert_common(H5SL_t *slist, void *item, const void *key);
static herr_t H5SL_release_common(H5SL_t *slist, H5SL_operator_t op, void *op_data);
static herr_t H5SL_close_common(H5SL_t *slist, H5SL_operator_t op, void *op_data);
@@ -287,24 +320,25 @@ H5SL_random_level(int p1, size_t max_level)
REVISION LOG
--------------------------------------------------------------------------*/
static H5SL_node_t *
-H5SL_new_node(size_t lvl, void *item, const void *key)
+H5SL_new_node(size_t lvl, void *item, const void *key, uint32_t hashval)
{
H5SL_node_t *ret_value; /* New skip list node */
- FUNC_ENTER_NOAPI_NOINIT(H5SL_new_node);
+ FUNC_ENTER_NOAPI_NOINIT(H5SL_new_node)
/* Allocate the node */
- if((ret_value=H5FL_ARR_MALLOC(H5SL_node_ptr_t,(lvl+1)))==NULL)
- HGOTO_ERROR(H5E_SLIST,H5E_NOSPACE,NULL,"memory allocation failed");
+ if(NULL == (ret_value = (H5SL_node_t *)H5FL_ARR_MALLOC(H5SL_node_ptr_t, (lvl + 1))))
+ HGOTO_ERROR(H5E_SLIST, H5E_NOSPACE, NULL, "memory allocation failed")
/* Initialize node */
- ret_value->key=key;
- ret_value->item=item;
- ret_value->level=lvl;
- ret_value->forward=(H5SL_node_t **)((unsigned char *)ret_value+sizeof(H5SL_node_t));
+ ret_value->key = key;
+ ret_value->item = item;
+ ret_value->level = lvl;
+ ret_value->hashval = hashval;
+ ret_value->forward = (H5SL_node_t **)((unsigned char *)ret_value + sizeof(H5SL_node_t));
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5SL_new_node() */
@@ -333,8 +367,8 @@ static H5SL_node_t *
H5SL_insert_common(H5SL_t *slist, void *item, const void *key)
{
H5SL_node_t **update[H5SL_LEVEL_MAX]; /* 'update' vector */
- H5SL_node_t *checked; /* Pointer to last node checked */
H5SL_node_t *x; /* Current node to examine */
+ uint32_t hashval = 0; /* Hash value for key */
size_t lvl; /* Level of new node */
int i; /* Local index value */
H5SL_node_t *ret_value; /* Return value */
@@ -356,28 +390,35 @@ H5SL_insert_common(H5SL_t *slist, void *item, const void *key)
x=slist->header;
switch(slist->type) {
case H5SL_TYPE_INT:
- H5SL_INSERT(SCALAR, slist, x, update, i, const int, key, checked)
+ H5SL_INSERT(SCALAR, slist, x, update, const int, key, -)
break;
case H5SL_TYPE_HADDR:
- H5SL_INSERT(SCALAR, slist, x, update, i, const haddr_t, key, checked)
+ H5SL_INSERT(SCALAR, slist, x, update, const haddr_t, key, -)
break;
case H5SL_TYPE_STR:
- H5SL_INSERT(STRING, slist, x, update, i, char *, key, checked)
+ H5SL_INSERT(STRING, slist, x, update, char *, key, hashval)
break;
case H5SL_TYPE_HSIZE:
- H5SL_INSERT(SCALAR, slist, x, update, i, const hsize_t, key, checked)
+ H5SL_INSERT(SCALAR, slist, x, update, const hsize_t, key, -)
break;
case H5SL_TYPE_UNSIGNED:
- H5SL_INSERT(SCALAR, slist, x, update, i, const unsigned, key, checked)
+ H5SL_INSERT(SCALAR, slist, x, update, const unsigned, key, -)
break;
case H5SL_TYPE_SIZE:
- H5SL_INSERT(SCALAR, slist, x, update, i, const size_t, key, checked)
+ H5SL_INSERT(SCALAR, slist, x, update, const size_t, key, -)
+ break;
+
+ case H5SL_TYPE_OBJ:
+ H5SL_INSERT(OBJ, slist, x, update, const H5_obj_t, key, -)
break;
+
+ default:
+ HDassert(0 && "Unknown skiplist type!");
} /* end switch */
/* 'key' must not have been found in existing list, if we get here */
@@ -396,8 +437,8 @@ H5SL_insert_common(H5SL_t *slist, void *item, const void *key)
} /* end if */
/* Create new node of proper level */
- if((x=H5SL_new_node(lvl,item,key))==NULL)
- HGOTO_ERROR(H5E_SLIST,H5E_NOSPACE,NULL,"can't create new skip list node");
+ if(NULL == (x = H5SL_new_node(lvl, item, key, hashval)))
+ HGOTO_ERROR(H5E_SLIST ,H5E_NOSPACE, NULL, "can't create new skip list node")
/* Update the backward links */
if(*update[0]!=NULL) {
@@ -520,24 +561,24 @@ H5SL_release_common(H5SL_t *slist, H5SL_operator_t op, void *op_data)
herr_t
H5SL_close_common(H5SL_t *slist, H5SL_operator_t op, void *op_data)
{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_close_common);
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_close_common)
/* Check args */
- assert(slist);
+ HDassert(slist);
/* Check internal consistency */
/* (Pre-condition) */
/* Free skip list nodes */
- (void)H5SL_release_common(slist,op,op_data); /* always succeeds */
+ (void)H5SL_release_common(slist, op, op_data); /* always succeeds */
/* Release header node */
- H5FL_ARR_FREE(H5SL_node_ptr_t,slist->header);
+ H5FL_ARR_FREE(H5SL_node_ptr_t, slist->header);
/* Free skip list object */
- H5FL_FREE(H5SL_t,slist);
+ (void)H5FL_FREE(H5SL_t, slist);
- FUNC_LEAVE_NOAPI(SUCCEED);
+ FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5SL_close_common() */
@@ -561,7 +602,7 @@ H5SL_close_common(H5SL_t *slist, H5SL_operator_t op, void *op_data)
H5SL_t *
H5SL_create(H5SL_type_t type, double p, size_t max_level)
{
- H5SL_t *new_slist=NULL; /* Pointer to new skip list object created */
+ H5SL_t *new_slist = NULL; /* Pointer to new skip list object created */
H5SL_node_t *header; /* Pointer to skip list header node */
size_t u; /* Local index variable */
H5SL_t *ret_value; /* Return value */
@@ -571,49 +612,48 @@ H5SL_create(H5SL_type_t type, double p, size_t max_level)
/* Check args */
HDassert(p>0.0 && p<1.0);
HDassert(max_level>0 && max_level<=H5SL_LEVEL_MAX);
- HDassert(type>=H5SL_TYPE_INT && type<=H5SL_TYPE_SIZE);
+ HDassert(type>=H5SL_TYPE_INT && type<=H5SL_TYPE_OBJ);
/* Allocate skip list structure */
- if((new_slist=H5FL_MALLOC(H5SL_t))==NULL)
- HGOTO_ERROR(H5E_SLIST,H5E_NOSPACE,NULL,"memory allocation failed");
+ if(NULL == (new_slist = H5FL_MALLOC(H5SL_t)))
+ HGOTO_ERROR(H5E_SLIST, H5E_NOSPACE, NULL, "memory allocation failed")
/* Set the static internal fields */
- new_slist->type=type;
- new_slist->p=p;
- new_slist->p1=(int)(p*RAND_MAX);
- new_slist->max_level=max_level;
+ new_slist->type = type;
+ new_slist->p = p;
+ new_slist->p1 = (int)(p*RAND_MAX);
+ new_slist->max_level = max_level;
/* Set the dynamic internal fields */
- new_slist->curr_level=-1;
- new_slist->nobjs=0;
+ new_slist->curr_level = -1;
+ new_slist->nobjs = 0;
/* Allocate the header node */
- if((header=H5SL_new_node(max_level-1,NULL,NULL))==NULL)
- HGOTO_ERROR(H5E_SLIST,H5E_NOSPACE,NULL,"memory allocation failed");
+ if(NULL == (header = H5SL_new_node((max_level - 1), NULL, NULL, ULONG_MAX)))
+ HGOTO_ERROR(H5E_SLIST ,H5E_NOSPACE, NULL, "can't create new skip list node")
/* Initialize header node's forward pointers */
- for(u=0; u<max_level; u++)
- header->forward[u]=NULL;
+ for(u = 0; u < max_level; u++)
+ header->forward[u] = NULL;
/* Initialize header node's backward pointer */
- header->backward=NULL;
+ header->backward = NULL;
/* Attach the header */
- new_slist->header=header;
- new_slist->last=header;
+ new_slist->header = header;
+ new_slist->last = header;
/* Set the return value */
- ret_value=new_slist;
+ ret_value = new_slist;
done:
/* Error cleanup */
- if(ret_value==NULL) {
- if(new_slist!=NULL) {
- H5FL_FREE(H5SL_t,new_slist);
- } /* end if */
+ if(ret_value == NULL) {
+ if(new_slist != NULL)
+ (void)H5FL_FREE(H5SL_t, new_slist);
} /* end if */
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5SL_create() */
@@ -764,16 +804,15 @@ void *
H5SL_remove(H5SL_t *slist, const void *key)
{
H5SL_node_t **update[H5SL_LEVEL_MAX]; /* 'update' vector */
- H5SL_node_t *checked; /* Pointer to last node checked */
H5SL_node_t *x; /* Current node to examine */
- int i; /* Local index value */
- void *ret_value=NULL; /* Return value */
+ uint32_t hashval = 0; /* Hash value for key */
+ void *ret_value = NULL; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_remove);
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_remove)
/* Check args */
- assert(slist);
- assert(key);
+ HDassert(slist);
+ HDassert(key);
/* Check internal consistency */
/* (Pre-condition) */
@@ -783,35 +822,42 @@ H5SL_remove(H5SL_t *slist, const void *key)
/* Work through the forward pointers for a node, finding the node at each
* level that is before the location to remove
*/
- x=slist->header;
+ x = slist->header;
switch(slist->type) {
case H5SL_TYPE_INT:
- H5SL_REMOVE(SCALAR, slist, x, update, i, const int, key, checked)
+ H5SL_REMOVE(SCALAR, slist, x, update, const int, key, -)
break;
case H5SL_TYPE_HADDR:
- H5SL_REMOVE(SCALAR, slist, x, update, i, const haddr_t, key, checked)
+ H5SL_REMOVE(SCALAR, slist, x, update, const haddr_t, key, -)
break;
case H5SL_TYPE_STR:
- H5SL_REMOVE(STRING, slist, x, update, i, char *, key, checked)
+ H5SL_REMOVE(STRING, slist, x, update, char *, key, hashval)
break;
case H5SL_TYPE_HSIZE:
- H5SL_REMOVE(SCALAR, slist, x, update, i, const hsize_t, key, checked)
+ H5SL_REMOVE(SCALAR, slist, x, update, const hsize_t, key, -)
break;
case H5SL_TYPE_UNSIGNED:
- H5SL_REMOVE(SCALAR, slist, x, update, i, const unsigned, key, checked)
+ H5SL_REMOVE(SCALAR, slist, x, update, const unsigned, key, -)
break;
case H5SL_TYPE_SIZE:
- H5SL_REMOVE(SCALAR, slist, x, update, i, const size_t, key, checked)
+ H5SL_REMOVE(SCALAR, slist, x, update, const size_t, key, -)
+ break;
+
+ case H5SL_TYPE_OBJ:
+ H5SL_REMOVE(OBJ, slist, x, update, const H5_obj_t, key, -)
break;
+
+ default:
+ HDassert(0 && "Unknown skiplist type!");
} /* end switch */
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5SL_remove() */
@@ -911,9 +957,8 @@ H5SL_remove_first(H5SL_t *slist)
void *
H5SL_search(H5SL_t *slist, const void *key)
{
- H5SL_node_t *checked; /* Pointer to last node checked */
H5SL_node_t *x; /* Current node to examine */
- int i; /* Local index value */
+ uint32_t hashval = 0; /* Hash value for key */
void *ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_search);
@@ -933,28 +978,35 @@ H5SL_search(H5SL_t *slist, const void *key)
x=slist->header;
switch(slist->type) {
case H5SL_TYPE_INT:
- H5SL_SEARCH(SCALAR, slist, x, -, i, const int, key, checked)
+ H5SL_SEARCH(SCALAR, slist, x, -, const int, key, -)
break;
case H5SL_TYPE_HADDR:
- H5SL_SEARCH(SCALAR, slist, x, -, i, const haddr_t, key, checked)
+ H5SL_SEARCH(SCALAR, slist, x, -, const haddr_t, key, -)
break;
case H5SL_TYPE_STR:
- H5SL_SEARCH(STRING, slist, x, -, i, char *, key, checked)
+ H5SL_SEARCH(STRING, slist, x, -, char *, key, hashval)
break;
case H5SL_TYPE_HSIZE:
- H5SL_SEARCH(SCALAR, slist, x, -, i, const hsize_t, key, checked)
+ H5SL_SEARCH(SCALAR, slist, x, -, const hsize_t, key, -)
break;
case H5SL_TYPE_UNSIGNED:
- H5SL_SEARCH(SCALAR, slist, x, -, i, const unsigned, key, checked)
+ H5SL_SEARCH(SCALAR, slist, x, -, const unsigned, key, -)
break;
case H5SL_TYPE_SIZE:
- H5SL_SEARCH(SCALAR, slist, x, -, i, const size_t, key, checked)
+ H5SL_SEARCH(SCALAR, slist, x, -, const size_t, key, -)
+ break;
+
+ case H5SL_TYPE_OBJ:
+ H5SL_SEARCH(OBJ, slist, x, -, const H5_obj_t, key, -)
break;
+
+ default:
+ HDassert(0 && "Unknown skiplist type!");
} /* end switch */
/* 'key' must not have been found in list, if we get here */
@@ -990,9 +1042,8 @@ done:
void *
H5SL_less(H5SL_t *slist, const void *key)
{
- H5SL_node_t *checked; /* Pointer to last node checked */
H5SL_node_t *x; /* Current node to examine */
- int i; /* Local index value */
+ uint32_t hashval = 0; /* Hash value for key */
void *ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_less);
@@ -1012,28 +1063,35 @@ H5SL_less(H5SL_t *slist, const void *key)
x=slist->header;
switch(slist->type) {
case H5SL_TYPE_INT:
- H5SL_SEARCH(SCALAR, slist, x, -, i, const int, key, checked)
+ H5SL_SEARCH(SCALAR, slist, x, -, const int, key, -)
break;
case H5SL_TYPE_HADDR:
- H5SL_SEARCH(SCALAR, slist, x, -, i, const haddr_t, key, checked)
+ H5SL_SEARCH(SCALAR, slist, x, -, const haddr_t, key, -)
break;
case H5SL_TYPE_STR:
- H5SL_SEARCH(STRING, slist, x, -, i, char *, key, checked)
+ H5SL_SEARCH(STRING, slist, x, -, char *, key, hashval)
break;
case H5SL_TYPE_HSIZE:
- H5SL_SEARCH(SCALAR, slist, x, -, i, const hsize_t, key, checked)
+ H5SL_SEARCH(SCALAR, slist, x, -, const hsize_t, key, -)
break;
case H5SL_TYPE_UNSIGNED:
- H5SL_SEARCH(SCALAR, slist, x, -, i, const unsigned, key, checked)
+ H5SL_SEARCH(SCALAR, slist, x, -, const unsigned, key, -)
break;
case H5SL_TYPE_SIZE:
- H5SL_SEARCH(SCALAR, slist, x, -, i, const size_t, key, checked)
+ H5SL_SEARCH(SCALAR, slist, x, -, const size_t, key, -)
+ break;
+
+ case H5SL_TYPE_OBJ:
+ H5SL_SEARCH(OBJ, slist, x, -, const H5_obj_t, key, -)
break;
+
+ default:
+ HDassert(0 && "Unknown skiplist type!");
} /* end switch */
/* An exact match for 'key' must not have been found in list, if we get here */
@@ -1082,9 +1140,8 @@ done:
void *
H5SL_greater(H5SL_t *slist, const void *key)
{
- H5SL_node_t *checked; /* Pointer to last node checked */
H5SL_node_t *x; /* Current node to examine */
- int i; /* Local index value */
+ uint32_t hashval = 0; /* Hash value for key */
void *ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_greater);
@@ -1104,28 +1161,35 @@ H5SL_greater(H5SL_t *slist, const void *key)
x = slist->header;
switch(slist->type) {
case H5SL_TYPE_INT:
- H5SL_SEARCH(SCALAR, slist, x, -, i, const int, key, checked)
+ H5SL_SEARCH(SCALAR, slist, x, -, const int, key, -)
break;
case H5SL_TYPE_HADDR:
- H5SL_SEARCH(SCALAR, slist, x, -, i, const haddr_t, key, checked)
+ H5SL_SEARCH(SCALAR, slist, x, -, const haddr_t, key, -)
break;
case H5SL_TYPE_STR:
- H5SL_SEARCH(STRING, slist, x, -, i, char *, key, checked)
+ H5SL_SEARCH(STRING, slist, x, -, char *, key, hashval)
break;
case H5SL_TYPE_HSIZE:
- H5SL_SEARCH(SCALAR, slist, x, -, i, const hsize_t, key, checked)
+ H5SL_SEARCH(SCALAR, slist, x, -, const hsize_t, key, -)
break;
case H5SL_TYPE_UNSIGNED:
- H5SL_SEARCH(SCALAR, slist, x, -, i, const unsigned, key, checked)
+ H5SL_SEARCH(SCALAR, slist, x, -, const unsigned, key, -)
break;
case H5SL_TYPE_SIZE:
- H5SL_SEARCH(SCALAR, slist, x, -, i, const size_t, key, checked)
+ H5SL_SEARCH(SCALAR, slist, x, -, const size_t, key, -)
break;
+
+ case H5SL_TYPE_OBJ:
+ H5SL_SEARCH(OBJ, slist, x, -, const H5_obj_t, key, -)
+ break;
+
+ default:
+ HDassert(0 && "Unknown skiplist type!");
} /* end switch */
/* An exact match for 'key' must not have been found in list, if we get here */
@@ -1164,9 +1228,8 @@ done:
H5SL_node_t *
H5SL_find(H5SL_t *slist, const void *key)
{
- H5SL_node_t *checked; /* Pointer to last node checked */
H5SL_node_t *x; /* Current node to examine */
- int i; /* Local index value */
+ uint32_t hashval = 0; /* Hash value for key */
H5SL_node_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_find);
@@ -1186,28 +1249,35 @@ H5SL_find(H5SL_t *slist, const void *key)
x=slist->header;
switch(slist->type) {
case H5SL_TYPE_INT:
- H5SL_FIND(SCALAR, slist, x, -, i, const int, key, checked)
+ H5SL_FIND(SCALAR, slist, x, -, const int, key, -)
break;
case H5SL_TYPE_HADDR:
- H5SL_FIND(SCALAR, slist, x, -, i, const haddr_t, key, checked)
+ H5SL_FIND(SCALAR, slist, x, -, const haddr_t, key, -)
break;
case H5SL_TYPE_STR:
- H5SL_FIND(STRING, slist, x, -, i, char *, key, checked)
+ H5SL_FIND(STRING, slist, x, -, char *, key, hashval)
break;
case H5SL_TYPE_HSIZE:
- H5SL_FIND(SCALAR, slist, x, -, i, const hsize_t, key, checked)
+ H5SL_FIND(SCALAR, slist, x, -, const hsize_t, key, -)
break;
case H5SL_TYPE_UNSIGNED:
- H5SL_FIND(SCALAR, slist, x, -, i, const unsigned, key, checked)
+ H5SL_FIND(SCALAR, slist, x, -, const unsigned, key, -)
break;
case H5SL_TYPE_SIZE:
- H5SL_FIND(SCALAR, slist, x, -, i, const size_t, key, checked)
+ H5SL_FIND(SCALAR, slist, x, -, const size_t, key, -)
+ break;
+
+ case H5SL_TYPE_OBJ:
+ H5SL_FIND(OBJ, slist, x, -, const H5_obj_t, key, -)
break;
+
+ default:
+ HDassert(0 && "Unknown skiplist type!");
} /* end switch */
/* 'key' must not have been found in list, if we get here */
@@ -1220,6 +1290,187 @@ done:
/*--------------------------------------------------------------------------
NAME
+ H5SL_below
+ PURPOSE
+ Search for _node_ in a skip list whose object is less than or equal to 'key'
+ USAGE
+ H5SL_node_t *H5SL_below(slist, key)
+ H5SL_t *slist; IN/OUT: Pointer to skip list
+ void *key; IN: Key for item to search for
+
+ RETURNS
+ Returns pointer to _node_ who key is less than or equal to 'key' on success,
+ NULL on failure
+ DESCRIPTION
+ Search for a node with an object in a skip list, according to it's key,
+ returning the node itself (for an exact match), or the node with the next
+ highest key that is less than 'key'
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+H5SL_node_t *
+H5SL_below(H5SL_t *slist, const void *key)
+{
+ H5SL_node_t *x; /* Current node to examine */
+ uint32_t hashval = 0; /* Hash value for key */
+ H5SL_node_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_below)
+
+ /* Check args */
+ HDassert(slist);
+ HDassert(key);
+
+ /* Check internal consistency */
+ /* (Pre-condition) */
+
+ /* Insert item into skip list */
+
+ /* Work through the forward pointers for a node, finding the node at each
+ * level that is before the location to insert
+ */
+ x = slist->header;
+ switch(slist->type) {
+ case H5SL_TYPE_INT:
+ H5SL_FIND(SCALAR, slist, x, -, const int, key, -)
+ break;
+
+ case H5SL_TYPE_HADDR:
+ H5SL_FIND(SCALAR, slist, x, -, const haddr_t, key, -)
+ break;
+
+ case H5SL_TYPE_STR:
+ H5SL_FIND(STRING, slist, x, -, char *, key, hashval)
+ break;
+
+ case H5SL_TYPE_HSIZE:
+ H5SL_FIND(SCALAR, slist, x, -, const hsize_t, key, -)
+ break;
+
+ case H5SL_TYPE_UNSIGNED:
+ H5SL_FIND(SCALAR, slist, x, -, const unsigned, key, -)
+ break;
+
+ case H5SL_TYPE_SIZE:
+ H5SL_FIND(SCALAR, slist, x, -, const size_t, key, -)
+ break;
+
+ case H5SL_TYPE_OBJ:
+ H5SL_FIND(OBJ, slist, x, -, const H5_obj_t, key, -)
+ break;
+ } /* end switch */
+
+ /* An exact match for 'key' must not have been found in list, if we get here */
+ /* Check for a node with a key that is less than the given 'key' */
+ if(NULL == x) {
+ /* Check for walking off the list */
+ if(slist->last != slist->header)
+ ret_value = slist->last;
+ else
+ ret_value = NULL;
+ } /* end if */
+ else {
+ if(x->backward != slist->header)
+ ret_value = x->backward;
+ else
+ ret_value = NULL;
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5SL_below() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5SL_above
+ PURPOSE
+ Search for _node_ in a skip list whose object is greater than or equal to 'key'
+ USAGE
+ H5SL_node_t *H5SL_above(slist, key)
+ H5SL_t *slist; IN/OUT: Pointer to skip list
+ void *key; IN: Key for item to search for
+
+ RETURNS
+ Returns pointer to _node_ with object that has a key is greater than or
+ equal to 'key' on success, NULL on failure
+ DESCRIPTION
+ Search for a node with an object in a skip list, according to it's key,
+ returning the node itself (for an exact match), or the node with the next
+ lowest key that is greater than 'key'
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+H5SL_node_t *
+H5SL_above(H5SL_t *slist, const void *key)
+{
+ H5SL_node_t *x; /* Current node to examine */
+ uint32_t hashval = 0; /* Hash value for key */
+ H5SL_node_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_above)
+
+ /* Check args */
+ HDassert(slist);
+ HDassert(key);
+
+ /* Check internal consistency */
+ /* (Pre-condition) */
+
+ /* Insert item into skip list */
+
+ /* Work through the forward pointers for a node, finding the node at each
+ * level that is before the location to insert
+ */
+ x = slist->header;
+ switch(slist->type) {
+ case H5SL_TYPE_INT:
+ H5SL_FIND(SCALAR, slist, x, -, const int, key, -)
+ break;
+
+ case H5SL_TYPE_HADDR:
+ H5SL_FIND(SCALAR, slist, x, -, const haddr_t, key, -)
+ break;
+
+ case H5SL_TYPE_STR:
+ H5SL_FIND(STRING, slist, x, -, char *, key, hashval)
+ break;
+
+ case H5SL_TYPE_HSIZE:
+ H5SL_FIND(SCALAR, slist, x, -, const hsize_t, key, -)
+ break;
+
+ case H5SL_TYPE_UNSIGNED:
+ H5SL_FIND(SCALAR, slist, x, -, const unsigned, key, -)
+ break;
+
+ case H5SL_TYPE_SIZE:
+ H5SL_FIND(SCALAR, slist, x, -, const size_t, key, -)
+ break;
+
+ case H5SL_TYPE_OBJ:
+ H5SL_FIND(OBJ, slist, x, -, const H5_obj_t, key, -)
+ break;
+ } /* end switch */
+
+ /* An exact match for 'key' must not have been found in list, if we get here */
+ /* ('x' must be the next node with a key greater than the 'key', or NULL) */
+ if(x)
+ ret_value = x;
+ else
+ ret_value = NULL;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5SL_above() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
H5SL_first
PURPOSE
Gets a pointer to the first node in a skip list
@@ -1426,28 +1677,28 @@ herr_t
H5SL_iterate(H5SL_t *slist, H5SL_operator_t op, void *op_data)
{
H5SL_node_t *node; /* Pointers to skip list nodes */
- herr_t ret_value=0; /* Return value */
+ herr_t ret_value = 0; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_iterate);
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_iterate)
/* Check args */
- assert(slist);
+ HDassert(slist);
/* Check internal consistency */
/* (Pre-condition) */
/* Free skip list nodes */
- node=slist->header->forward[0];
- while(node!=NULL) {
+ node = slist->header->forward[0];
+ while(node != NULL) {
/* Call the iterator callback */
/* Casting away const OK -QAK */
- if((ret_value=(op)(node->item,(void *)node->key,op_data))!=0)
+ if((ret_value = (op)(node->item, (void *)node->key, op_data)) != 0)
break;
- node=node->forward[0];
+ node = node->forward[0];
} /* end while */
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5SL_iterate() */
diff --git a/src/H5SLprivate.h b/src/H5SLprivate.h
index 98c1b84..27bb4d1 100644
--- a/src/H5SLprivate.h
+++ b/src/H5SLprivate.h
@@ -46,7 +46,8 @@ typedef enum {
H5SL_TYPE_STR, /* Skip list keys are 'char *'s (ie. strings) */
H5SL_TYPE_HSIZE, /* Skip list keys are 'hsize_t's */
H5SL_TYPE_UNSIGNED, /* Skip list keys are 'unsigned's */
- H5SL_TYPE_SIZE /* Skip list keys are 'size_t's */
+ H5SL_TYPE_SIZE, /* Skip list keys are 'size_t's */
+ H5SL_TYPE_OBJ /* Skip list keys are 'H5_obj_t's */
} H5SL_type_t;
/**********/
@@ -71,6 +72,8 @@ H5_DLL void *H5SL_search(H5SL_t *slist, const void *key);
H5_DLL void *H5SL_less(H5SL_t *slist, const void *key);
H5_DLL void *H5SL_greater(H5SL_t *slist, const void *key);
H5_DLL H5SL_node_t *H5SL_find(H5SL_t *slist, const void *key);
+H5_DLL H5SL_node_t *H5SL_below(H5SL_t *slist, const void *key);
+H5_DLL H5SL_node_t *H5SL_above(H5SL_t *slist, const void *key);
H5_DLL H5SL_node_t *H5SL_first(H5SL_t *slist);
H5_DLL H5SL_node_t *H5SL_next(H5SL_node_t *slist_node);
H5_DLL H5SL_node_t *H5SL_prev(H5SL_node_t *slist_node);
diff --git a/src/H5SM.c b/src/H5SM.c
index 179a526..d942399 100755
--- a/src/H5SM.c
+++ b/src/H5SM.c
@@ -70,7 +70,7 @@ static herr_t H5SM_write_mesg(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
unsigned *cache_flags_ptr);
static herr_t H5SM_decr_ref(void *record, void *op_data, hbool_t *changed);
static herr_t H5SM_delete_from_index(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
- H5SM_index_header_t *header, const H5O_shared_t * mesg,
+ H5SM_index_header_t *header, const H5O_shared_t * mesg,
unsigned *cache_flags, void ** /*out*/ encoded_mesg);
static herr_t H5SM_type_to_flag(unsigned type_id, unsigned *type_flag);
static herr_t H5SM_read_iter_op(H5O_t *oh, H5O_mesg_t *mesg, unsigned sequence,
@@ -220,7 +220,7 @@ H5SM_init(H5F_t *f, H5P_genplist_t * fc_plist, const H5O_loc_t *ext_loc, hid_t d
/* Check for sharing attributes in this file, which means that creation
* indices must be tracked on object header message in the file.
*/
- if(type_flags_used & H5O_MESG_ATTR_FLAG)
+ if(type_flags_used & H5O_SHMESG_ATTR_FLAG)
f->shared->store_msg_crt_idx = TRUE;
/* Write shared message information to the superblock extension */
@@ -235,7 +235,7 @@ done:
if(table_addr != HADDR_UNDEF)
H5MF_xfree(f, H5FD_MEM_SOHM_TABLE, dxpl_id, table_addr, (hsize_t)H5SM_TABLE_SIZE(f));
if(table != NULL)
- H5FL_FREE(H5SM_master_table_t, table);
+ (void)H5FL_FREE(H5SM_master_table_t, table);
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
@@ -263,22 +263,18 @@ H5SM_type_to_flag(unsigned type_id, unsigned *type_flag)
/* Translate the H5O type_id into an H5SM type flag */
switch(type_id) {
+ case H5O_FILL_ID:
+ type_id = H5O_FILL_NEW_ID;
+ /* Fall through... */
+
case H5O_SDSPACE_ID:
- *type_flag = H5O_MESG_SDSPACE_FLAG;
- break;
case H5O_DTYPE_ID:
- *type_flag = H5O_MESG_DTYPE_FLAG;
- break;
- case H5O_FILL_ID:
case H5O_FILL_NEW_ID:
- *type_flag = H5O_MESG_FILL_FLAG;
- break;
case H5O_PLINE_ID:
- *type_flag = H5O_MESG_PLINE_FLAG;
- break;
case H5O_ATTR_ID:
- *type_flag = H5O_MESG_ATTR_FLAG;
+ *type_flag = (unsigned)1 << type_id;
break;
+
default:
HGOTO_ERROR(H5E_OHDR, H5E_BADTYPE, FAIL, "unknown message type ID")
} /* end switch */
@@ -307,7 +303,7 @@ done:
ssize_t
H5SM_get_index(const H5SM_master_table_t *table, unsigned type_id)
{
- ssize_t x;
+ size_t x;
unsigned type_flag;
ssize_t ret_value = FAIL;
@@ -322,7 +318,7 @@ H5SM_get_index(const H5SM_master_table_t *table, unsigned type_id)
*/
for(x = 0; x < table->num_indexes; ++x)
if(table->indexes[x].mesg_types & type_flag)
- HGOTO_DONE(x)
+ HGOTO_DONE((ssize_t)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.
@@ -533,23 +529,31 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5SM_delete_index(H5F_t *f, H5SM_index_header_t *header, hid_t dxpl_id, hbool_t delete_heap)
+H5SM_delete_index(H5F_t *f, H5SM_index_header_t *header, hid_t dxpl_id,
+ hbool_t delete_heap)
{
- hsize_t list_size; /* Size of list on disk */
- herr_t ret_value = SUCCEED;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5SM_delete_index)
/* Determine whether index is a list or a B-tree. */
if(header->index_type == H5SM_LIST) {
- /* Eject entry from cache */
- if(H5AC_expunge_entry(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "unable to remove list index from cache")
-
- /* Free the file space used */
- list_size = H5SM_LIST_SIZE(f, header->list_max);
- if(H5MF_xfree(f, H5FD_MEM_SOHM_INDEX, dxpl_id, header->index_addr, list_size) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to free shared message list")
+ unsigned index_status = 0; /* Index list's status in the metadata cache */
+
+ /* Check the index list's status in the metadata cache */
+ if(H5AC_get_entry_status(f, header->index_addr, &index_status) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to check metadata cache status for direct block")
+
+ /* If the index list is in the cache, expunge it now */
+ if(index_status & H5AC_ES__IN_CACHE) {
+ /* Sanity checks on index list */
+ HDassert(!(index_status & H5AC_ES__IS_PINNED));
+ HDassert(!(index_status & H5AC_ES__IS_PROTECTED));
+
+ /* Evict the index list from the metadata cache */
+ if(H5AC_expunge_entry(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, H5AC__FREE_FILE_SPACE_FLAG) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "unable to remove list index from cache")
+ } /* end if */
} /* end if */
else {
HDassert(header->index_type == H5SM_BTREE);
@@ -642,7 +646,7 @@ done:
if(list != NULL) {
if(list->messages != NULL)
H5FL_ARR_FREE(H5SM_sohm_t, list->messages);
- H5FL_FREE(H5SM_list_t, list);
+ (void)H5FL_FREE(H5SM_list_t, list);
} /* end if */
if(addr != HADDR_UNDEF)
H5MF_xfree(f, H5FD_MEM_SOHM_INDEX, dxpl_id, addr, size);
@@ -731,7 +735,7 @@ H5SM_convert_list_to_btree(H5F_t *f, H5SM_index_header_t *header,
} /* end for */
/* Unprotect list in cache and release heap */
- if(H5AC_unprotect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, list, H5AC__DELETED_FLAG) < 0)
+ if(H5AC_unprotect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, list, H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "unable to release SOHM list")
*_list = list = NULL;
@@ -1586,8 +1590,6 @@ H5SM_delete_from_index(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
H5HF_t *fheap = NULL; /* Fractal heap that contains the message */
size_t buf_size; /* Size of the encoded message (out) */
void *encoding_buf = NULL; /* The encoded message (out) */
- H5O_loc_t oloc; /* Object location for message in object header */
- H5O_t *oh = NULL; /* Object header for message in object header */
unsigned type_id; /* Message type to operate on */
herr_t ret_value = SUCCEED;
@@ -1697,7 +1699,7 @@ H5SM_delete_from_index(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
if(header->num_messages == 0) {
/* Unprotect cache and release heap */
- if(list && H5AC_unprotect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, list, H5AC__DELETED_FLAG) < 0)
+ if(list && H5AC_unprotect(f, dxpl_id, H5AC_SOHM_LIST, header->index_addr, list, H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, "unable to release SOHM list")
list = NULL;
@@ -1720,15 +1722,6 @@ H5SM_delete_from_index(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
} /* end if */
done:
- /* Unprotect & close the object header if we opened one */
- if(oh && oh != open_oh) {
- if(H5AC_unprotect(oloc.file, dxpl_id, H5AC_OHDR, oloc.addr, oh, H5AC__NO_FLAGS_SET) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header")
-
- if(H5O_close(&oloc) < 0)
- HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to close object header")
- } /* end if */
-
/* 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")
@@ -1766,6 +1759,7 @@ H5SM_get_info(const H5O_loc_t *ext_loc, H5P_genplist_t *fc_plist, hid_t dxpl_id)
H5F_file_t *shared = f->shared; /* Shared file info (convenience variable) */
H5O_shmesg_table_t sohm_table; /* SOHM message from superblock extension */
H5SM_master_table_t *table = NULL; /* SOHM master table */
+ htri_t status; /* Status for message existing */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5SM_get_info, FAIL)
@@ -1775,27 +1769,20 @@ H5SM_get_info(const H5O_loc_t *ext_loc, H5P_genplist_t *fc_plist, hid_t dxpl_id)
HDassert(f && shared);
HDassert(fc_plist);
- /* Read in shared message information, if it exists */
- if(NULL == H5O_msg_read(ext_loc, H5O_SHMESG_ID, &sohm_table, dxpl_id)) {
- /* Reset error from "failed" message read */
- H5E_clear_stack(NULL);
-
- /* No SOHM info in file */
- shared->sohm_addr = HADDR_UNDEF;
- shared->sohm_nindexes = 0;
- shared->sohm_vers = 0;
-
- /* Shared object header messages are disabled */
- if(H5P_set(fc_plist, H5F_CRT_SHMSG_NINDEXES_NAME, &shared->sohm_nindexes) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set number of SOHM indexes")
- } /* end if */
- else {
+ /* Check for the extension having a 'shared message info' message */
+ if((status = H5O_msg_exists(ext_loc, H5O_SHMESG_ID, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to read object header")
+ if(status) {
unsigned index_flags[H5O_SHMESG_MAX_NINDEXES]; /* Message flags for each index */
unsigned minsizes[H5O_SHMESG_MAX_NINDEXES]; /* Minimum message size for each index */
unsigned sohm_l2b; /* SOHM list-to-btree cutoff */
unsigned sohm_b2l; /* SOHM btree-to-list cutoff */
unsigned u; /* Local index variable */
+ /* Retrieve the 'shared message info' structure */
+ if(NULL == H5O_msg_read(ext_loc, H5O_SHMESG_ID, &sohm_table, dxpl_id))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "shared message info message not present")
+
/* Portably initialize the arrays */
HDmemset(index_flags, 0, sizeof(index_flags));
HDmemset(minsizes, 0, sizeof(minsizes));
@@ -1828,7 +1815,7 @@ H5SM_get_info(const H5O_loc_t *ext_loc, H5P_genplist_t *fc_plist, hid_t dxpl_id)
/* Check for sharing attributes in this file, which means that creation
* indices must be tracked on object header message in the file.
*/
- if(index_flags[u] & H5O_MESG_ATTR_FLAG)
+ if(index_flags[u] & H5O_SHMESG_ATTR_FLAG)
shared->store_msg_crt_idx = TRUE;
} /* end for */
@@ -1843,6 +1830,16 @@ H5SM_get_info(const H5O_loc_t *ext_loc, H5P_genplist_t *fc_plist, hid_t dxpl_id)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set SOHM cutoff in property list")
if(H5P_set(fc_plist, H5F_CRT_SHMSG_BTREE_MIN_NAME, &sohm_b2l) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set SOHM cutoff in property list")
+ } /* end if */
+ else {
+ /* No SOHM info in file */
+ shared->sohm_addr = HADDR_UNDEF;
+ shared->sohm_nindexes = 0;
+ shared->sohm_vers = 0;
+
+ /* Shared object header messages are disabled */
+ if(H5P_set(fc_plist, H5F_CRT_SHMSG_NINDEXES_NAME, &shared->sohm_nindexes) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set number of SOHM indexes")
} /* end else */
done:
@@ -2014,7 +2011,7 @@ H5SM_get_refcount_bt2_cb(const void *_record, void *_op_data)
herr_t
H5SM_get_refcount(H5F_t *f, hid_t dxpl_id, unsigned type_id,
const H5O_shared_t *sh_mesg, hsize_t *ref_count)
-{
+{
H5HF_t *fheap = NULL; /* Fractal heap that contains shared messages */
H5SM_master_table_t *table = NULL; /* SOHM master table */
H5SM_list_t *list = NULL; /* SOHM index list for message type (if in list form) */
@@ -2079,11 +2076,15 @@ H5SM_get_refcount(H5F_t *f, hid_t dxpl_id, unsigned type_id,
message = list->messages[list_pos];
} /* end if */
else {
+ htri_t msg_exists; /* Whether the message exists in the v2 B-tree */
+
/* Index is a B-tree */
HDassert(header->index_type == H5SM_BTREE);
/* Look up the message in the v2 B-tree */
- if(H5B2_find(f, dxpl_id, H5SM_INDEX, header->index_addr, &key, H5SM_get_refcount_bt2_cb, &message) < 0)
+ if((msg_exists = H5B2_find(f, dxpl_id, H5SM_INDEX, header->index_addr, &key, H5SM_get_refcount_bt2_cb, &message)) < 0)
+ HGOTO_ERROR(H5E_SOHM, H5E_CANTGET, FAIL, "error finding message in index")
+ if(!msg_exists)
HGOTO_ERROR(H5E_SOHM, H5E_NOTFOUND, FAIL, "message not in index")
} /* end else */
@@ -2261,7 +2262,7 @@ H5SM_read_mesg(H5F_t *f, const H5SM_sohm_t *mesg, H5HF_t *fheap,
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to open object header")
/* Load the object header from the cache */
- if(NULL == (oh = H5AC_protect(oloc.file, dxpl_id, H5AC_OHDR, oloc.addr, NULL, NULL, H5AC_READ)))
+ if(NULL == (oh = (H5O_t *)H5AC_protect(oloc.file, dxpl_id, H5AC_OHDR, oloc.addr, NULL, NULL, H5AC_READ)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
} /* end if */
else
@@ -2481,7 +2482,7 @@ done:
*
* Purpose: Loop through the master SOHM table (if there is one) to:
* 1. collect storage used for header
- * 1. collect storage used for B-tree and List
+ * 1. collect storage used for B-tree and List
* (include btree storage used by huge objects in fractal heap)
* 2. collect fractal heap storage
*
diff --git a/src/H5SMcache.c b/src/H5SMcache.c
index 371344a..91478c5 100644
--- a/src/H5SMcache.c
+++ b/src/H5SMcache.c
@@ -27,6 +27,7 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5Fpkg.h" /* File access */
#include "H5FLprivate.h" /* Free Lists */
+#include "H5MFprivate.h" /* File memory management */
#include "H5MMprivate.h" /* Memory management */
#include "H5SMpkg.h" /* Shared object header messages */
#include "H5WBprivate.h" /* Wrapped Buffers */
@@ -154,7 +155,7 @@ H5SM_table_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *udata1
size = H5SM_TABLE_SIZE(f) + (table->num_indexes * H5SM_INDEX_HEADER_SIZE(f));
/* Get a pointer to a buffer that's large enough for serialized table */
- if(NULL == (buf = H5WB_actual(wb, size)))
+ if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
HGOTO_ERROR(H5E_SOHM, H5E_NOSPACE, NULL, "can't get actual buffer")
/* Read header from disk */
@@ -165,9 +166,9 @@ H5SM_table_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *udata1
p = buf;
/* Check magic number */
- if(HDmemcmp(p, H5SM_TABLE_MAGIC, (size_t)H5SM_SIZEOF_MAGIC))
+ if(HDmemcmp(p, H5SM_TABLE_MAGIC, (size_t)H5_SIZEOF_MAGIC))
HGOTO_ERROR(H5E_SOHM, H5E_CANTLOAD, NULL, "bad SOHM table signature")
- p += H5SM_SIZEOF_MAGIC;
+ p += H5_SIZEOF_MAGIC;
/* Don't count the checksum in the table size yet, since it comes after
* all of the index headers
@@ -233,7 +234,7 @@ done:
(void)H5SM_table_dest(f, table);
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5SM_table_load() */
+} /* end H5SM_table_load() */
/*-------------------------------------------------------------------------
@@ -283,15 +284,15 @@ H5SM_table_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5SM_ma
size = H5SM_TABLE_SIZE(f) + (H5SM_INDEX_HEADER_SIZE(f) * table->num_indexes);
/* Get a pointer to a buffer that's large enough for serialized table */
- if(NULL == (buf = H5WB_actual(wb, size)))
+ if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
HGOTO_ERROR(H5E_SOHM, H5E_NOSPACE, FAIL, "can't get actual buffer")
/* Get temporary pointer to buffer for serialized table */
p = buf;
/* Encode magic number */
- HDmemcpy(p, H5SM_TABLE_MAGIC, (size_t)H5SM_SIZEOF_MAGIC);
- p += H5SM_SIZEOF_MAGIC;
+ HDmemcpy(p, H5SM_TABLE_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ p += H5_SIZEOF_MAGIC;
/* Encode each index header */
for(x = 0; x < table->num_indexes; ++x) {
@@ -371,7 +372,7 @@ H5SM_table_dest(H5F_t UNUSED *f, H5SM_master_table_t* table)
H5FL_ARR_FREE(H5SM_index_header_t, table->indexes);
- H5FL_FREE(H5SM_master_table_t, table);
+ (void)H5FL_FREE(H5SM_master_table_t, table);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5SM_table_dest() */
@@ -493,7 +494,7 @@ H5SM_list_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *udata1,
size = H5SM_LIST_SIZE(f, header->num_messages);
/* Get a pointer to a buffer that's large enough for serialized list index */
- if(NULL == (buf = H5WB_actual(wb, size)))
+ if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
HGOTO_ERROR(H5E_SOHM, H5E_NOSPACE, NULL, "can't get actual buffer")
/* Read list from disk */
@@ -504,9 +505,9 @@ H5SM_list_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *udata1,
p = buf;
/* Check magic number */
- if(HDmemcmp(p, H5SM_LIST_MAGIC, (size_t)H5SM_SIZEOF_MAGIC))
+ if(HDmemcmp(p, H5SM_LIST_MAGIC, (size_t)H5_SIZEOF_MAGIC))
HGOTO_ERROR(H5E_SOHM, H5E_CANTLOAD, NULL, "bad SOHM list signature")
- p += H5SM_SIZEOF_MAGIC;
+ p += H5_SIZEOF_MAGIC;
/* Read messages into the list array */
for(x = 0; x < header->num_messages; x++) {
@@ -542,7 +543,7 @@ done:
if(!ret_value && list) {
if(list->messages)
H5FL_ARR_FREE(H5SM_sohm_t, list->messages);
- H5FL_FREE(H5SM_list_t, list);
+ (void)H5FL_FREE(H5SM_list_t, list);
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
@@ -591,15 +592,15 @@ H5SM_list_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5SM_lis
size = H5SM_LIST_SIZE(f, list->header->num_messages);
/* Get a pointer to a buffer that's large enough for serialized list index */
- if(NULL == (buf = H5WB_actual(wb, size)))
+ if(NULL == (buf = (uint8_t *)H5WB_actual(wb, size)))
HGOTO_ERROR(H5E_SOHM, H5E_NOSPACE, FAIL, "can't get actual buffer")
/* Get temporary pointer to buffer for serialized list index */
p = buf;
/* Encode magic number */
- HDmemcpy(p, H5SM_LIST_MAGIC, (size_t)H5SM_SIZEOF_MAGIC);
- p += H5SM_SIZEOF_MAGIC;
+ HDmemcpy(p, H5SM_LIST_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ p += H5_SIZEOF_MAGIC;
/* Write messages from the messages array to disk */
mesgs_written = 0;
@@ -652,18 +653,34 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5SM_list_dest(H5F_t UNUSED *f, H5SM_list_t* list)
+H5SM_list_dest(H5F_t *f, H5SM_list_t* list)
{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SM_list_dest)
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5SM_list_dest)
+ /* Sanity check */
HDassert(list);
+ HDassert(list->header);
HDassert(list->messages);
- H5FL_ARR_FREE(H5SM_sohm_t, list->messages);
+ /* If we're going to free the space on disk, the address must be valid */
+ HDassert(!list->cache_info.free_file_space_on_destroy || H5F_addr_defined(list->cache_info.addr));
+
+ /* Check for freeing file space for shared message index list */
+ if(list->cache_info.free_file_space_on_destroy) {
+ /* Release the space on disk */
+ /* (XXX: Nasty usage of internal DXPL value! -QAK) */
+ if(H5MF_xfree(f, H5FD_MEM_SOHM_INDEX, H5AC_dxpl_id, list->cache_info.addr, (hsize_t)H5SM_LIST_SIZE(f, list->header->list_max)) < 0)
+ HGOTO_ERROR(H5E_SOHM, H5E_NOSPACE, FAIL, "unable to free shared message list")
+ } /* end if */
- H5FL_FREE(H5SM_list_t, list);
+ /* Release resources */
+ H5FL_ARR_FREE(H5SM_sohm_t, list->messages);
+ (void)H5FL_FREE(H5SM_list_t, list);
- FUNC_LEAVE_NOAPI(SUCCEED)
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5SM_list_dest() */
diff --git a/src/H5SMpkg.h b/src/H5SMpkg.h
index 8d987a9..dc69b2b 100755
--- a/src/H5SMpkg.h
+++ b/src/H5SMpkg.h
@@ -40,13 +40,6 @@
/* Package Macros */
/****************************/
-/* Size of signature information (on disk) */
-#define H5SM_SIZEOF_MAGIC 4
-
-/* Shared Message signatures */
-#define H5SM_TABLE_MAGIC "SMTB" /* Shared Message Table */
-#define H5SM_LIST_MAGIC "SMLI" /* Shared Message List */
-
/* Size of checksum information (on disk) */
#define H5SM_SIZEOF_CHECKSUM 4
@@ -69,7 +62,7 @@
)
#define H5SM_TABLE_SIZE(f) ( \
- H5SM_SIZEOF_MAGIC /* Signature */ \
+ H5_SIZEOF_MAGIC /* Signature */ \
+ H5SM_SIZEOF_CHECKSUM /* Checksum */ \
)
@@ -84,7 +77,7 @@
)
#define H5SM_LIST_SIZE(f, num_mesg) ( \
- H5SM_SIZEOF_MAGIC /* Signature */ \
+ H5_SIZEOF_MAGIC /* Signature */ \
+ (H5SM_SOHM_ENTRY_SIZE(f) * num_mesg) /* Message entries */ \
+ H5SM_SIZEOF_CHECKSUM /* Checksum */ \
)
diff --git a/src/H5SMtest.c b/src/H5SMtest.c
index 5de8ce1..8412a89 100644
--- a/src/H5SMtest.c
+++ b/src/H5SMtest.c
@@ -78,7 +78,7 @@
herr_t
H5SM_get_mesg_count_test(H5F_t *f, hid_t dxpl_id, unsigned type_id,
size_t *mesg_count)
-{
+{
H5SM_master_table_t *table = NULL; /* SOHM master table */
herr_t ret_value = SUCCEED; /* Return value */
diff --git a/src/H5ST.c b/src/H5ST.c
index f36855e..7dee73f 100644
--- a/src/H5ST.c
+++ b/src/H5ST.c
@@ -87,18 +87,18 @@ done:
static herr_t
H5ST_close_internal(H5ST_ptr_t p)
{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5ST_close_internal);
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5ST_close_internal)
/* Recursively free TST */
if(p) {
H5ST_close_internal(p->lokid);
- if (p->splitchar)
+ if(p->splitchar)
H5ST_close_internal(p->eqkid);
H5ST_close_internal(p->hikid);
- H5FL_FREE(H5ST_node_t,p);
+ (void)H5FL_FREE(H5ST_node_t, p);
} /* end if */
- FUNC_LEAVE_NOAPI(SUCCEED);
+ FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5ST_close_internal() */
@@ -123,23 +123,23 @@ H5ST_close_internal(H5ST_ptr_t p)
herr_t
H5ST_close(H5ST_tree_t *tree)
{
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5ST_close,FAIL);
+ FUNC_ENTER_NOAPI(H5ST_close, FAIL)
/* Check arguments */
- if(tree==NULL)
- HGOTO_ERROR(H5E_ARGS,H5E_BADVALUE,FAIL,"invalid TST");
+ if(NULL == tree)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid TST")
/* Free the TST itself */
- if(H5ST_close_internal(tree->root)<0)
- HGOTO_ERROR(H5E_TST,H5E_CANTFREE,FAIL,"can't free TST");
+ if(H5ST_close_internal(tree->root) < 0)
+ HGOTO_ERROR(H5E_TST, H5E_CANTFREE, FAIL, "can't free TST")
/* Free root node itself */
- H5FL_FREE(H5ST_tree_t,tree);
+ (void)H5FL_FREE(H5ST_tree_t, tree);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5ST_close() */
@@ -587,53 +587,54 @@ H5ST_delete_internal(H5ST_ptr_t *root, H5ST_ptr_t p)
H5ST_ptr_t q, /* Temporary pointer to TST node */
newp; /* Pointer to node which will replace deleted node in tree */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5ST_delete_internal);
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5ST_delete_internal)
/* Find node to replace one being deleted */
if(p->lokid) {
/* If the deleted node has lo & hi kids, attach them together */
if(p->hikid) {
- q=p->lokid;
+ q = p->lokid;
while(q->hikid)
- q=q->hikid;
- q->hikid=p->hikid;
- p->hikid->parent=q;
+ q = q->hikid;
+ q->hikid = p->hikid;
+ p->hikid->parent = q;
} /* end if */
- newp=p->lokid;
+ newp = p->lokid;
} /* end if */
else if(p->hikid) {
- newp=p->hikid;
+ newp = p->hikid;
} /* end if */
else {
- newp=NULL;
+ newp = NULL;
} /* end else */
/* Deleted node is in middle of tree */
if(p->parent) {
/* Attach new node to correct side of parent */
- if(p==p->parent->lokid)
- p->parent->lokid=newp;
+ if(p == p->parent->lokid)
+ p->parent->lokid = newp;
else
- p->parent->hikid=newp;
+ p->parent->hikid = newp;
if(newp)
- newp->parent=p->parent;
+ newp->parent = p->parent;
} /* end if */
else {
if(newp)
- newp->parent=p->parent;
+ newp->parent = p->parent;
if(p->up) {
- p->up->eqkid=newp;
+ p->up->eqkid = newp;
+
/* If we deleted the last node in the TST, delete the upper node also */
- if(newp==NULL)
- H5ST_delete_internal(root,p->up);
+ if(NULL == newp)
+ H5ST_delete_internal(root, p->up);
} /* end if */
else /* Deleted last node at top level of tree */
- *root=newp;
+ *root = newp;
} /* end else */
- H5FL_FREE(H5ST_node_t,p);
+ (void)H5FL_FREE(H5ST_node_t, p);
- FUNC_LEAVE_NOAPI(SUCCEED);
+ FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5ST_delete_internal() */
diff --git a/src/H5Sall.c b/src/H5Sall.c
index c216323..1c086b9 100644
--- a/src/H5Sall.c
+++ b/src/H5Sall.c
@@ -42,9 +42,11 @@ static hssize_t H5S_all_serial_size(const H5S_t *space);
static herr_t H5S_all_serialize(const H5S_t *space, uint8_t *buf);
static herr_t H5S_all_deserialize(H5S_t *space, const uint8_t *buf);
static herr_t H5S_all_bounds(const H5S_t *space, hsize_t *start, hsize_t *end);
+static herr_t H5S_all_offset(const H5S_t *space, hsize_t *off);
static htri_t H5S_all_is_contiguous(const H5S_t *space);
static htri_t H5S_all_is_single(const H5S_t *space);
static htri_t H5S_all_is_regular(const H5S_t *space);
+static herr_t H5S_all_adjust_u(H5S_t *space, const hsize_t *offset);
static herr_t H5S_all_iter_init(H5S_sel_iter_t *iter, const H5S_t *space);
/* Selection iteration callbacks */
@@ -69,9 +71,11 @@ const H5S_select_class_t H5S_sel_all[1] = {{
H5S_all_serialize,
H5S_all_deserialize,
H5S_all_bounds,
+ H5S_all_offset,
H5S_all_is_contiguous,
H5S_all_is_single,
H5S_all_is_regular,
+ H5S_all_adjust_u,
H5S_all_iter_init,
}};
@@ -583,26 +587,61 @@ done:
herr_t
H5S_all_bounds(const H5S_t *space, hsize_t *start, hsize_t *end)
{
- int rank; /* Dataspace rank */
- int i; /* index variable */
+ unsigned rank; /* Dataspace rank */
+ unsigned i; /* index variable */
- FUNC_ENTER_NOAPI_NOFUNC(H5S_all_bounds);
+ FUNC_ENTER_NOAPI_NOFUNC(H5S_all_bounds)
- assert(space);
- assert(start);
- assert(end);
+ HDassert(space);
+ HDassert(start);
+ HDassert(end);
/* Get the dataspace extent rank */
- rank=space->extent.rank;
+ rank = space->extent.rank;
/* Just copy over the complete extent */
- for(i=0; i<rank; i++) {
- start[i]=0;
- end[i]=space->extent.size[i]-1;
+ for(i = 0; i < rank; i++) {
+ start[i] = 0;
+ end[i] = space->extent.size[i] - 1;
} /* end for */
- FUNC_LEAVE_NOAPI(SUCCEED);
-} /* H5Sget_all_bounds() */
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5S_all_bounds() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S_all_offset
+ PURPOSE
+ Gets the linear offset of the first element for the selection.
+ USAGE
+ herr_t H5S_all_offset(space, offset)
+ const H5S_t *space; IN: Dataspace pointer of selection to query
+ hsize_t *offset; OUT: Linear offset of first element in selection
+ RETURNS
+ Non-negative on success, negative on failure
+ DESCRIPTION
+ Retrieves the linear offset (in "units" of elements) of the first element
+ selected within the dataspace.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Calling this function on a "none" selection returns fail.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5S_all_offset(const H5S_t *space, hsize_t *offset)
+{
+ FUNC_ENTER_NOAPI_NOFUNC(H5S_all_offset)
+
+ HDassert(space);
+ HDassert(offset);
+
+ /* 'All' selections always start at offset 0 */
+ *offset = 0;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5S_all_offset() */
/*--------------------------------------------------------------------------
@@ -696,6 +735,37 @@ H5S_all_is_regular(const H5S_t UNUSED *space)
/*--------------------------------------------------------------------------
NAME
+ H5S_all_adjust_u
+ PURPOSE
+ Adjust an "all" selection by subtracting an offset
+ USAGE
+ herr_t H5S_all_adjust_u(space, offset)
+ H5S_t *space; IN/OUT: Pointer to dataspace to adjust
+ const hsize_t *offset; IN: Offset to subtract
+ RETURNS
+ Non-negative on success, negative on failure
+ DESCRIPTION
+ Moves selection by subtracting an offset from it.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5S_all_adjust_u(H5S_t UNUSED *space, const hsize_t UNUSED *offset)
+{
+ FUNC_ENTER_NOAPI_NOFUNC(H5S_all_adjust_u)
+
+ /* Check args */
+ HDassert(space);
+ HDassert(offset);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5S_all_adjust_u() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
H5S_select_all
PURPOSE
Specify the the entire extent is selected
@@ -755,23 +825,25 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-herr_t H5Sselect_all (hid_t spaceid)
+herr_t
+H5Sselect_all(hid_t spaceid)
{
- H5S_t *space = NULL; /* Dataspace to modify selection of */
- herr_t ret_value=SUCCEED; /* return value */
+ H5S_t *space; /* Dataspace to modify selection of */
+ herr_t ret_value = SUCCEED; /* return value */
- FUNC_ENTER_API(H5Sselect_all, FAIL);
+ FUNC_ENTER_API(H5Sselect_all, FAIL)
+ H5TRACE1("e", "i", spaceid);
/* Check args */
- if (NULL == (space=H5I_object_verify(spaceid, H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space");
+ if(NULL == (space = (H5S_t *)H5I_object_verify(spaceid, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space")
/* Call internal routine to do the work */
if((ret_value = H5S_select_all(space, TRUE)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection")
done:
- FUNC_LEAVE_API(ret_value);
+ FUNC_LEAVE_API(ret_value)
} /* H5Sselect_all() */
diff --git a/src/H5Shyper.c b/src/H5Shyper.c
index ffb03d2..6e8836c 100644
--- a/src/H5Shyper.c
+++ b/src/H5Shyper.c
@@ -23,12 +23,12 @@
#define H5S_PACKAGE /*suppress error about including H5Spkg */
-#include "H5private.h" /* Generic Functions */
-#include "H5Eprivate.h" /* Error handling */
-#include "H5FLprivate.h" /* Free Lists */
-#include "H5Iprivate.h" /* ID Functions */
-#include "H5Spkg.h" /* Dataspace functions */
-#include "H5Vprivate.h" /* Vector functions */
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5FLprivate.h" /* Free Lists */
+#include "H5Iprivate.h" /* ID Functions */
+#include "H5Spkg.h" /* Dataspace functions */
+#include "H5Vprivate.h" /* Vector functions */
/* Local datatypes */
@@ -57,9 +57,11 @@ static hssize_t H5S_hyper_serial_size(const H5S_t *space);
static herr_t H5S_hyper_serialize(const H5S_t *space, uint8_t *buf);
static herr_t H5S_hyper_deserialize(H5S_t *space, const uint8_t *buf);
static herr_t H5S_hyper_bounds(const H5S_t *space, hsize_t *start, hsize_t *end);
+static herr_t H5S_hyper_offset(const H5S_t *space, hsize_t *offset);
static htri_t H5S_hyper_is_contiguous(const H5S_t *space);
static htri_t H5S_hyper_is_single(const H5S_t *space);
static htri_t H5S_hyper_is_regular(const H5S_t *space);
+static herr_t H5S_hyper_adjust_u(H5S_t *space, const hsize_t *offset);
static herr_t H5S_hyper_iter_init(H5S_sel_iter_t *iter, const H5S_t *space);
/* Selection iteration callbacks */
@@ -89,9 +91,11 @@ const H5S_select_class_t H5S_sel_hyper[1] = {{
H5S_hyper_serialize,
H5S_hyper_deserialize,
H5S_hyper_bounds,
+ H5S_hyper_offset,
H5S_hyper_is_contiguous,
H5S_hyper_is_single,
H5S_hyper_is_regular,
+ H5S_hyper_adjust_u,
H5S_hyper_iter_init,
}};
@@ -273,12 +277,17 @@ H5S_hyper_iter_init(H5S_sel_iter_t *iter, const H5S_t *space)
/* Don't flatten adjacent elements into contiguous block if the
* element size is 0. This is for the H5S_select_shape_same() code.
*/
- if(iter->elmt_size>0) {
+ if(iter->elmt_size > 0) {
/* Check for any "contiguous" blocks that can be flattened */
- for(u=rank-1; u>0; u--) {
- if(tdiminfo[u].count==1 && tdiminfo[u].block==mem_size[u])
+ for(u = (rank - 1); u > 0; u--) {
+ if(tdiminfo[u].count == 1 && tdiminfo[u].block == mem_size[u]) {
cont_dim++;
+ iter->u.hyp.flattened[u] = TRUE;
+ } /* end if */
+ else
+ iter->u.hyp.flattened[u] = FALSE;
} /* end for */
+ iter->u.hyp.flattened[0] = FALSE;
} /* end if */
/* Check if the regular selection can be "flattened" */
@@ -428,23 +437,59 @@ H5S_hyper_iter_coords (const H5S_sel_iter_t *iter, hsize_t *coords)
/* Check for a single "regular" hyperslab */
if(iter->u.hyp.diminfo_valid) {
/* Check if this is a "flattened" regular hyperslab selection */
- if(iter->u.hyp.iter_rank!=0 && iter->u.hyp.iter_rank<iter->rank) {
- unsigned flat_dim; /* The rank of the flattened dimension */
+ if(iter->u.hyp.iter_rank != 0 && iter->u.hyp.iter_rank < iter->rank) {
+ int u, v; /* Dimension indices */
+
+ /* Set the starting rank of both the "natural" & "flattened" dimensions */
+ u = iter->rank - 1;
+ v = iter->u.hyp.iter_rank - 1;
+
+ /* Construct the "natural" dimensions from a set of flattened coordinates */
+ while(u >= 0) {
+ if(iter->u.hyp.flattened[u]) {
+ int begin = u; /* The rank of the first flattened dimension */
+
+ /* Walk up through as many flattened dimensions as possible */
+ do {
+ u--;
+ } while(u >= 0 && iter->u.hyp.flattened[u]);
+
+ /* Compensate for possibly overshooting dim 0 */
+ if(u < 0)
+ u = 0;
- /* Get the rank of the flattened dimension */
- flat_dim=iter->u.hyp.iter_rank-1;
+ /* Sanity check */
+ HDassert(v >= 0);
- /* Copy the coordinates up to where things got flattened */
- HDmemcpy(coords,iter->u.hyp.off,sizeof(hsize_t)*flat_dim);
+ /* Compute the coords for the flattened dimensions */
+ H5V_array_calc(iter->u.hyp.off[v], (unsigned)((begin - u) + 1), &(iter->dims[u]), &(coords[u]));
- /* Compute the coordinates for the flattened dimensions */
- H5V_array_calc(iter->u.hyp.off[flat_dim],iter->rank-flat_dim,&(iter->dims[flat_dim]),&(coords[flat_dim]));
+ /* Continue to faster dimension in both indices */
+ u--;
+ v--;
+ } /* end if */
+ else {
+ /* Walk up through as many non-flattened dimensions as possible */
+ while(u >= 0 && !iter->u.hyp.flattened[u]) {
+ /* Sanity check */
+ HDassert(v >= 0);
+
+ /* Copy the coordinate */
+ coords[u] = iter->u.hyp.off[v];
+
+ /* Continue to faster dimension in both indices */
+ u--;
+ v--;
+ } /* end while */
+ } /* end else */
+ } /* end while */
+ HDassert(v < 0);
} /* end if */
else
- HDmemcpy(coords,iter->u.hyp.off,sizeof(hsize_t)*iter->rank);
+ HDmemcpy(coords, iter->u.hyp.off, sizeof(hsize_t) * iter->rank);
} /* end if */
else
- HDmemcpy(coords,iter->u.hyp.off,sizeof(hsize_t)*iter->rank);
+ HDmemcpy(coords, iter->u.hyp.off, sizeof(hsize_t) * iter->rank);
FUNC_LEAVE_NOAPI(SUCCEED);
} /* H5S_hyper_iter_coords() */
@@ -1201,7 +1246,7 @@ H5S_hyper_span_scratch (H5S_hyper_span_info_t *spans, void *scr_value)
/* Check if we've already set this down span tree */
if(spans->scratch!=scr_value) {
/* Set the tree's scratch pointer */
- spans->scratch=scr_value;
+ spans->scratch = (H5S_hyper_span_info_t *)scr_value;
/* Set the scratch pointers in all the nodes */
span=spans->head;
@@ -1498,7 +1543,7 @@ H5S_hyper_free_span_info (H5S_hyper_span_info_t *span_info)
} /* end while */
/* Free this span info */
- H5FL_FREE(H5S_hyper_span_info_t,span_info);
+ (void)H5FL_FREE(H5S_hyper_span_info_t, span_info);
} /* end if */
done:
@@ -1541,7 +1586,7 @@ H5S_hyper_free_span (H5S_hyper_span_t *span)
} /* end if */
/* Free this span */
- H5FL_FREE(H5S_hyper_span_t,span);
+ (void)H5FL_FREE(H5S_hyper_span_t, span);
done:
FUNC_LEAVE_NOAPI(ret_value);
@@ -1859,22 +1904,22 @@ H5S_get_select_hyper_nblocks(H5S_t *space)
hssize_t
H5Sget_select_hyper_nblocks(hid_t spaceid)
{
- H5S_t *space = NULL; /* Dataspace to modify selection of */
- hssize_t ret_value; /* return value */
+ H5S_t *space; /* Dataspace to modify selection of */
+ hssize_t ret_value; /* return value */
- FUNC_ENTER_API(H5Sget_select_hyper_nblocks, FAIL);
+ FUNC_ENTER_API(H5Sget_select_hyper_nblocks, FAIL)
H5TRACE1("Hs", "i", spaceid);
/* Check args */
- if (NULL == (space=H5I_object_verify(spaceid, H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space");
- if(H5S_GET_SELECT_TYPE(space)!=H5S_SEL_HYPERSLABS)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a hyperslab selection");
+ if(NULL == (space = (H5S_t *)H5I_object_verify(spaceid, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space")
+ if(H5S_GET_SELECT_TYPE(space) != H5S_SEL_HYPERSLABS)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a hyperslab selection")
ret_value = H5S_get_select_hyper_nblocks(space);
done:
- FUNC_LEAVE_API(ret_value);
+ FUNC_LEAVE_API(ret_value)
} /* H5Sget_select_hyper_nblocks() */
@@ -2513,7 +2558,7 @@ H5S_get_select_hyper_blocklist(H5S_t *space, hbool_t internal, hsize_t startbloc
hid_t dsid; IN: Dataspace ID of selection to query
hsize_t startblock; IN: Hyperslab block to start with
hsize_t numblocks; IN: Number of hyperslab blocks to get
- hsize_t *buf; OUT: List of hyperslab blocks selected
+ hsize_t buf[]; OUT: List of hyperslab blocks selected
RETURNS
Non-negative on success, negative on failure
DESCRIPTION
@@ -2534,30 +2579,31 @@ H5S_get_select_hyper_blocklist(H5S_t *space, hbool_t internal, hsize_t startbloc
REVISION LOG
--------------------------------------------------------------------------*/
herr_t
-H5Sget_select_hyper_blocklist(hid_t spaceid, hsize_t startblock, hsize_t numblocks, hsize_t *buf)
+H5Sget_select_hyper_blocklist(hid_t spaceid, hsize_t startblock,
+ hsize_t numblocks, hsize_t buf[/*numblocks*/])
{
- H5S_t *space = NULL; /* Dataspace to modify selection of */
- herr_t ret_value; /* return value */
+ H5S_t *space; /* Dataspace to modify selection of */
+ herr_t ret_value; /* return value */
- FUNC_ENTER_API(H5Sget_select_hyper_blocklist, FAIL);
- H5TRACE4("e", "ihh*h", spaceid, startblock, numblocks, buf);
+ FUNC_ENTER_API(H5Sget_select_hyper_blocklist, FAIL)
+ H5TRACE4("e", "ihh*[a2]h", spaceid, startblock, numblocks, buf);
/* Check args */
- if(buf==NULL)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid pointer");
- if (NULL == (space=H5I_object_verify(spaceid, H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space");
+ if(buf == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid pointer")
+ if(NULL == (space = (H5S_t *)H5I_object_verify(spaceid, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space")
if(H5S_GET_SELECT_TYPE(space)!=H5S_SEL_HYPERSLABS)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a hyperslab selection");
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a hyperslab selection")
/* Go get the correct number of blocks */
- if(numblocks>0)
- ret_value = H5S_get_select_hyper_blocklist(space,0,startblock,numblocks,buf);
+ if(numblocks > 0)
+ ret_value = H5S_get_select_hyper_blocklist(space, 0, startblock, numblocks, buf);
else
ret_value=SUCCEED; /* Successfully got 0 blocks... */
done:
- FUNC_LEAVE_API(ret_value);
+ FUNC_LEAVE_API(ret_value)
} /* H5Sget_select_hyper_blocklist() */
@@ -2706,6 +2752,114 @@ done:
/*--------------------------------------------------------------------------
NAME
+ H5S_hyper_offset
+ PURPOSE
+ Gets the linear offset of the first element for the selection.
+ USAGE
+ herr_t H5S_hyper_offset(space, offset)
+ const H5S_t *space; IN: Dataspace pointer of selection to query
+ hsize_t *offset; OUT: Linear offset of first element in selection
+ RETURNS
+ Non-negative on success, negative on failure
+ DESCRIPTION
+ Retrieves the linear offset (in "units" of elements) of the first element
+ selected within the dataspace.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Calling this function on a "none" selection returns fail.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5S_hyper_offset(const H5S_t *space, hsize_t *offset)
+{
+ const hssize_t *sel_offset; /* Pointer to the selection's offset */
+ const hsize_t *dim_size; /* Pointer to a dataspace's extent */
+ hsize_t accum; /* Accumulator for dimension sizes */
+ int rank; /* Dataspace rank */
+ int i; /* index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5S_hyper_offset, FAIL)
+
+ HDassert(space);
+ HDassert(offset);
+
+ /* Start at linear offset 0 */
+ *offset = 0;
+
+ /* Set up pointers to arrays of values */
+ rank = space->extent.rank;
+ sel_offset = space->select.offset;
+ dim_size = space->extent.size;
+
+ /* Check for a "regular" hyperslab selection */
+ if(space->select.sel_info.hslab->diminfo_valid) {
+ const H5S_hyper_dim_t *diminfo = space->select.sel_info.hslab->opt_diminfo; /* Local alias for diminfo */
+
+ /* Loop through starting coordinates, calculating the linear offset */
+ accum = 1;
+ for(i = (rank - 1); i >= 0; i--) {
+ hssize_t hyp_offset = (hssize_t)diminfo[i].start + sel_offset[i]; /* Hyperslab's offset in this dimension */
+
+ /* Check for offset moving selection out of the dataspace */
+ if(hyp_offset < 0 || (hsize_t)hyp_offset >= dim_size[i])
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "offset moves selection out of bounds")
+
+ /* Add the hyperslab's offset in this dimension to the total linear offset */
+ *offset += hyp_offset * accum;
+
+ /* Increase the accumulator */
+ accum *= dim_size[i];
+ } /* end for */
+ } /* end if */
+ else {
+ const H5S_hyper_span_t *span; /* Hyperslab span node */
+ hsize_t dim_accum[H5S_MAX_RANK]; /* Accumulators, for each dimension */
+
+ /* Calculate the accumulator for each dimension */
+ accum = 1;
+ for(i = (rank - 1); i >= 0; i--) {
+ /* Set the accumulator for this dimension */
+ dim_accum[i] = accum;
+
+ /* Increase the accumulator */
+ accum *= dim_size[i];
+ } /* end for */
+
+ /* Get information for the first span, in the slowest changing dimension */
+ span = space->select.sel_info.hslab->span_lst->head;
+
+ /* Work down the spans, computing the linear offset */
+ i = 0;
+ while(span) {
+ hssize_t hyp_offset = (hssize_t)span->low + sel_offset[i]; /* Hyperslab's offset in this dimension */
+
+ /* Check for offset moving selection out of the dataspace */
+ if(hyp_offset < 0 || (hsize_t)hyp_offset >= dim_size[i])
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "offset moves selection out of bounds")
+
+ /* Add the hyperslab's offset in this dimension to the total linear offset */
+ *offset += hyp_offset * dim_accum[i];
+
+ /* Advance to first span in "down" dimension */
+ if(span->down) {
+ HDassert(span->down->head);
+ span = span->down->head;
+ } /* end if */
+ else
+ span = NULL;
+ i++;
+ } /* end while */
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5S_hyper_offset() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
H5S_hyper_is_contiguous
PURPOSE
Check if a hyperslab selection is contiguous within the dataspace extent.
@@ -2725,12 +2879,10 @@ done:
htri_t
H5S_hyper_is_contiguous(const H5S_t *space)
{
- H5S_hyper_span_info_t *spans; /* Hyperslab span info node */
- H5S_hyper_span_t *span; /* Hyperslab span node */
- unsigned u; /* index variable */
unsigned small_contiguous, /* Flag for small contiguous block */
large_contiguous; /* Flag for large contiguous block */
- htri_t ret_value=FALSE; /* return value */
+ unsigned u; /* index variable */
+ htri_t ret_value = FALSE; /* Return value */
FUNC_ENTER_NOAPI_NOFUNC(H5S_hyper_is_contiguous);
@@ -2789,6 +2941,9 @@ H5S_hyper_is_contiguous(const H5S_t *space)
ret_value=TRUE;
} /* end if */
else {
+ H5S_hyper_span_info_t *spans; /* Hyperslab span info node */
+ H5S_hyper_span_t *span; /* Hyperslab span node */
+
/*
* For a hyperslab to be contiguous, it must have only one block and
* (either it's size must be the same as the dataspace extent's in all
@@ -3038,7 +3193,7 @@ H5S_hyper_release (H5S_t *space)
} /* end if */
/* Release space for the hyperslab selection information */
- H5FL_FREE(H5S_hyper_sel_t,space->select.sel_info.hslab);
+ (void)H5FL_FREE(H5S_hyper_sel_t, space->select.sel_info.hslab);
space->select.sel_info.hslab=NULL;
done:
@@ -4125,35 +4280,37 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-herr_t
+htri_t
H5S_hyper_normalize_offset(H5S_t *space, hssize_t *old_offset)
{
unsigned u; /* Local index variable */
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = FALSE; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5S_hyper_normalize_offset);
+ FUNC_ENTER_NOAPI_NOINIT(H5S_hyper_normalize_offset)
- assert(space);
+ HDassert(space);
- /* Check for 'all' selection, instead of a hyperslab selection */
- /* (Technically, this check shouldn't be in the "hyperslab" routines...) */
- if(H5S_GET_SELECT_TYPE(space)==H5S_SEL_HYPERSLABS) {
+ /* Check for hyperslab selection & offset changed */
+ if(H5S_GET_SELECT_TYPE(space) == H5S_SEL_HYPERSLABS && space->select.offset_changed) {
/* Copy & invert the selection offset */
- for(u=0; u<space->extent.rank; u++) {
+ for(u = 0; u<space->extent.rank; u++) {
old_offset[u] = space->select.offset[u];
space->select.offset[u] = -space->select.offset[u];
} /* end for */
/* Call the existing 'adjust' routine */
- if(H5S_hyper_adjust_s(space, space->select.offset)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab normalization");
+ if(H5S_hyper_adjust_s(space, space->select.offset) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab normalization")
/* Zero out the selection offset */
HDmemset(space->select.offset, 0, sizeof(hssize_t) * space->extent.rank);
+
+ /* Indicate that the offset was normalized */
+ ret_value = TRUE;
} /* end if */
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* H5S_hyper_normalize_offset() */
@@ -4181,25 +4338,22 @@ done:
herr_t
H5S_hyper_denormalize_offset(H5S_t *space, const hssize_t *old_offset)
{
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5S_hyper_denormalize_offset);
+ FUNC_ENTER_NOAPI_NOINIT(H5S_hyper_denormalize_offset)
- assert(space);
+ HDassert(space);
+ HDassert(H5S_GET_SELECT_TYPE(space) == H5S_SEL_HYPERSLABS);
- /* Check for 'all' selection, instead of a hyperslab selection */
- /* (Technically, this check shouldn't be in the "hyperslab" routines...) */
- if(H5S_GET_SELECT_TYPE(space)==H5S_SEL_HYPERSLABS) {
- /* Call the existing 'adjust' routine */
- if(H5S_hyper_adjust_s(space, old_offset)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab normalization");
+ /* Call the existing 'adjust' routine */
+ if(H5S_hyper_adjust_s(space, old_offset) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab normalization")
- /* Copy the selection offset over */
- HDmemcpy(space->select.offset, old_offset, sizeof(hssize_t) * space->extent.rank);
- } /* end if */
+ /* Copy the selection offset over */
+ HDmemcpy(space->select.offset, old_offset, sizeof(hssize_t) * space->extent.rank);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* H5S_hyper_denormalize_offset() */
@@ -6110,24 +6264,24 @@ herr_t
H5Sselect_hyperslab(hid_t space_id, H5S_seloper_t op, const hsize_t start[],
const hsize_t stride[], const hsize_t count[], const hsize_t block[])
{
- H5S_t *space = NULL; /* Dataspace to modify selection of */
+ H5S_t *space; /* Dataspace to modify selection of */
unsigned u; /* Local index variable */
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(H5Sselect_hyperslab, FAIL);
H5TRACE6("e", "iSs*h*h*h*h", space_id, op, start, stride, count, block);
/* Check args */
- if (NULL == (space=H5I_object_verify(space_id, H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space");
- if (H5S_SCALAR==H5S_GET_EXTENT_TYPE(space))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "hyperslab doesn't support H5S_SCALAR space");
- if (H5S_NULL==H5S_GET_EXTENT_TYPE(space))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "hyperslab doesn't support H5S_NULL space");
- if(start==NULL || count==NULL)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "hyperslab not specified");
- if(!(op>H5S_SELECT_NOOP && op<H5S_SELECT_INVALID))
- HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation");
+ if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space")
+ if(H5S_SCALAR == H5S_GET_EXTENT_TYPE(space))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "hyperslab doesn't support H5S_SCALAR space")
+ if(H5S_NULL == H5S_GET_EXTENT_TYPE(space))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "hyperslab doesn't support H5S_NULL space")
+ if(start == NULL || count == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "hyperslab not specified")
+ if(!(op > H5S_SELECT_NOOP && op < H5S_SELECT_INVALID))
+ HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation")
if(stride!=NULL) {
/* Check for 0-sized strides */
for(u=0; u<space->extent.rank; u++) {
@@ -6791,7 +6945,7 @@ H5Scombine_hyperslab(hid_t space_id, H5S_seloper_t op, const hsize_t start[],
HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation");
/* Copy the first dataspace */
- if (NULL==(new_space=H5S_copy (space, TRUE)))
+ if (NULL == (new_space = H5S_copy (space, TRUE, TRUE)))
HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, NULL, "unable to copy data space");
/* Go modify the selection in the new dataspace */
@@ -6799,7 +6953,7 @@ H5Scombine_hyperslab(hid_t space_id, H5S_seloper_t op, const hsize_t start[],
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to set hyperslab selection");
/* Atomize */
- if ((ret_value=H5I_register (H5I_DATASPACE, new_space))<0)
+ if ((ret_value=H5I_register (H5I_DATASPACE, new_space, TRUE))<0)
HGOTO_ERROR (H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace atom");
done:
@@ -6847,7 +7001,7 @@ H5S_combine_select (H5S_t *space1, H5S_seloper_t op, H5S_t *space2)
HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, NULL, "dataspace does not have span tree");
/* Copy the first dataspace */
- if (NULL==(new_space=H5S_copy (space1, TRUE)))
+ if (NULL == (new_space = H5S_copy (space1, TRUE, TRUE)))
HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, NULL, "unable to copy data space");
/* Free the current selection for the new dataspace */
@@ -6927,7 +7081,7 @@ H5Scombine_select(hid_t space1_id, H5S_seloper_t op, hid_t space2_id)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to create hyperslab selection");
/* Atomize */
- if ((ret_value=H5I_register (H5I_DATASPACE, new_space))<0)
+ if ((ret_value=H5I_register (H5I_DATASPACE, new_space, TRUE))<0)
HGOTO_ERROR (H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace atom");
done:
diff --git a/src/H5Smpio.c b/src/H5Smpio.c
index cc89b49..1f69706 100644
--- a/src/H5Smpio.c
+++ b/src/H5Smpio.c
@@ -123,7 +123,7 @@ H5S_mpio_all_type( const H5S_t *space, size_t elmt_size,
*new_type = MPI_BYTE;
H5_ASSIGN_OVERFLOW(*count, total_bytes, hsize_t, size_t);
*extra_offset = 0;
- *is_derived_type = 0;
+ *is_derived_type = FALSE;
done:
FUNC_LEAVE_NOAPI(ret_value);
@@ -163,7 +163,7 @@ H5S_mpio_none_type( const H5S_t UNUSED *space, size_t UNUSED elmt_size,
*new_type = MPI_BYTE;
*count = 0;
*extra_offset = 0;
- *is_derived_type = 0;
+ *is_derived_type = FALSE;
FUNC_LEAVE_NOAPI(SUCCEED);
} /* H5S_mpio_none_type() */
@@ -293,7 +293,7 @@ H5S_mpio_hyper_type( const H5S_t *space, size_t elmt_size,
goto empty;
#ifdef H5S_DEBUG
if(H5DEBUG(S))
- HDfprintf(H5DEBUG(S),"%s: Non-flattened selection\n",FUNC);
+ HDfprintf(H5DEBUG(S),"%s: Non-flattened selection\n",FUNC);
#endif
for ( i=0; i<rank; ++i) {
d[i].start = diminfo[i].start+space->select.offset[i];
@@ -456,7 +456,7 @@ H5S_mpio_hyper_type( const H5S_t *space, size_t elmt_size,
/* fill in the remaining return values */
*count = 1; /* only have to move one of these suckers! */
*extra_offset = 0;
- *is_derived_type = 1;
+ *is_derived_type = TRUE;
HGOTO_DONE(SUCCEED);
empty:
@@ -464,7 +464,7 @@ empty:
*new_type = MPI_BYTE;
*count = 0;
*extra_offset = 0;
- *is_derived_type = 0;
+ *is_derived_type = FALSE;
done:
/* Release selection iterator */
@@ -475,7 +475,7 @@ done:
#ifdef H5S_DEBUG
if(H5DEBUG(S)){
- HDfprintf(H5DEBUG(S), "Leave %s, count=%ld is_derived_type=%d\n",
+ HDfprintf(H5DEBUG(S), "Leave %s, count=%ld is_derived_type=%t\n",
FUNC, *count, *is_derived_type );
}
#endif
@@ -556,7 +556,7 @@ H5S_mpio_span_hyper_type( const H5S_t *space,
/* fill in the remaining return values */
*count = 1;
*extra_offset = 0;
- *is_derived_type = 1;
+ *is_derived_type = TRUE;
HGOTO_DONE(SUCCEED);
@@ -565,7 +565,7 @@ empty:
*new_type = MPI_BYTE;
*count = 0;
*extra_offset = 0;
- *is_derived_type = 0;
+ *is_derived_type = FALSE;
done:
FUNC_LEAVE_NOAPI(ret_value);
diff --git a/src/H5Snone.c b/src/H5Snone.c
index 1faf10c..fdea677 100644
--- a/src/H5Snone.c
+++ b/src/H5Snone.c
@@ -43,9 +43,11 @@ static hssize_t H5S_none_serial_size(const H5S_t *space);
static herr_t H5S_none_serialize(const H5S_t *space, uint8_t *buf);
static herr_t H5S_none_deserialize(H5S_t *space, const uint8_t *buf);
static herr_t H5S_none_bounds(const H5S_t *space, hsize_t *start, hsize_t *end);
+static herr_t H5S_none_offset(const H5S_t *space, hsize_t *off);
static htri_t H5S_none_is_contiguous(const H5S_t *space);
static htri_t H5S_none_is_single(const H5S_t *space);
static htri_t H5S_none_is_regular(const H5S_t *space);
+static herr_t H5S_none_adjust_u(H5S_t *space, const hsize_t *offset);
static herr_t H5S_none_iter_init(H5S_sel_iter_t *iter, const H5S_t *space);
/* Selection iteration callbacks */
@@ -70,9 +72,11 @@ const H5S_select_class_t H5S_sel_none[1] = {{
H5S_none_serialize,
H5S_none_deserialize,
H5S_none_bounds,
+ H5S_none_offset,
H5S_none_is_contiguous,
H5S_none_is_single,
H5S_none_is_regular,
+ H5S_none_adjust_u,
H5S_none_iter_init,
}};
@@ -284,12 +288,12 @@ H5S_none_iter_next(H5S_sel_iter_t UNUSED *iter, size_t UNUSED nelem)
static herr_t
H5S_none_iter_next_block(H5S_sel_iter_t UNUSED *iter)
{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_iter_next);
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_none_iter_next)
/* Check args */
- assert (iter);
+ HDassert(iter);
- FUNC_LEAVE_NOAPI(FAIL);
+ FUNC_LEAVE_NOAPI(FAIL)
} /* H5S_none_iter_next_block() */
@@ -563,11 +567,43 @@ H5S_none_bounds(const H5S_t UNUSED *space, hsize_t UNUSED *start, hsize_t UNUSED
/*--------------------------------------------------------------------------
NAME
+ H5S_none_offset
+ PURPOSE
+ Gets the linear offset of the first element for the selection.
+ USAGE
+ herr_t H5S_none_offset(space, offset)
+ const H5S_t *space; IN: Dataspace pointer of selection to query
+ hsize_t *offset; OUT: Linear offset of first element in selection
+ RETURNS
+ Non-negative on success, negative on failure
+ DESCRIPTION
+ Retrieves the linear offset (in "units" of elements) of the first element
+ selected within the dataspace.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Calling this function on a "none" selection returns fail.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5S_none_offset(const H5S_t *space, hsize_t *offset)
+{
+ FUNC_ENTER_NOAPI_NOFUNC(H5S_none_offset)
+
+ HDassert(space);
+ HDassert(offset);
+
+ FUNC_LEAVE_NOAPI(FAIL)
+} /* H5S_none_offset() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
H5S_none_is_contiguous
PURPOSE
Check if a "none" selection is contiguous within the dataspace extent.
USAGE
- htri_t H5S_all_is_contiguous(space)
+ htri_t H5S_none_is_contiguous(space)
H5S_t *space; IN: Dataspace pointer to check
RETURNS
TRUE/FALSE/FAIL
@@ -652,6 +688,37 @@ H5S_none_is_regular(const H5S_t UNUSED *space)
/*--------------------------------------------------------------------------
NAME
+ H5S_none_adjust_u
+ PURPOSE
+ Adjust an "none" selection by subtracting an offset
+ USAGE
+ herr_t H5S_none_adjust_u(space, offset)
+ H5S_t *space; IN/OUT: Pointer to dataspace to adjust
+ const hsize_t *offset; IN: Offset to subtract
+ RETURNS
+ Non-negative on success, negative on failure
+ DESCRIPTION
+ Moves selection by subtracting an offset from it.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5S_none_adjust_u(H5S_t UNUSED *space, const hsize_t UNUSED *offset)
+{
+ FUNC_ENTER_NOAPI_NOFUNC(H5S_none_adjust_u)
+
+ /* Check args */
+ HDassert(space);
+ HDassert(offset);
+
+ FUNC_LEAVE_NOAPI(FAIL)
+} /* H5S_none_adjust_u() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
H5S_select_none
PURPOSE
Specify that nothing is selected in the extent
@@ -708,23 +775,25 @@ done:
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-herr_t H5Sselect_none (hid_t spaceid)
+herr_t
+H5Sselect_none(hid_t spaceid)
{
- H5S_t *space = NULL; /* Dataspace to modify selection of */
- herr_t ret_value; /* return value */
+ H5S_t *space; /* Dataspace to modify selection of */
+ herr_t ret_value = SUCCEED; /* return value */
- FUNC_ENTER_API(H5Sselect_none, FAIL);
+ FUNC_ENTER_API(H5Sselect_none, FAIL)
+ H5TRACE1("e", "i", spaceid);
/* Check args */
- if (NULL == (space=H5I_object_verify(spaceid, H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space");
+ if(NULL == (space = (H5S_t *)H5I_object_verify(spaceid, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space")
/* Change to "none" selection */
- if((ret_value=H5S_select_none(space))<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection");
+ if(H5S_select_none(space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection")
done:
- FUNC_LEAVE_API(ret_value);
+ FUNC_LEAVE_API(ret_value)
} /* H5Sselect_none() */
@@ -734,7 +803,7 @@ done:
PURPOSE
Create a list of offsets & lengths for a selection
USAGE
- herr_t H5S_all_get_seq_list(space,flags,iter,maxseq,maxelem,nseq,nelem,off,len)
+ herr_t H5S_none_get_seq_list(space,flags,iter,maxseq,maxelem,nseq,nelem,off,len)
H5S_t *space; IN: Dataspace containing selection to use.
unsigned flags; IN: Flags for extra information about operation
H5S_sel_iter_t *iter; IN/OUT: Selection iterator describing last
@@ -783,4 +852,5 @@ H5S_none_get_seq_list(const H5S_t UNUSED *space, unsigned UNUSED flags, H5S_sel_
*nelem=0;
FUNC_LEAVE_NOAPI(SUCCEED);
-} /* end H5S_all_get_seq_list() */
+} /* end H5S_none_get_seq_list() */
+
diff --git a/src/H5Spkg.h b/src/H5Spkg.h
index 8dc2991..b7818a2 100644
--- a/src/H5Spkg.h
+++ b/src/H5Spkg.h
@@ -44,7 +44,7 @@
*/
#define H5O_SDSPACE_VERSION_2 2
-/* The latest version of the format. Look through the 'encode'
+/* The latest version of the format. Look through the 'encode'
* and 'size' callbacks for places to change when updating this. */
#define H5O_SDSPACE_VERSION_LATEST H5O_SDSPACE_VERSION_2
@@ -133,14 +133,18 @@ typedef hssize_t (*H5S_sel_serial_size_func_t)(const H5S_t *space);
typedef herr_t (*H5S_sel_serialize_func_t)(const H5S_t *space, uint8_t *buf);
/* Method to store create selection from "serialized" form (a byte sequence suitable for storing on disk) */
typedef herr_t (*H5S_sel_deserialize_func_t)(H5S_t *space, const uint8_t *buf);
-/* Method to determine to smallest n-D bounding box containing the current selection */
+/* Method to determine smallest n-D bounding box containing the current selection */
typedef herr_t (*H5S_sel_bounds_func_t)(const H5S_t *space, hsize_t *start, hsize_t *end);
+/* Method to determine linear offset of initial element in selection within dataspace */
+typedef herr_t (*H5S_sel_offset_func_t)(const H5S_t *space, hsize_t *offset);
/* Method to determine if current selection is contiguous */
typedef htri_t (*H5S_sel_is_contiguous_func_t)(const H5S_t *space);
/* Method to determine if current selection is a single block */
typedef htri_t (*H5S_sel_is_single_func_t)(const H5S_t *space);
/* Method to determine if current selection is "regular" */
typedef htri_t (*H5S_sel_is_regular_func_t)(const H5S_t *space);
+/* Method to adjust a selection by an offset */
+typedef herr_t (*H5S_sel_adjust_u_func_t)(H5S_t *space, const hsize_t *offset);
/* Method to initialize iterator for current selection */
typedef herr_t (*H5S_sel_iter_init_func_t)(H5S_sel_iter_t *sel_iter, const H5S_t *space);
@@ -157,15 +161,18 @@ typedef struct {
H5S_sel_serialize_func_t serialize; /* Method to store current selection in "serialized" form (a byte sequence suitable for storing on disk) */
H5S_sel_deserialize_func_t deserialize; /* Method to store create selection from "serialized" form (a byte sequence suitable for storing on disk) */
H5S_sel_bounds_func_t bounds; /* Method to determine to smallest n-D bounding box containing the current selection */
+ H5S_sel_offset_func_t offset; /* Method to determine linear offset of initial element in selection within dataspace */
H5S_sel_is_contiguous_func_t is_contiguous; /* Method to determine if current selection is contiguous */
H5S_sel_is_single_func_t is_single; /* Method to determine if current selection is a single block */
H5S_sel_is_regular_func_t is_regular; /* Method to determine if current selection is "regular" */
+ H5S_sel_adjust_u_func_t adjust_u; /* Method to adjust a selection by an offset */
H5S_sel_iter_init_func_t iter_init; /* Method to initialize iterator for current selection */
} H5S_select_class_t;
/* Selection information object */
typedef struct {
const H5S_select_class_t *type; /* Pointer to selection's class info */
+ hbool_t offset_changed; /* Indicate that the offset for the selection has been changed */
hssize_t offset[H5S_MAX_RANK]; /* Offset within the extent */
hsize_t num_elem; /* Number of elements in selection */
union {
@@ -232,7 +239,8 @@ H5_DLLVAR const H5S_select_class_t H5S_sel_point[1];
/* Extent functions */
H5_DLL herr_t H5S_extent_release(H5S_extent_t *extent);
-H5_DLL herr_t H5S_extent_copy(H5S_extent_t *dst, const H5S_extent_t *src);
+H5_DLL herr_t H5S_extent_copy(H5S_extent_t *dst, const H5S_extent_t *src,
+ hbool_t copy_max);
/* Operations on selections */
diff --git a/src/H5Spoint.c b/src/H5Spoint.c
index fc94191..74d72d9 100644
--- a/src/H5Spoint.c
+++ b/src/H5Spoint.c
@@ -44,9 +44,11 @@ static hssize_t H5S_point_serial_size(const H5S_t *space);
static herr_t H5S_point_serialize(const H5S_t *space, uint8_t *buf);
static herr_t H5S_point_deserialize(H5S_t *space, const uint8_t *buf);
static herr_t H5S_point_bounds(const H5S_t *space, hsize_t *start, hsize_t *end);
+static herr_t H5S_point_offset(const H5S_t *space, hsize_t *off);
static htri_t H5S_point_is_contiguous(const H5S_t *space);
static htri_t H5S_point_is_single(const H5S_t *space);
static htri_t H5S_point_is_regular(const H5S_t *space);
+static herr_t H5S_point_adjust_u(H5S_t *space, const hsize_t *offset);
static herr_t H5S_point_iter_init(H5S_sel_iter_t *iter, const H5S_t *space);
/* Selection iteration callbacks */
@@ -71,9 +73,11 @@ const H5S_select_class_t H5S_sel_point[1] = {{
H5S_point_serialize,
H5S_point_deserialize,
H5S_point_bounds,
+ H5S_point_offset,
H5S_point_is_contiguous,
H5S_point_is_single,
H5S_point_is_regular,
+ H5S_point_adjust_u,
H5S_point_iter_init,
}};
@@ -378,71 +382,70 @@ H5S_point_iter_release (H5S_sel_iter_t UNUSED * iter)
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_point_add (H5S_t *space, H5S_seloper_t op, size_t num_elem, const hsize_t **_coord)
+H5S_point_add(H5S_t *space, H5S_seloper_t op, size_t num_elem, const hsize_t *coord)
{
H5S_pnt_node_t *top, *curr, *new_node; /* Point selection nodes */
- const hsize_t *coord=(const hsize_t *)_coord; /* Pointer to the actual coordinates */
- unsigned i; /* Counter */
- herr_t ret_value=SUCCEED; /* Return value */
+ unsigned i; /* Counter */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5S_point_add);
+ FUNC_ENTER_NOAPI_NOINIT(H5S_point_add)
- assert(space);
- assert(num_elem>0);
- assert(coord);
- assert(op==H5S_SELECT_SET || op==H5S_SELECT_APPEND || op==H5S_SELECT_PREPEND);
+ HDassert(space);
+ HDassert(num_elem > 0);
+ HDassert(coord);
+ HDassert(op == H5S_SELECT_SET || op == H5S_SELECT_APPEND || op == H5S_SELECT_PREPEND);
- top=curr=NULL;
- for(i=0; i<num_elem; i++) {
+ top = curr = NULL;
+ for(i = 0; i < num_elem; i++) {
/* Allocate space for the new node */
- if((new_node = H5FL_MALLOC(H5S_pnt_node_t))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate point node");
+ if(NULL == (new_node = H5FL_MALLOC(H5S_pnt_node_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate point node")
- if((new_node->pnt = H5MM_malloc(space->extent.rank*sizeof(hsize_t)))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate coordinate information");
+ if(NULL == (new_node->pnt = (hsize_t *)H5MM_malloc(space->extent.rank * sizeof(hsize_t))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate coordinate information")
/* Copy over the coordinates */
- HDmemcpy(new_node->pnt,coord+(i*space->extent.rank),(space->extent.rank*sizeof(hsize_t)));
+ HDmemcpy(new_node->pnt, coord + (i * space->extent.rank), (space->extent.rank * sizeof(hsize_t)));
/* Link into list */
- new_node->next=NULL;
- if(top==NULL)
- top=new_node;
+ new_node->next = NULL;
+ if(top == NULL)
+ top = new_node;
else
- curr->next=new_node;
- curr=new_node;
+ curr->next = new_node;
+ curr = new_node;
} /* end for */
/* Insert the list of points selected in the proper place */
- if(op==H5S_SELECT_SET || op==H5S_SELECT_PREPEND) {
+ if(op == H5S_SELECT_SET || op == H5S_SELECT_PREPEND) {
/* Append current list, if there is one */
- if(space->select.sel_info.pnt_lst->head!=NULL)
- curr->next=space->select.sel_info.pnt_lst->head;
+ if(space->select.sel_info.pnt_lst->head != NULL)
+ curr->next = space->select.sel_info.pnt_lst->head;
/* Put new list in point selection */
- space->select.sel_info.pnt_lst->head=top;
+ space->select.sel_info.pnt_lst->head = top;
} /* end if */
else { /* op==H5S_SELECT_APPEND */
- new_node=space->select.sel_info.pnt_lst->head;
- if(new_node!=NULL) {
- while(new_node->next!=NULL)
- new_node=new_node->next;
+ new_node = space->select.sel_info.pnt_lst->head;
+ if(new_node != NULL) {
+ while(new_node->next != NULL)
+ new_node = new_node->next;
/* Append new list to point selection */
- new_node->next=top;
+ new_node->next = top;
} /* end if */
else
- space->select.sel_info.pnt_lst->head=top;
+ space->select.sel_info.pnt_lst->head = top;
} /* end else */
/* Set the number of elements in the new selection */
- if(op==H5S_SELECT_SET)
- space->select.num_elem=num_elem;
+ if(op == H5S_SELECT_SET)
+ space->select.num_elem = num_elem;
else
- space->select.num_elem+=num_elem;
+ space->select.num_elem += num_elem;
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* H5S_point_add() */
@@ -478,12 +481,12 @@ H5S_point_release (H5S_t *space)
while(curr!=NULL) {
next=curr->next;
H5MM_xfree(curr->pnt);
- H5FL_FREE(H5S_pnt_node_t,curr);
+ (void)H5FL_FREE(H5S_pnt_node_t, curr);
curr=next;
} /* end while */
/* Free & reset the point list header */
- H5FL_FREE(H5S_pnt_list_t,space->select.sel_info.pnt_lst);
+ (void)H5FL_FREE(H5S_pnt_list_t, space->select.sel_info.pnt_lst);
space->select.sel_info.pnt_lst=NULL;
/* Reset the number of elements in the selection */
@@ -503,7 +506,7 @@ H5S_point_release (H5S_t *space)
hid_t dsid; IN: Dataspace ID of selection to modify
H5S_seloper_t op; IN: Operation to perform on current selection
size_t num_elem; IN: Number of elements in COORD array.
- const hsize_t **coord; IN: The location of each element selected
+ const hsize_t *coord; IN: The location of each element selected
RETURNS
Non-negative on success/Negative on failure
DESCRIPTION
@@ -524,40 +527,38 @@ H5S_point_release (H5S_t *space)
REVISION LOG
--------------------------------------------------------------------------*/
herr_t
-H5S_select_elements (H5S_t *space, H5S_seloper_t op, size_t num_elem,
- const hsize_t **coord)
+H5S_select_elements(H5S_t *space, H5S_seloper_t op, size_t num_elem,
+ const hsize_t *coord)
{
- herr_t ret_value=SUCCEED; /* return value */
+ herr_t ret_value = SUCCEED; /* return value */
- FUNC_ENTER_NOAPI_NOINIT(H5S_select_elements);
+ FUNC_ENTER_NOAPI_NOINIT(H5S_select_elements)
/* Check args */
- assert(space);
- assert(num_elem);
- assert(coord);
- assert(op==H5S_SELECT_SET || op==H5S_SELECT_APPEND || op==H5S_SELECT_PREPEND);
+ HDassert(space);
+ HDassert(num_elem);
+ HDassert(coord);
+ HDassert(op == H5S_SELECT_SET || op == H5S_SELECT_APPEND || op == H5S_SELECT_PREPEND);
/* If we are setting a new selection, remove current selection first */
- if(op==H5S_SELECT_SET || H5S_GET_SELECT_TYPE(space)!=H5S_SEL_POINTS) {
- if(H5S_SELECT_RELEASE(space)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release point selection");
- } /* end if */
+ if(op == H5S_SELECT_SET || H5S_GET_SELECT_TYPE(space) != H5S_SEL_POINTS)
+ if(H5S_SELECT_RELEASE(space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release point selection")
/* Allocate space for the point selection information if necessary */
- if(H5S_GET_SELECT_TYPE(space)!=H5S_SEL_POINTS || space->select.sel_info.pnt_lst==NULL) {
- if((space->select.sel_info.pnt_lst = H5FL_CALLOC(H5S_pnt_list_t))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate element information");
- } /* end if */
+ if(H5S_GET_SELECT_TYPE(space) != H5S_SEL_POINTS || space->select.sel_info.pnt_lst == NULL)
+ if(NULL == (space->select.sel_info.pnt_lst = H5FL_CALLOC(H5S_pnt_list_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate element information")
/* Add points to selection */
- if(H5S_point_add(space,op,num_elem,coord)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert elements");
+ if(H5S_point_add(space, op, num_elem, coord) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert elements")
/* Set selection type */
- space->select.type=H5S_sel_point;
+ space->select.type = H5S_sel_point;
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* H5S_select_elements() */
@@ -599,12 +600,12 @@ H5S_point_copy(H5S_t *dst, const H5S_t *src, hbool_t UNUSED share_selection)
new_head=NULL;
while(curr!=NULL) {
/* Create each point */
- if((new_node=H5FL_MALLOC(H5S_pnt_node_t))==NULL)
+ if(NULL == (new_node = H5FL_MALLOC(H5S_pnt_node_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate point node");
- if((new_node->pnt = H5MM_malloc(src->extent.rank*sizeof(hsize_t)))==NULL)
+ if((new_node->pnt = (hsize_t *)H5MM_malloc(src->extent.rank*sizeof(hsize_t)))==NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate coordinate information");
- HDmemcpy(new_node->pnt,curr->pnt,(src->extent.rank*sizeof(hsize_t)));
- new_node->next=NULL;
+ HDmemcpy(new_node->pnt, curr->pnt, (src->extent.rank * sizeof(hsize_t)));
+ new_node->next = NULL;
/* Keep the order the same when copying */
if(new_head==NULL)
@@ -693,22 +694,22 @@ done:
hssize_t
H5Sget_select_elem_npoints(hid_t spaceid)
{
- H5S_t *space = NULL; /* Dataspace to modify selection of */
- hssize_t ret_value; /* return value */
+ H5S_t *space; /* Dataspace to modify selection of */
+ hssize_t ret_value; /* return value */
- FUNC_ENTER_API(H5Sget_select_elem_npoints, FAIL);
+ FUNC_ENTER_API(H5Sget_select_elem_npoints, FAIL)
H5TRACE1("Hs", "i", spaceid);
/* Check args */
- if (NULL == (space=H5I_object_verify(spaceid, H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space");
- if(H5S_GET_SELECT_TYPE(space)!=H5S_SEL_POINTS)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an element selection");
+ if(NULL == (space = (H5S_t *)H5I_object_verify(spaceid, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space")
+ if(H5S_GET_SELECT_TYPE(space) != H5S_SEL_POINTS)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an element selection")
ret_value = H5S_GET_SELECT_NPOINTS(space);
done:
- FUNC_LEAVE_API(ret_value);
+ FUNC_LEAVE_API(ret_value)
} /* H5Sget_select_elem_npoints() */
@@ -851,41 +852,41 @@ H5S_point_deserialize (H5S_t *space, const uint8_t *buf)
uint32_t rank; /* Rank of points */
size_t num_elem=0; /* Number of elements in selection */
hsize_t *coord=NULL, *tcoord; /* Pointer to array of elements */
- unsigned i,j; /* local counting variables */
- herr_t ret_value; /* return value */
+ unsigned i, j; /* local counting variables */
+ herr_t ret_value = SUCCEED; /* return value */
- FUNC_ENTER_NOAPI_NOINIT(H5S_point_deserialize);
+ FUNC_ENTER_NOAPI_NOINIT(H5S_point_deserialize)
/* Check args */
- assert(space);
- assert(buf);
+ HDassert(space);
+ HDassert(buf);
/* Deserialize points to select */
- buf+=16; /* Skip over selection header */
- UINT32DECODE(buf,rank); /* decode the rank of the point selection */
- if(rank!=space->extent.rank)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "rank of pointer does not match dataspace");
- UINT32DECODE(buf,num_elem); /* decode the number of points */
+ buf += 16; /* Skip over selection header */
+ UINT32DECODE(buf, rank); /* decode the rank of the point selection */
+ if(rank != space->extent.rank)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "rank of pointer does not match dataspace")
+ UINT32DECODE(buf, num_elem); /* decode the number of points */
/* Allocate space for the coordinates */
- if((coord = H5MM_malloc(num_elem*rank*sizeof(hsize_t)))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate coordinate information");
+ if(NULL == (coord = (hsize_t *)H5MM_malloc(num_elem * rank * sizeof(hsize_t))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate coordinate information")
/* Retrieve the coordinates from the buffer */
- for(tcoord=coord,i=0; i<num_elem; i++)
- for(j=0; j<(unsigned)rank; j++,tcoord++)
+ for(tcoord = coord, i = 0; i < num_elem; i++)
+ for(j = 0; j < (unsigned)rank; j++, tcoord++)
UINT32DECODE(buf, *tcoord);
/* Select points */
- if((ret_value=H5S_select_elements(space,op,num_elem,(const hsize_t **)coord))<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection");
+ if(H5S_select_elements(space, op, num_elem, (const hsize_t *)coord) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection")
done:
/* Free the coordinate array if necessary */
- if(coord!=NULL)
+ if(coord != NULL)
H5MM_xfree(coord);
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* H5S_point_deserialize() */
@@ -963,7 +964,7 @@ H5S_get_select_elem_pointlist(H5S_t *space, hsize_t startpoint, hsize_t numpoint
hid_t dsid; IN: Dataspace ID of selection to query
hsize_t startpoint; IN: Element point to start with
hsize_t numpoints; IN: Number of element points to get
- hsize_t *buf; OUT: List of element points selected
+ hsize_t buf[]; OUT: List of element points selected
RETURNS
Non-negative on success, negative on failure
DESCRIPTION
@@ -983,26 +984,27 @@ H5S_get_select_elem_pointlist(H5S_t *space, hsize_t startpoint, hsize_t numpoint
REVISION LOG
--------------------------------------------------------------------------*/
herr_t
-H5Sget_select_elem_pointlist(hid_t spaceid, hsize_t startpoint, hsize_t numpoints, hsize_t *buf)
+H5Sget_select_elem_pointlist(hid_t spaceid, hsize_t startpoint,
+ hsize_t numpoints, hsize_t buf[/*numpoints*/])
{
- H5S_t *space = NULL; /* Dataspace to modify selection of */
- herr_t ret_value; /* return value */
+ H5S_t *space; /* Dataspace to modify selection of */
+ herr_t ret_value; /* return value */
- FUNC_ENTER_API(H5Sget_select_elem_pointlist, FAIL);
- H5TRACE4("e", "ihh*h", spaceid, startpoint, numpoints, buf);
+ FUNC_ENTER_API(H5Sget_select_elem_pointlist, FAIL)
+ H5TRACE4("e", "ihh*[a2]h", spaceid, startpoint, numpoints, buf);
/* Check args */
- if(buf==NULL)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid pointer");
- if (NULL == (space=H5I_object_verify(spaceid, H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space");
- if(H5S_GET_SELECT_TYPE(space)!=H5S_SEL_POINTS)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a point selection");
+ if(NULL == buf)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid pointer")
+ if(NULL == (space = (H5S_t *)H5I_object_verify(spaceid, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space")
+ if(H5S_GET_SELECT_TYPE(space) != H5S_SEL_POINTS)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a point selection")
- ret_value = H5S_get_select_elem_pointlist(space,startpoint,numpoints,buf);
+ ret_value = H5S_get_select_elem_pointlist(space, startpoint, numpoints, buf);
done:
- FUNC_LEAVE_API(ret_value);
+ FUNC_LEAVE_API(ret_value)
} /* H5Sget_select_elem_pointlist() */
@@ -1036,48 +1038,114 @@ static herr_t
H5S_point_bounds(const H5S_t *space, hsize_t *start, hsize_t *end)
{
H5S_pnt_node_t *node; /* Point node */
- int rank; /* Dataspace rank */
- int i; /* index variable */
- herr_t ret_value=SUCCEED; /* Return value */
+ unsigned rank; /* Dataspace rank */
+ unsigned u; /* index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5S_point_bounds);
+ FUNC_ENTER_NOAPI_NOINIT(H5S_point_bounds)
- assert(space);
- assert(start);
- assert(end);
+ HDassert(space);
+ HDassert(start);
+ HDassert(end);
/* Get the dataspace extent rank */
- rank=space->extent.rank;
+ rank = space->extent.rank;
/* Set the start and end arrays up */
- for(i=0; i<rank; i++) {
- start[i]=HSIZET_MAX;
- end[i]=0;
+ for(u = 0; u < rank; u++) {
+ start[u] = HSIZET_MAX;
+ end[u] = 0;
} /* end for */
/* Iterate through the node, checking the bounds on each element */
- node=space->select.sel_info.pnt_lst->head;
- while(node!=NULL) {
- for(i=0; i<rank; i++) {
+ node = space->select.sel_info.pnt_lst->head;
+ while(node != NULL) {
+ for(u = 0; u < rank; u++) {
/* Check for offset moving selection negative */
- if(((hssize_t)node->pnt[i]+space->select.offset[i])<0)
+ if(((hssize_t)node->pnt[u] + space->select.offset[u]) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "offset moves selection out of bounds")
- if(start[i]>(node->pnt[i]+space->select.offset[i]))
- start[i]=node->pnt[i]+space->select.offset[i];
- if(end[i]<(node->pnt[i]+space->select.offset[i]))
- end[i]=node->pnt[i]+space->select.offset[i];
+ if(start[u] > (node->pnt[u] + space->select.offset[u]))
+ start[u] = node->pnt[u] + space->select.offset[u];
+ if(end[u] < (node->pnt[u] + space->select.offset[u]))
+ end[u] = node->pnt[u] + space->select.offset[u];
} /* end for */
- node=node->next;
+ node = node->next;
} /* end while */
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* H5S_point_bounds() */
/*--------------------------------------------------------------------------
NAME
+ H5S_point_offset
+ PURPOSE
+ Gets the linear offset of the first element for the selection.
+ USAGE
+ herr_t H5S_point_offset(space, offset)
+ const H5S_t *space; IN: Dataspace pointer of selection to query
+ hsize_t *offset; OUT: Linear offset of first element in selection
+ RETURNS
+ Non-negative on success, negative on failure
+ DESCRIPTION
+ Retrieves the linear offset (in "units" of elements) of the first element
+ selected within the dataspace.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Calling this function on a "none" selection returns fail.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5S_point_offset(const H5S_t *space, hsize_t *offset)
+{
+ const hsize_t *pnt; /* Pointer to a selected point's coordinates */
+ const hssize_t *sel_offset; /* Pointer to the selection's offset */
+ const hsize_t *dim_size; /* Pointer to a dataspace's extent */
+ hsize_t accum; /* Accumulator for dimension sizes */
+ int rank; /* Dataspace rank */
+ int i; /* index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5S_point_offset, FAIL)
+
+ HDassert(space);
+ HDassert(offset);
+
+ /* Start at linear offset 0 */
+ *offset = 0;
+
+ /* Set up pointers to arrays of values */
+ pnt = space->select.sel_info.pnt_lst->head->pnt;
+ sel_offset = space->select.offset;
+ dim_size = space->extent.size;
+
+ /* Loop through coordinates, calculating the linear offset */
+ rank = space->extent.rank;
+ accum = 1;
+ for(i = (rank - 1); i >= 0; i--) {
+ hssize_t pnt_offset = (hssize_t)pnt[i] + sel_offset[i]; /* Point's offset in this dimension */
+
+ /* Check for offset moving selection out of the dataspace */
+ if(pnt_offset < 0 || (hsize_t)pnt_offset >= dim_size[i])
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "offset moves selection out of bounds")
+
+ /* Add the point's offset in this dimension to the total linear offset */
+ *offset += pnt_offset * accum;
+
+ /* Increase the accumulator */
+ accum *= dim_size[i];
+ } /* end for */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5S_point_offset() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
H5S_point_is_contiguous
PURPOSE
Check if a point selection is contiguous within the dataspace extent.
@@ -1196,6 +1264,58 @@ H5S_point_is_regular(const H5S_t *space)
/*--------------------------------------------------------------------------
NAME
+ H5S_point_adjust_u
+ PURPOSE
+ Adjust a "point" selection by subtracting an offset
+ USAGE
+ herr_t H5S_point_adjust_u(space, offset)
+ H5S_t *space; IN/OUT: Pointer to dataspace to adjust
+ const hsize_t *offset; IN: Offset to subtract
+ RETURNS
+ Non-negative on success, negative on failure
+ DESCRIPTION
+ Moves a point selection by subtracting an offset from it.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5S_point_adjust_u(H5S_t *space, const hsize_t *offset)
+{
+ H5S_pnt_node_t *node; /* Point node */
+ unsigned rank; /* Dataspace rank */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_point_adjust_u)
+
+ HDassert(space);
+ HDassert(offset);
+
+ /* Iterate through the nodes, checking the bounds on each element */
+ node = space->select.sel_info.pnt_lst->head;
+ rank = space->extent.rank;
+ while(node) {
+ unsigned u; /* Local index variable */
+
+ /* Adjust each coordinate for point node */
+ for(u = 0; u < rank; u++) {
+ /* Check for offset moving selection negative */
+ HDassert(node->pnt[u] >= offset[u]);
+
+ /* Adjust node's coordinate location */
+ node->pnt[u] -= offset[u];
+ } /* end for */
+
+ /* Advance to next point node in selection */
+ node = node->next;
+ } /* end while */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5S_point_adjust_u() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
H5Sselect_elements
PURPOSE
Specify a series of elements in the dataspace to select
@@ -1204,7 +1324,7 @@ H5S_point_is_regular(const H5S_t *space)
hid_t dsid; IN: Dataspace ID of selection to modify
H5S_seloper_t op; IN: Operation to perform on current selection
size_t num_elem; IN: Number of elements in COORD array.
- const hsize_t **coord; IN: The location of each element selected
+ const hsize_t *coord; IN: The location of each element selected
RETURNS
Non-negative on success/Negative on failure
DESCRIPTION
@@ -1226,32 +1346,32 @@ H5S_point_is_regular(const H5S_t *space)
--------------------------------------------------------------------------*/
herr_t
H5Sselect_elements(hid_t spaceid, H5S_seloper_t op, size_t num_elem,
- const hsize_t **coord)
+ const hsize_t *coord)
{
- H5S_t *space = NULL; /* Dataspace to modify selection of */
- herr_t ret_value; /* return value */
+ H5S_t *space; /* Dataspace to modify selection of */
+ herr_t ret_value; /* Return value */
- FUNC_ENTER_API(H5Sselect_elements, FAIL);
- H5TRACE4("e", "iSsz**h", spaceid, op, num_elem, coord);
+ FUNC_ENTER_API(H5Sselect_elements, FAIL)
+ H5TRACE4("e", "iSsz*h", spaceid, op, num_elem, coord);
/* Check args */
- if (NULL == (space=H5I_object_verify(spaceid, H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace");
- if (H5S_SCALAR==H5S_GET_EXTENT_TYPE(space))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "point doesn't support H5S_SCALAR space");
- if (H5S_NULL==H5S_GET_EXTENT_TYPE(space))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "point doesn't support H5S_NULL space");
- if(coord==NULL || num_elem==0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "elements not specified");
- if(!(op==H5S_SELECT_SET || op==H5S_SELECT_APPEND || op==H5S_SELECT_PREPEND))
- HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "unsupported operation attempted");
+ if(NULL == (space = (H5S_t *)H5I_object_verify(spaceid, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
+ if(H5S_SCALAR == H5S_GET_EXTENT_TYPE(space))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "point doesn't support H5S_SCALAR space")
+ if(H5S_NULL == H5S_GET_EXTENT_TYPE(space))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "point doesn't support H5S_NULL space")
+ if(coord == NULL || num_elem == 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "elements not specified")
+ if(!(op == H5S_SELECT_SET || op == H5S_SELECT_APPEND || op == H5S_SELECT_PREPEND))
+ HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "unsupported operation attempted")
/* Call the real element selection routine */
- if((ret_value=H5S_select_elements(space,op,num_elem,coord))<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't select elements");
+ if((ret_value = H5S_select_elements(space, op, num_elem, coord)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't select elements")
done:
- FUNC_LEAVE_API(ret_value);
+ FUNC_LEAVE_API(ret_value)
} /* H5Sselect_elements() */
diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h
index c6f2ce5..e78fb51 100644
--- a/src/H5Sprivate.h
+++ b/src/H5Sprivate.h
@@ -78,8 +78,9 @@ typedef struct {
/* "Flattened" regular hyperslab selection fields */
H5S_hyper_dim_t diminfo[H5S_MAX_RANK]; /* "Flattened" regular selection information */
- hsize_t size[H5S_MAX_RANK]; /* "Flattened" dataspace extent information */
- hssize_t sel_off[H5S_MAX_RANK]; /* "Flattened" selection offset information */
+ hsize_t size[H5S_MAX_RANK]; /* "Flattened" dataspace extent information */
+ hssize_t sel_off[H5S_MAX_RANK]; /* "Flattened" selection offset information */
+ hbool_t flattened[H5S_MAX_RANK]; /* Whether this dimension has been flattened */
/* Irregular hyperslab selection fields */
H5S_hyper_span_info_t *spans; /* Pointer to copy of the span tree */
@@ -114,31 +115,6 @@ typedef struct H5S_sel_iter_t {
} u;
} H5S_sel_iter_t;
-#ifdef H5S_DEBUG
-typedef struct H5S_iostats_t {
- H5S_sel_type ftype;
- H5S_sel_type mtype;
-
- struct {
- H5_timer_t scat_timer; /*time spent scattering */
- hsize_t scat_nbytes; /*scatter throughput */
- hsize_t scat_ncalls; /*number of calls */
- H5_timer_t gath_timer; /*time spent gathering */
- hsize_t gath_nbytes; /*gather throughput */
- hsize_t gath_ncalls; /*number of calls */
- H5_timer_t bkg_timer; /*time for background */
- hsize_t bkg_nbytes; /*background throughput */
- hsize_t bkg_ncalls; /*number of calls */
- H5_timer_t read_timer; /*time for read calls */
- hsize_t read_nbytes; /*total bytes read */
- hsize_t read_ncalls; /*number of calls */
- H5_timer_t write_timer; /*time for write calls */
- hsize_t write_nbytes; /*total bytes written */
- hsize_t write_ncalls; /*number of calls */
- } stats[2]; /* 0=output, 1=input */
-} H5S_iostats_t;
-#endif
-
/* If the module using this macro is allowed access to the private variables, access them directly */
#ifdef H5S_PACKAGE
#define H5S_GET_EXTENT_TYPE(S) ((S)->extent.type)
@@ -152,9 +128,11 @@ typedef struct H5S_iostats_t {
#define H5S_SELECT_SERIAL_SIZE(S) ((*(S)->select.type->serial_size)(S))
#define H5S_SELECT_SERIALIZE(S,BUF) ((*(S)->select.type->serialize)(S,BUF))
#define H5S_SELECT_BOUNDS(S,START,END) ((*(S)->select.type->bounds)(S,START,END))
+#define H5S_SELECT_OFFSET(S, OFFSET) ((*(S)->select.type->offset)(S, OFFSET))
#define H5S_SELECT_IS_CONTIGUOUS(S) ((*(S)->select.type->is_contiguous)(S))
#define H5S_SELECT_IS_SINGLE(S) ((*(S)->select.type->is_single)(S))
#define H5S_SELECT_IS_REGULAR(S) ((*(S)->select.type->is_regular)(S))
+#define H5S_SELECT_ADJUST_U(S,O) ((*(S)->select.type->adjust_u)(S, O))
#define H5S_SELECT_ITER_COORDS(ITER,COORDS) ((*(ITER)->type->iter_coords)(ITER,COORDS))
#define H5S_SELECT_ITER_BLOCK(ITER,START,END) ((*(ITER)->type->iter_block)(ITER,START,END))
#define H5S_SELECT_ITER_NELMTS(ITER) ((*(ITER)->type->iter_nelmts)(ITER))
@@ -174,9 +152,11 @@ typedef struct H5S_iostats_t {
#define H5S_SELECT_SERIAL_SIZE(S) (H5S_select_serial_size(S))
#define H5S_SELECT_SERIALIZE(S,BUF) (H5S_select_serialize(S,BUF))
#define H5S_SELECT_BOUNDS(S,START,END) (H5S_get_select_bounds(S,START,END))
+#define H5S_SELECT_OFFSET(S, OFFSET) (H5S_get_select_offset(S, OFFSET))
#define H5S_SELECT_IS_CONTIGUOUS(S) (H5S_select_is_contiguous(S))
#define H5S_SELECT_IS_SINGLE(S) (H5S_select_is_single(S))
#define H5S_SELECT_IS_REGULAR(S) (H5S_select_is_regular(S))
+#define H5S_SELECT_ADJUST_U(S,O) (H5S_select_adjust_u(S, O))
#define H5S_SELECT_ITER_COORDS(ITER,COORDS) (H5S_select_iter_coords(ITER,COORDS))
#define H5S_SELECT_ITER_BLOCK(ITER,START,END) (H5S_select_iter_block(ITER,START,END))
#define H5S_SELECT_ITER_NELMTS(ITER) (H5S_select_iter_nelmts(ITER))
@@ -191,11 +171,8 @@ typedef struct H5S_iostats_t {
/* Operations on dataspaces */
-H5_DLL H5S_t *H5S_copy(const H5S_t *src, hbool_t share_selection);
+H5_DLL H5S_t *H5S_copy(const H5S_t *src, hbool_t share_selection, hbool_t copy_max);
H5_DLL herr_t H5S_close(H5S_t *ds);
-#ifdef H5S_DEBUG
-H5_DLL H5S_iostats_t *H5S_find(const H5S_t *mem_space, const H5S_t *file_space);
-#endif /* H5S_DEBUG */
H5_DLL H5S_class_t H5S_get_simple_extent_type(const H5S_t *ds);
H5_DLL hssize_t H5S_get_simple_extent_npoints(const H5S_t *ds);
H5_DLL hsize_t H5S_get_npoints_max(const H5S_t *ds);
@@ -203,10 +180,9 @@ H5_DLL hbool_t H5S_has_extent(const H5S_t *ds);
H5_DLL int H5S_get_simple_extent_ndims(const H5S_t *ds);
H5_DLL int H5S_get_simple_extent_dims(const H5S_t *ds, hsize_t dims[]/*out*/,
hsize_t max_dims[]/*out*/);
-H5_DLL herr_t H5S_write(struct H5O_loc_t *loc, const H5S_t *space,
- hbool_t update_time, hid_t dxpl_id);
-H5_DLL herr_t H5S_append(H5F_t *f, hid_t dxpl_id, struct H5O_t *oh,
- const H5S_t *ds);
+H5_DLL herr_t H5S_write(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned update_flags,
+ H5S_t *ds);
+H5_DLL herr_t H5S_append(H5F_t *f, hid_t dxpl_id, struct H5O_t *oh, H5S_t *ds);
H5_DLL H5S_t *H5S_read(const struct H5O_loc_t *loc, hid_t dxpl_id);
H5_DLL int H5S_set_extent(H5S_t *space, const hsize_t *size);
H5_DLL herr_t H5S_set_extent_real(H5S_t *space, const hsize_t *size);
@@ -220,7 +196,9 @@ H5_DLL herr_t H5S_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE *stream
H5_DLL int H5S_extend(H5S_t *space, const hsize_t *size);
#endif /* H5_NO_DEPRECATED_SYMBOLS */
+/* Operations on dataspace extents */
H5_DLL hsize_t H5S_extent_nelem(const H5S_extent_t *ext);
+H5_DLL htri_t H5S_extent_equal(const H5S_t *ds1, const H5S_t *ds2);
/* Operations on selections */
H5_DLL herr_t H5S_select_deserialize(H5S_t *space, const uint8_t *buf);
@@ -232,6 +210,7 @@ H5_DLL herr_t H5S_select_fill(const void *fill, size_t fill_size,
H5_DLL htri_t H5S_select_valid(const H5S_t *space);
H5_DLL hssize_t H5S_get_select_npoints(const H5S_t *space);
H5_DLL herr_t H5S_get_select_bounds(const H5S_t *space, hsize_t *start, hsize_t *end);
+H5_DLL herr_t H5S_get_select_offset(const H5S_t *space, hsize_t *offset);
H5_DLL herr_t H5S_select_offset(H5S_t *space, const hssize_t *offset);
H5_DLL herr_t H5S_select_copy(H5S_t *dst, const H5S_t *src, hbool_t share_selection);
H5_DLL htri_t H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2);
@@ -244,6 +223,7 @@ H5_DLL herr_t H5S_select_serialize(const H5S_t *space, uint8_t *buf);
H5_DLL htri_t H5S_select_is_contiguous(const H5S_t *space);
H5_DLL htri_t H5S_select_is_single(const H5S_t *space);
H5_DLL htri_t H5S_select_is_regular(const H5S_t *space);
+H5_DLL herr_t H5S_select_adjust_u(H5S_t *space, const hsize_t *offset);
/* Operations on all selections */
H5_DLL herr_t H5S_select_all(H5S_t *space, hbool_t rel_prev);
@@ -252,8 +232,8 @@ H5_DLL herr_t H5S_select_all(H5S_t *space, hbool_t rel_prev);
H5_DLL herr_t H5S_select_none(H5S_t *space);
/* Operations on point selections */
-H5_DLL herr_t H5S_select_elements (H5S_t *space, H5S_seloper_t op,
- size_t num_elem, const hsize_t **coord);
+H5_DLL herr_t H5S_select_elements(H5S_t *space, H5S_seloper_t op,
+ size_t num_elem, const hsize_t *coord);
/* Operations on hyperslab selections */
H5_DLL herr_t H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, const hsize_t start[],
@@ -266,10 +246,9 @@ H5_DLL herr_t H5S_hyper_convert(H5S_t *space);
H5_DLL htri_t H5S_hyper_intersect (H5S_t *space1, H5S_t *space2);
#endif /* LATER */
H5_DLL htri_t H5S_hyper_intersect_block (H5S_t *space, hsize_t *start, hsize_t *end);
-H5_DLL herr_t H5S_hyper_adjust_u(H5S_t *space, const hsize_t *offset);
H5_DLL herr_t H5S_hyper_adjust_s(H5S_t *space, const hssize_t *offset);
H5_DLL herr_t H5S_hyper_move(H5S_t *space, const hssize_t *offset);
-H5_DLL herr_t H5S_hyper_normalize_offset(H5S_t *space, hssize_t *old_offset);
+H5_DLL htri_t H5S_hyper_normalize_offset(H5S_t *space, hssize_t *old_offset);
H5_DLL herr_t H5S_hyper_denormalize_offset(H5S_t *space, const hssize_t *old_offset);
/* Operations on selection iterators */
diff --git a/src/H5Spublic.h b/src/H5Spublic.h
index 4a49da2..c62a7b7 100644
--- a/src/H5Spublic.h
+++ b/src/H5Spublic.h
@@ -126,8 +126,7 @@ H5_DLL hid_t H5Scombine_select(hid_t space1_id, H5S_seloper_t op,
hid_t space2_id);
#endif /* NEW_HYPERSLAB_API */
H5_DLL herr_t H5Sselect_elements(hid_t space_id, H5S_seloper_t op,
- size_t num_elemn,
- const hsize_t **coord);
+ size_t num_elem, const hsize_t *coord);
H5_DLL H5S_class_t H5Sget_simple_extent_type(hid_t space_id);
H5_DLL herr_t H5Sset_extent_none(hid_t space_id);
H5_DLL herr_t H5Sextent_copy(hid_t dst_id,hid_t src_id);
@@ -138,12 +137,16 @@ H5_DLL herr_t H5Soffset_simple(hid_t space_id, const hssize_t *offset);
H5_DLL htri_t H5Sselect_valid(hid_t spaceid);
H5_DLL hssize_t H5Sget_select_hyper_nblocks(hid_t spaceid);
H5_DLL hssize_t H5Sget_select_elem_npoints(hid_t spaceid);
-H5_DLL herr_t H5Sget_select_hyper_blocklist(hid_t spaceid, hsize_t startblock, hsize_t numblocks, hsize_t *buf);
-H5_DLL herr_t H5Sget_select_elem_pointlist(hid_t spaceid, hsize_t startpoint, hsize_t numpoints, hsize_t *buf);
-H5_DLL herr_t H5Sget_select_bounds(hid_t spaceid, hsize_t *start, hsize_t *end);
+H5_DLL herr_t H5Sget_select_hyper_blocklist(hid_t spaceid, hsize_t startblock,
+ hsize_t numblocks, hsize_t buf[/*numblocks*/]);
+H5_DLL herr_t H5Sget_select_elem_pointlist(hid_t spaceid, hsize_t startpoint,
+ hsize_t numpoints, hsize_t buf[/*numpoints*/]);
+H5_DLL herr_t H5Sget_select_bounds(hid_t spaceid, hsize_t start[],
+ hsize_t end[]);
H5_DLL H5S_sel_type H5Sget_select_type(hid_t spaceid);
#ifdef __cplusplus
}
#endif
-#endif
+#endif /* _H5Spublic_H */
+
diff --git a/src/H5Sselect.c b/src/H5Sselect.c
index e3b90bb..2a9c4dc 100644
--- a/src/H5Sselect.c
+++ b/src/H5Sselect.c
@@ -62,17 +62,20 @@ static herr_t H5S_select_iter_next_block(H5S_sel_iter_t *iter);
herr_t
H5S_select_offset(H5S_t *space, const hssize_t *offset)
{
- FUNC_ENTER_NOAPI_NOFUNC(H5S_select_offset);
+ FUNC_ENTER_NOAPI_NOFUNC(H5S_select_offset)
/* Check args */
- assert(space);
- assert(space->extent.rank);
- assert(offset);
+ HDassert(space);
+ HDassert(space->extent.rank);
+ HDassert(offset);
/* Copy the offset over */
- HDmemcpy(space->select.offset,offset,sizeof(hssize_t)*space->extent.rank);
+ HDmemcpy(space->select.offset, offset, sizeof(hssize_t)*space->extent.rank);
+
+ /* Indicate that the offset was changed */
+ space->select.offset_changed = TRUE;
- FUNC_LEAVE_NOAPI(SUCCEED);
+ FUNC_LEAVE_NOAPI(SUCCEED)
} /* H5S_select_offset() */
@@ -288,20 +291,20 @@ H5S_select_serialize(const H5S_t *space, uint8_t *buf)
hssize_t
H5Sget_select_npoints(hid_t spaceid)
{
- H5S_t *space = NULL; /* Dataspace to modify selection of */
+ H5S_t *space; /* Dataspace to modify selection of */
hssize_t ret_value; /* return value */
- FUNC_ENTER_API(H5Sget_select_npoints, FAIL);
+ FUNC_ENTER_API(H5Sget_select_npoints, FAIL)
H5TRACE1("Hs", "i", spaceid);
/* Check args */
- if (NULL == (space=H5I_object_verify(spaceid, H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace");
+ if(NULL == (space = (H5S_t *)H5I_object_verify(spaceid, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
ret_value = H5S_GET_SELECT_NPOINTS(space);
done:
- FUNC_LEAVE_API(ret_value);
+ FUNC_LEAVE_API(ret_value)
} /* H5Sget_select_npoints() */
@@ -362,20 +365,20 @@ H5S_get_select_npoints(const H5S_t *space)
htri_t
H5Sselect_valid(hid_t spaceid)
{
- H5S_t *space = NULL; /* Dataspace to modify selection of */
- htri_t ret_value; /* return value */
+ H5S_t *space; /* Dataspace to modify selection of */
+ htri_t ret_value; /* return value */
- FUNC_ENTER_API(H5Sselect_valid, FAIL);
+ FUNC_ENTER_API(H5Sselect_valid, FAIL)
H5TRACE1("t", "i", spaceid);
/* Check args */
- if (NULL == (space=H5I_object_verify(spaceid, H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace");
+ if(NULL == (space = (H5S_t *)H5I_object_verify(spaceid, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
ret_value = H5S_SELECT_VALID(space);
done:
- FUNC_LEAVE_API(ret_value);
+ FUNC_LEAVE_API(ret_value)
} /* H5Sselect_valid() */
@@ -488,8 +491,8 @@ done:
USAGE
herr_t H5S_get_select_bounds(space, start, end)
hid_t dsid; IN: Dataspace ID of selection to query
- hsize_t *start; OUT: Starting coordinate of bounding box
- hsize_t *end; OUT: Opposite coordinate of bounding box
+ hsize_t start[]; OUT: Starting coordinate of bounding box
+ hsize_t end[]; OUT: Opposite coordinate of bounding box
RETURNS
Non-negative on success, negative on failure
DESCRIPTION
@@ -511,24 +514,24 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
herr_t
-H5Sget_select_bounds(hid_t spaceid, hsize_t *start, hsize_t *end)
+H5Sget_select_bounds(hid_t spaceid, hsize_t start[], hsize_t end[])
{
- H5S_t *space = NULL; /* Dataspace to modify selection of */
- herr_t ret_value; /* return value */
+ H5S_t *space; /* Dataspace to modify selection of */
+ herr_t ret_value; /* return value */
- FUNC_ENTER_API(H5Sget_select_bounds, FAIL);
+ FUNC_ENTER_API(H5Sget_select_bounds, FAIL)
H5TRACE3("e", "i*h*h", spaceid, start, end);
/* Check args */
- if(start==NULL || end==NULL)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid pointer");
- if (NULL == (space=H5I_object_verify(spaceid, H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace");
+ if(start == NULL || end == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid pointer")
+ if(NULL == (space = (H5S_t *)H5I_object_verify(spaceid, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
- ret_value = H5S_SELECT_BOUNDS(space,start,end);
+ ret_value = H5S_SELECT_BOUNDS(space, start, end);
done:
- FUNC_LEAVE_API(ret_value);
+ FUNC_LEAVE_API(ret_value)
} /* H5Sget_select_bounds() */
@@ -579,6 +582,46 @@ H5S_get_select_bounds(const H5S_t *space, hsize_t *start, hsize_t *end)
/*--------------------------------------------------------------------------
NAME
+ H5S_get_select_offset
+ PURPOSE
+ Gets the linear offset of the first element for the selection.
+ USAGE
+ herr_t H5S_get_select_offset(space, offset)
+ const H5S_t *space; IN: Dataspace pointer of selection to query
+ hsize_t *offset; OUT: Linear offset of first element in selection
+ RETURNS
+ Non-negative on success, negative on failure
+ DESCRIPTION
+ Retrieves the linear offset (in "units" of elements) of the first element
+ selected within the dataspace.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ The offset calculation _does_ include the current offset of the
+ selection within the dataspace extent.
+
+ Calling this function on a "none" selection returns fail.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5S_get_select_offset(const H5S_t *space, hsize_t *offset)
+{
+ herr_t ret_value; /* return value */
+
+ FUNC_ENTER_NOAPI_NOFUNC(H5S_get_select_offset)
+
+ /* Check args */
+ HDassert(space);
+ HDassert(offset);
+
+ ret_value = (*space->select.type->offset)(space, offset);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5S_get_select_offset() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
H5S_select_is_contiguous
PURPOSE
Determines if a selection is contiguous in the dataspace
@@ -690,6 +733,43 @@ H5S_select_is_regular(const H5S_t *space)
/*--------------------------------------------------------------------------
NAME
+ H5S_select_adjust_u
+ PURPOSE
+ Adjust a selection by subtracting an offset
+ USAGE
+ herr_t H5S_select_adjust_u(space, offset)
+ H5S_t *space; IN/OUT: Pointer to dataspace to adjust
+ const hsize_t *offset; IN: Offset to subtract
+ RETURNS
+ Non-negative on success, negative on failure
+ DESCRIPTION
+ Moves a selection by subtracting an offset from it.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ This routine participates in the "Inlining C function pointers"
+ pattern, don't call it directly, use the appropriate macro
+ defined in H5Sprivate.h.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5S_select_adjust_u(H5S_t *space, const hsize_t *offset)
+{
+ herr_t ret_value; /* return value */
+
+ FUNC_ENTER_NOAPI_NOFUNC(H5S_select_adjust_u)
+
+ /* Check args */
+ HDassert(space);
+
+ ret_value = (*space->select.type->adjust_u)(space, offset);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5S_select_adjust_u() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
H5S_select_iter_init
PURPOSE
Initializes iteration information for a selection.
@@ -721,10 +801,9 @@ H5S_select_iter_init(H5S_sel_iter_t *sel_iter, const H5S_t *space, size_t elmt_s
/* Save the dataspace's rank */
sel_iter->rank=space->extent.rank;
- if(sel_iter->rank>0) {
- /* Point to the dataspace dimensions */
- sel_iter->dims=space->extent.size;
- } /* end if */
+ /* Point to the dataspace dimensions, if there are any */
+ if(sel_iter->rank > 0)
+ sel_iter->dims = space->extent.size;
else
sel_iter->dims = NULL;
@@ -1055,7 +1134,7 @@ H5S_select_iterate(void *buf, hid_t type_id, const H5S_t *space, H5D_operator_t
{
H5T_t *dt; /* Datatype structure */
H5S_sel_iter_t iter; /* Selection iteration info */
- hbool_t iter_init=0; /* Selection iteration info has been initialized */
+ hbool_t iter_init = FALSE; /* Selection iteration info has been initialized */
uint8_t *loc; /* Current element location in buffer */
hsize_t coords[H5O_LAYOUT_NDIMS]; /* Coordinates of element in dataspace */
hssize_t nelmts; /* Number of elements in selection */
@@ -1078,44 +1157,44 @@ H5S_select_iterate(void *buf, hid_t type_id, const H5S_t *space, H5D_operator_t
FUNC_ENTER_NOAPI(H5S_select_iterate, FAIL);
/* Check args */
- assert(buf);
- assert(H5I_DATATYPE == H5I_get_type(type_id));
- assert(space);
- assert(op);
+ HDassert(buf);
+ HDassert(H5I_DATATYPE == H5I_get_type(type_id));
+ HDassert(space);
+ HDassert(op);
/* Get the datatype size */
- if (NULL==(dt=H5I_object_verify(type_id,H5I_DATATYPE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an valid base datatype");
- if((elmt_size=H5T_get_size(dt))==0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_BADSIZE, FAIL, "datatype size invalid");
+ if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an valid base datatype")
+ if(0 == (elmt_size = H5T_get_size(dt)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_BADSIZE, FAIL, "datatype size invalid")
/* Initialize iterator */
- if (H5S_select_iter_init(&iter, space, elmt_size)<0)
- HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator");
- iter_init=1; /* Selection iteration info has been initialized */
+ if(H5S_select_iter_init(&iter, space, elmt_size) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator")
+ iter_init = TRUE; /* Selection iteration info has been initialized */
/* Get the number of elements in selection */
- if((nelmts = H5S_GET_SELECT_NPOINTS(space))<0)
- HGOTO_ERROR (H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't get number of elements selected");
+ if((nelmts = H5S_GET_SELECT_NPOINTS(space)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't get number of elements selected")
/* Get the rank of the dataspace */
- ndims=space->extent.rank;
+ ndims = space->extent.rank;
- if (ndims > 0){
+ if(ndims > 0) {
/* Copy the size of the space */
- assert(space->extent.size);
- HDmemcpy(space_size, space->extent.size, ndims*sizeof(hsize_t));
- }
- space_size[ndims]=elmt_size;
+ HDassert(space->extent.size);
+ HDmemcpy(space_size, space->extent.size, ndims * sizeof(hsize_t));
+ } /* end if */
+ space_size[ndims] = elmt_size;
/* Compute the maximum number of bytes required */
- H5_ASSIGN_OVERFLOW(max_elem,nelmts,hssize_t,size_t);
+ H5_ASSIGN_OVERFLOW(max_elem, nelmts, hssize_t, size_t);
/* Loop, while elements left in selection */
- while(max_elem>0 && user_ret==0) {
+ while(max_elem > 0 && user_ret == 0) {
/* Get the sequences of bytes */
if(H5S_SELECT_GET_SEQ_LIST(space, 0, &iter, (size_t)H5D_IO_VECTOR_SIZE, max_elem, &nseq, &nelem, off, len) < 0)
- HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed");
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed")
/* Loop, while sequences left to process */
for(curr_seq=0; curr_seq<nseq && user_ret==0; curr_seq++) {
@@ -1156,12 +1235,10 @@ H5S_select_iterate(void *buf, hid_t type_id, const H5S_t *space, H5D_operator_t
done:
/* Release selection iterator */
- if(iter_init) {
- if (H5S_SELECT_ITER_RELEASE(&iter)<0)
- HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator");
- } /* end if */
+ if(iter_init && H5S_SELECT_ITER_RELEASE(&iter) < 0)
+ HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator")
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_select_iterate() */
@@ -1183,21 +1260,21 @@ done:
H5S_sel_type
H5Sget_select_type(hid_t space_id)
{
- H5S_t *space = NULL; /* dataspace to modify */
- H5S_sel_type ret_value; /* Return value */
+ H5S_t *space; /* dataspace to modify */
+ H5S_sel_type ret_value; /* Return value */
- FUNC_ENTER_API(H5Sget_select_type, H5S_SEL_ERROR);
+ FUNC_ENTER_API(H5Sget_select_type, H5S_SEL_ERROR)
H5TRACE1("St", "i", space_id);
/* Check args */
- if (NULL == (space = H5I_object_verify(space_id, H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, H5S_SEL_ERROR, "not a dataspace");
+ if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, H5S_SEL_ERROR, "not a dataspace")
/* Set return value */
- ret_value=H5S_GET_SELECT_TYPE(space);
+ ret_value = H5S_GET_SELECT_TYPE(space);
done:
- FUNC_LEAVE_API(ret_value);
+ FUNC_LEAVE_API(ret_value)
} /* end H5Sget_select_type() */
@@ -1261,137 +1338,145 @@ H5S_get_select_type(const H5S_t *space)
htri_t
H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2)
{
- H5S_sel_iter_t iter1; /* Selection #1 iteration info */
- H5S_sel_iter_t iter2; /* Selection #2 iteration info */
- hbool_t iter1_init=0; /* Selection #1 iteration info has been initialized */
- hbool_t iter2_init=0; /* Selection #2 iteration info has been initialized */
- unsigned u; /* Index variable */
- htri_t ret_value=TRUE; /* return value */
+ H5S_sel_iter_t iter1; /* Selection #1 iteration info */
+ H5S_sel_iter_t iter2; /* Selection #2 iteration info */
+ hbool_t iter1_init = 0; /* Selection #1 iteration info has been initialized */
+ hbool_t iter2_init = 0; /* Selection #2 iteration info has been initialized */
+ unsigned u; /* Index variable */
+ htri_t ret_value = TRUE; /* Return value */
- FUNC_ENTER_NOAPI(H5S_select_shape_same, FAIL);
+ FUNC_ENTER_NOAPI(H5S_select_shape_same, FAIL)
/* Check args */
- assert(space1);
- assert(space2);
-
- /* Check for different dimensionality */
- if (space1->extent.rank!=space2->extent.rank)
- HGOTO_DONE(FALSE);
-
- /* Check for different number of elements selected */
- if(H5S_GET_SELECT_NPOINTS(space1)!=H5S_GET_SELECT_NPOINTS(space2))
- HGOTO_DONE(FALSE);
-
- /* Check for "easy" cases before getting into generalized block iteration code */
- if(H5S_GET_SELECT_TYPE(space1)==H5S_SEL_ALL && H5S_GET_SELECT_TYPE(space2)==H5S_SEL_ALL) {
- hsize_t dims1[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace #1 */
- hsize_t dims2[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace #2 */
-
- if(H5S_get_simple_extent_dims(space1, dims1, NULL)<0)
- HGOTO_ERROR (H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality");
- if(H5S_get_simple_extent_dims(space2, dims2, NULL)<0)
- HGOTO_ERROR (H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality");
-
- /* Check that the sizes are the same */
- for (u=0; u<space1->extent.rank; u++)
- if(dims1[u]!=dims2[u])
- HGOTO_DONE(FALSE);
+ HDassert(space1);
+ HDassert(space2);
+
+ /* Special case for one or both dataspaces being scalar */
+ if(space1->extent.rank == 0 || space2->extent.rank == 0) {
+ /* Check for different number of elements selected */
+ if(H5S_GET_SELECT_NPOINTS(space1) != H5S_GET_SELECT_NPOINTS(space2))
+ HGOTO_DONE(FALSE)
} /* end if */
- else if(H5S_GET_SELECT_TYPE(space1)==H5S_SEL_NONE || H5S_GET_SELECT_TYPE(space2)==H5S_SEL_NONE) {
- HGOTO_DONE(TRUE);
- } /* end if */
- else if((H5S_GET_SELECT_TYPE(space1)==H5S_SEL_HYPERSLABS && space1->select.sel_info.hslab->diminfo_valid)
- && (H5S_GET_SELECT_TYPE(space2)==H5S_SEL_HYPERSLABS && space2->select.sel_info.hslab->diminfo_valid)) {
-
- /* Check that the shapes are the same */
- for (u=0; u<space1->extent.rank; u++) {
- if(space1->select.sel_info.hslab->opt_diminfo[u].stride!=space2->select.sel_info.hslab->opt_diminfo[u].stride)
- HGOTO_DONE(FALSE);
- if(space1->select.sel_info.hslab->opt_diminfo[u].count!=space2->select.sel_info.hslab->opt_diminfo[u].count)
- HGOTO_DONE(FALSE);
- if(space1->select.sel_info.hslab->opt_diminfo[u].block!=space2->select.sel_info.hslab->opt_diminfo[u].block)
- HGOTO_DONE(FALSE);
- } /* end for */
- } /* end if */
- /* Iterate through all the blocks in the selection */
else {
- hsize_t start1[H5O_LAYOUT_NDIMS]; /* Start point of selection block in dataspace #1 */
- hsize_t start2[H5O_LAYOUT_NDIMS]; /* Start point of selection block in dataspace #2 */
- hsize_t end1[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace #1 */
- hsize_t end2[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace #2 */
- hsize_t off1[H5O_LAYOUT_NDIMS]; /* Offset of selection #1 blocks */
- hsize_t off2[H5O_LAYOUT_NDIMS]; /* Offset of selection #2 blocks */
- htri_t status1,status2; /* Status from next block checks */
- unsigned first_block=1; /* Flag to indicate the first block */
-
- /* Initialize iterator for each dataspace selection
- * Use '0' for element size instead of actual element size to indicate
- * that the selection iterator shouldn't be "flattened", since we
- * aren't actually going to be doing I/O with the iterators.
- */
- if(H5S_select_iter_init(&iter1, space1, (size_t)0) < 0)
- HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator");
- iter1_init = 1;
- if(H5S_select_iter_init(&iter2, space2, (size_t)0) < 0)
- HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator");
- iter2_init = 1;
-
- /* Iterate over all the blocks in each selection */
- while(1) {
- /* Get the current block for each selection iterator */
- if(H5S_SELECT_ITER_BLOCK(&iter1,start1,end1)<0)
- HGOTO_ERROR (H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get iterator block");
- if(H5S_SELECT_ITER_BLOCK(&iter2,start2,end2)<0)
- HGOTO_ERROR (H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get iterator block");
-
- /* The first block only compares the sizes and sets the relative offsets for later blocks */
- if(first_block) {
- /* If the block sizes from each selection doesn't match, get out */
- for (u=0; u<space1->extent.rank; u++) {
- if((end1[u]-start1[u])!=(end2[u]-start2[u]))
- HGOTO_DONE(FALSE);
-
- /* Set the relative locations of the selections */
- off1[u]=start1[u];
- off2[u]=start2[u];
- } /* end for */
-
- /* Reset "first block" flag */
- first_block=0;
- } /* end if */
- else {
- /* Check over the blocks for each selection */
- for (u=0; u<space1->extent.rank; u++) {
- /* Check if the blocks are in the same relative location */
- if((start1[u]-off1[u])!=(start2[u]-off2[u]))
- HGOTO_DONE(FALSE);
-
+ /* Check for different dimensionality */
+ if(space1->extent.rank != space2->extent.rank)
+ HGOTO_DONE(FALSE)
+
+ /* Check for different number of elements selected */
+ if(H5S_GET_SELECT_NPOINTS(space1) != H5S_GET_SELECT_NPOINTS(space2))
+ HGOTO_DONE(FALSE)
+
+ /* Check for "easy" cases before getting into generalized block iteration code */
+ if(H5S_GET_SELECT_TYPE(space1)==H5S_SEL_ALL && H5S_GET_SELECT_TYPE(space2)==H5S_SEL_ALL) {
+ hsize_t dims1[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace #1 */
+ hsize_t dims2[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace #2 */
+
+ if(H5S_get_simple_extent_dims(space1, dims1, NULL)<0)
+ HGOTO_ERROR (H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality");
+ if(H5S_get_simple_extent_dims(space2, dims2, NULL)<0)
+ HGOTO_ERROR (H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality");
+
+ /* Check that the sizes are the same */
+ for (u=0; u<space1->extent.rank; u++)
+ if(dims1[u]!=dims2[u])
+ HGOTO_DONE(FALSE);
+ } /* end if */
+ else if(H5S_GET_SELECT_TYPE(space1)==H5S_SEL_NONE || H5S_GET_SELECT_TYPE(space2)==H5S_SEL_NONE) {
+ HGOTO_DONE(TRUE);
+ } /* end if */
+ else if((H5S_GET_SELECT_TYPE(space1)==H5S_SEL_HYPERSLABS && space1->select.sel_info.hslab->diminfo_valid)
+ && (H5S_GET_SELECT_TYPE(space2)==H5S_SEL_HYPERSLABS && space2->select.sel_info.hslab->diminfo_valid)) {
+
+ /* Check that the shapes are the same */
+ for (u=0; u<space1->extent.rank; u++) {
+ if(space1->select.sel_info.hslab->opt_diminfo[u].stride!=space2->select.sel_info.hslab->opt_diminfo[u].stride)
+ HGOTO_DONE(FALSE);
+ if(space1->select.sel_info.hslab->opt_diminfo[u].count!=space2->select.sel_info.hslab->opt_diminfo[u].count)
+ HGOTO_DONE(FALSE);
+ if(space1->select.sel_info.hslab->opt_diminfo[u].block!=space2->select.sel_info.hslab->opt_diminfo[u].block)
+ HGOTO_DONE(FALSE);
+ } /* end for */
+ } /* end if */
+ /* Iterate through all the blocks in the selection */
+ else {
+ hsize_t start1[H5O_LAYOUT_NDIMS]; /* Start point of selection block in dataspace #1 */
+ hsize_t start2[H5O_LAYOUT_NDIMS]; /* Start point of selection block in dataspace #2 */
+ hsize_t end1[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace #1 */
+ hsize_t end2[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace #2 */
+ hsize_t off1[H5O_LAYOUT_NDIMS]; /* Offset of selection #1 blocks */
+ hsize_t off2[H5O_LAYOUT_NDIMS]; /* Offset of selection #2 blocks */
+ htri_t status1,status2; /* Status from next block checks */
+ unsigned first_block=1; /* Flag to indicate the first block */
+
+ /* Initialize iterator for each dataspace selection
+ * Use '0' for element size instead of actual element size to indicate
+ * that the selection iterator shouldn't be "flattened", since we
+ * aren't actually going to be doing I/O with the iterators.
+ */
+ if(H5S_select_iter_init(&iter1, space1, (size_t)0) < 0)
+ HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator");
+ iter1_init = 1;
+ if(H5S_select_iter_init(&iter2, space2, (size_t)0) < 0)
+ HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator");
+ iter2_init = 1;
+
+ /* Iterate over all the blocks in each selection */
+ while(1) {
+ /* Get the current block for each selection iterator */
+ if(H5S_SELECT_ITER_BLOCK(&iter1,start1,end1)<0)
+ HGOTO_ERROR (H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get iterator block");
+ if(H5S_SELECT_ITER_BLOCK(&iter2,start2,end2)<0)
+ HGOTO_ERROR (H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get iterator block");
+
+ /* The first block only compares the sizes and sets the relative offsets for later blocks */
+ if(first_block) {
/* If the block sizes from each selection doesn't match, get out */
- if((end1[u]-start1[u])!=(end2[u]-start2[u]))
- HGOTO_DONE(FALSE);
- } /* end for */
- } /* end else */
-
- /* Check if we are able to advance to the next selection block */
- if((status1=H5S_SELECT_ITER_HAS_NEXT_BLOCK(&iter1))<0)
- HGOTO_ERROR (H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to check iterator block");
- if((status2=H5S_SELECT_ITER_HAS_NEXT_BLOCK(&iter2))<0)
- HGOTO_ERROR (H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to check iterator block");
-
- /* Did we run out of blocks at the same time? */
- if(status1==FALSE && status2==FALSE)
- break;
- else if(status1!=status2) {
- HGOTO_DONE(FALSE);
- } /* end if */
- else {
- /* Advance to next block in selection iterators */
- if(H5S_SELECT_ITER_NEXT_BLOCK(&iter1)<0)
- HGOTO_ERROR (H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to advance to next iterator block");
- if(H5S_SELECT_ITER_NEXT_BLOCK(&iter2)<0)
- HGOTO_ERROR (H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to advance to next iterator block");
- } /* end else */
- } /* end while */
+ for (u=0; u<space1->extent.rank; u++) {
+ if((end1[u]-start1[u])!=(end2[u]-start2[u]))
+ HGOTO_DONE(FALSE);
+
+ /* Set the relative locations of the selections */
+ off1[u]=start1[u];
+ off2[u]=start2[u];
+ } /* end for */
+
+ /* Reset "first block" flag */
+ first_block=0;
+ } /* end if */
+ else {
+ /* Check over the blocks for each selection */
+ for (u=0; u<space1->extent.rank; u++) {
+ /* Check if the blocks are in the same relative location */
+ if((start1[u]-off1[u])!=(start2[u]-off2[u]))
+ HGOTO_DONE(FALSE);
+
+ /* If the block sizes from each selection doesn't match, get out */
+ if((end1[u]-start1[u])!=(end2[u]-start2[u]))
+ HGOTO_DONE(FALSE);
+ } /* end for */
+ } /* end else */
+
+ /* Check if we are able to advance to the next selection block */
+ if((status1=H5S_SELECT_ITER_HAS_NEXT_BLOCK(&iter1))<0)
+ HGOTO_ERROR (H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to check iterator block");
+ if((status2=H5S_SELECT_ITER_HAS_NEXT_BLOCK(&iter2))<0)
+ HGOTO_ERROR (H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to check iterator block");
+
+ /* Did we run out of blocks at the same time? */
+ if(status1==FALSE && status2==FALSE)
+ break;
+ else if(status1!=status2) {
+ HGOTO_DONE(FALSE);
+ } /* end if */
+ else {
+ /* Advance to next block in selection iterators */
+ if(H5S_SELECT_ITER_NEXT_BLOCK(&iter1)<0)
+ HGOTO_ERROR (H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to advance to next iterator block");
+ if(H5S_SELECT_ITER_NEXT_BLOCK(&iter2)<0)
+ HGOTO_ERROR (H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to advance to next iterator block");
+ } /* end else */
+ } /* end while */
+ } /* end else */
} /* end else */
done:
@@ -1404,7 +1489,7 @@ done:
HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator");
} /* end if */
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* H5S_select_shape_same() */
diff --git a/src/H5Stest.c b/src/H5Stest.c
index 85693da..787cdef 100644
--- a/src/H5Stest.c
+++ b/src/H5Stest.c
@@ -52,16 +52,16 @@
htri_t
H5S_select_shape_same_test(hid_t sid1, hid_t sid2)
{
- H5S_t *space1 = NULL; /* Pointer to 1st dataspace */
- H5S_t *space2 = NULL; /* Pointer to 2nd dataspace */
+ H5S_t *space1; /* Pointer to 1st dataspace */
+ H5S_t *space2; /* Pointer to 2nd dataspace */
htri_t ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5S_select_shape_same_test, FAIL)
/* Get dataspace structures */
- if(NULL == (space1 = H5I_object_verify(sid1, H5I_DATASPACE)))
+ if(NULL == (space1 = (H5S_t *)H5I_object_verify(sid1, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
- if(NULL == (space2 = H5I_object_verify(sid2, H5I_DATASPACE)))
+ if(NULL == (space2 = (H5S_t *)H5I_object_verify(sid2, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
/* Check if the dataspace selections are the same shape */
@@ -94,13 +94,13 @@ done:
htri_t
H5S_get_rebuild_status_test(hid_t space_id)
{
- H5S_t *space = NULL; /* Pointer to 1st dataspace */
+ H5S_t *space; /* Pointer to 1st dataspace */
htri_t ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5S_get_rebuild_status_test, FAIL)
/* Get dataspace structures */
- if(NULL == (space = H5I_object_verify(space_id, H5I_DATASPACE)))
+ if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
ret_value = space->select.sel_info.hslab->diminfo_valid;
diff --git a/src/H5T.c b/src/H5T.c
index 04d6c0b..ee02016 100644
--- a/src/H5T.c
+++ b/src/H5T.c
@@ -20,23 +20,30 @@
* one particular datatype class are in another module.
*/
+/****************/
+/* Module Setup */
+/****************/
+
#define H5T_PACKAGE /*suppress error about including H5Tpkg */
/* Interface initialization */
#define H5_INTERFACE_INIT_FUNC H5T_init_interface
-#include "H5private.h" /*generic functions */
-#include "H5Dprivate.h" /*datasets (for H5Tcopy) */
-#include "H5Eprivate.h" /*error handling */
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Dprivate.h" /* Datasets */
+#include "H5Eprivate.h" /* Error handling */
#include "H5Fprivate.h" /* Files */
#include "H5FLprivate.h" /* Free Lists */
#include "H5FOprivate.h" /* File objects */
-#include "H5Gprivate.h" /*groups */
-#include "H5Iprivate.h" /*ID functions */
-#include "H5MMprivate.h" /*memory management */
-#include "H5Pprivate.h" /* Property Lists */
-#include "H5Tpkg.h" /*data-type functions */
+#include "H5Gprivate.h" /* Groups */
+#include "H5Iprivate.h" /* IDs */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5Pprivate.h" /* Property lists */
+#include "H5Tpkg.h" /* Datatypes */
/* Check for header needed for SGI floating-point code */
#ifdef H5_HAVE_SYS_FPU_H
@@ -465,13 +472,13 @@ static H5T_t *H5T_decode(const unsigned char *buf);
#define H5T_INIT_TYPE_COPY_CREATE(BASE) { \
/* Base off of existing datatype */ \
if(NULL == (dt = H5T_copy(BASE, H5T_COPY_TRANSIENT))) \
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTCOPY, FAIL, "duplicating base type failed") \
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "duplicating base type failed") \
}
#define H5T_INIT_TYPE_ALLOC_CREATE(BASE) { \
/* Allocate new datatype info */ \
if(NULL == (dt = H5T_alloc())) \
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") \
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "memory allocation failed") \
}
@@ -484,10 +491,10 @@ static H5T_t *H5T_decode(const unsigned char *buf);
H5_GLUE3(H5T_INIT_TYPE_,SIZE_TMPL,_SIZE)(SIZE) \
\
/* Adjust information for this type */ \
- H5_GLUE3(H5T_INIT_TYPE_,GUTS,_CORE) \
+ H5_GLUE3(H5T_INIT_TYPE_, GUTS, _CORE) \
\
/* Atomize result */ \
- if((GLOBAL = H5I_register(H5I_DATATYPE, dt)) < 0) \
+ if((GLOBAL = H5I_register(H5I_DATATYPE, dt, FALSE)) < 0) \
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register datatype atom") \
}
@@ -546,9 +553,9 @@ H5T_init_inf(void)
uint8_t *d; /* Pointer to value to set */
size_t half_size; /* Half the type size */
size_t u; /* Local index value */
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5T_init_inf);
+ FUNC_ENTER_NOAPI_NOINIT(H5T_init_inf)
/* Get the float datatype */
if (NULL==(dst_p=H5I_object(H5T_NATIVE_FLOAT_g)))
@@ -556,40 +563,40 @@ H5T_init_inf(void)
dst = &dst_p->shared->u.atomic;
/* Check that we can re-order the bytes correctly */
- if (H5T_ORDER_LE!=H5T_native_order_g && H5T_ORDER_BE!=H5T_native_order_g)
- HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported byte order");
+ if(H5T_ORDER_LE != H5T_native_order_g && H5T_ORDER_BE != H5T_native_order_g)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported byte order")
/* +Inf */
- d=(uint8_t *)&H5T_NATIVE_FLOAT_POS_INF_g;
- H5T_bit_set (d, dst->u.f.sign, (size_t)1, FALSE);
- H5T_bit_set (d, dst->u.f.epos, dst->u.f.esize, TRUE);
- H5T_bit_set (d, dst->u.f.mpos, dst->u.f.msize, FALSE);
+ d = (uint8_t *)&H5T_NATIVE_FLOAT_POS_INF_g;
+ H5T_bit_set(d, dst->u.f.sign, (size_t)1, FALSE);
+ H5T_bit_set(d, dst->u.f.epos, dst->u.f.esize, TRUE);
+ H5T_bit_set(d, dst->u.f.mpos, dst->u.f.msize, FALSE);
/* Swap the bytes if the machine architecture is big-endian */
- if (H5T_ORDER_BE==H5T_native_order_g) {
- half_size = dst_p->shared->size/2;
- for (u=0; u<half_size; u++) {
- uint8_t tmp = d[dst_p->shared->size-(u+1)];
- d[dst_p->shared->size-(u+1)] = d[u];
+ if (H5T_ORDER_BE == H5T_native_order_g) {
+ half_size = dst_p->shared->size / 2;
+ for(u = 0; u < half_size; u++) {
+ uint8_t tmp = d[dst_p->shared->size - (u + 1)];
+ d[dst_p->shared->size - (u + 1)] = d[u];
d[u] = tmp;
- }
- }
+ } /* end for */
+ } /* end if */
/* -Inf */
- d=(uint8_t *)&H5T_NATIVE_FLOAT_NEG_INF_g;
- H5T_bit_set (d, dst->u.f.sign, (size_t)1, TRUE);
- H5T_bit_set (d, dst->u.f.epos, dst->u.f.esize, TRUE);
- H5T_bit_set (d, dst->u.f.mpos, dst->u.f.msize, FALSE);
+ d = (uint8_t *)&H5T_NATIVE_FLOAT_NEG_INF_g;
+ H5T_bit_set(d, dst->u.f.sign, (size_t)1, TRUE);
+ H5T_bit_set(d, dst->u.f.epos, dst->u.f.esize, TRUE);
+ H5T_bit_set(d, dst->u.f.mpos, dst->u.f.msize, FALSE);
/* Swap the bytes if the machine architecture is big-endian */
- if (H5T_ORDER_BE==H5T_native_order_g) {
- half_size = dst_p->shared->size/2;
- for (u=0; u<half_size; u++) {
- uint8_t tmp = d[dst_p->shared->size-(u+1)];
- d[dst_p->shared->size-(u+1)] = d[u];
+ if(H5T_ORDER_BE == H5T_native_order_g) {
+ half_size = dst_p->shared->size / 2;
+ for(u = 0; u < half_size; u++) {
+ uint8_t tmp = d[dst_p->shared->size - (u + 1)];
+ d[dst_p->shared->size - (u + 1)] = d[u];
d[u] = tmp;
- }
- }
+ } /* end for */
+ } /* end if */
/* Get the double datatype */
if (NULL==(dst_p=H5I_object(H5T_NATIVE_DOUBLE_g)))
@@ -601,40 +608,40 @@ H5T_init_inf(void)
HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported byte order");
/* +Inf */
- d=(uint8_t *)&H5T_NATIVE_DOUBLE_POS_INF_g;
- H5T_bit_set (d, dst->u.f.sign, (size_t)1, FALSE);
- H5T_bit_set (d, dst->u.f.epos, dst->u.f.esize, TRUE);
- H5T_bit_set (d, dst->u.f.mpos, dst->u.f.msize, FALSE);
+ d = (uint8_t *)&H5T_NATIVE_DOUBLE_POS_INF_g;
+ H5T_bit_set(d, dst->u.f.sign, (size_t)1, FALSE);
+ H5T_bit_set(d, dst->u.f.epos, dst->u.f.esize, TRUE);
+ H5T_bit_set(d, dst->u.f.mpos, dst->u.f.msize, FALSE);
/* Swap the bytes if the machine architecture is big-endian */
- if (H5T_ORDER_BE==H5T_native_order_g) {
- half_size = dst_p->shared->size/2;
- for (u=0; u<half_size; u++) {
- uint8_t tmp = d[dst_p->shared->size-(u+1)];
- d[dst_p->shared->size-(u+1)] = d[u];
+ if(H5T_ORDER_BE == H5T_native_order_g) {
+ half_size = dst_p->shared->size / 2;
+ for(u = 0; u < half_size; u++) {
+ uint8_t tmp = d[dst_p->shared->size - (u + 1)];
+ d[dst_p->shared->size - (u + 1)] = d[u];
d[u] = tmp;
- }
- }
+ } /* end for */
+ } /* end if */
/* -Inf */
- d=(uint8_t *)&H5T_NATIVE_DOUBLE_NEG_INF_g;
- H5T_bit_set (d, dst->u.f.sign, (size_t)1, TRUE);
- H5T_bit_set (d, dst->u.f.epos, dst->u.f.esize, TRUE);
- H5T_bit_set (d, dst->u.f.mpos, dst->u.f.msize, FALSE);
+ d = (uint8_t *)&H5T_NATIVE_DOUBLE_NEG_INF_g;
+ H5T_bit_set(d, dst->u.f.sign, (size_t)1, TRUE);
+ H5T_bit_set(d, dst->u.f.epos, dst->u.f.esize, TRUE);
+ H5T_bit_set(d, dst->u.f.mpos, dst->u.f.msize, FALSE);
/* Swap the bytes if the machine architecture is big-endian */
- if (H5T_ORDER_BE==H5T_native_order_g) {
- half_size = dst_p->shared->size/2;
- for (u=0; u<half_size; u++) {
- uint8_t tmp = d[dst_p->shared->size-(u+1)];
- d[dst_p->shared->size-(u+1)] = d[u];
+ if(H5T_ORDER_BE == H5T_native_order_g) {
+ half_size = dst_p->shared->size / 2;
+ for(u = 0; u < half_size; u++) {
+ uint8_t tmp = d[dst_p->shared->size - (u + 1)];
+ d[dst_p->shared->size - (u + 1)] = d[u];
d[u] = tmp;
- }
- }
+ } /* end for */
+ } /* end if */
done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T_init_inf() */
/*-------------------------------------------------------------------------
@@ -643,14 +650,11 @@ done:
* Purpose: Perform hardware specific [floating-point] initialization
*
* Return: Success: non-negative
- *
* Failure: negative
*
* Programmer: Quincey Koziol
* Monday, November 24, 2003
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static herr_t
@@ -659,25 +663,25 @@ H5T_init_hw(void)
#ifdef H5_HAVE_GET_FPC_CSR
union fpc_csr csr; /* Union to hold results of floating-point status register query */
#endif /* H5_HAVE_GET_FPC_CSR */
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_init_hw);
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_init_hw)
#ifdef H5_HAVE_GET_FPC_CSR
/* [This code is specific to SGI machines] */
/* Get the floating-point status register */
- csr.fc_word=get_fpc_csr();
+ csr.fc_word = get_fpc_csr();
/* If the "flush denormalized values to zero" flag is set, unset it */
if(csr.fc_struct.flush) {
- csr.fc_struct.flush=0;
+ csr.fc_struct.flush = 0;
set_fpc_csr(csr.fc_word);
} /* end if */
#endif /* H5_HAVE_GET_FPC_CSR */
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T_init_hw() */
/*--------------------------------------------------------------------------
@@ -734,7 +738,7 @@ H5T_init_interface(void)
herr_t status;
unsigned copied_dtype=1; /* Flag to indicate whether datatype was copied or allocated (for error cleanup) */
H5P_genclass_t *crt_pclass; /* Property list class for datatype creation properties */
- herr_t ret_value=SUCCEED;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5T_init_interface)
@@ -747,11 +751,11 @@ H5T_init_interface(void)
HDassert(H5T_NCLASSES < 16);
/* Perform any necessary hardware initializations */
- if(H5T_init_hw()<0)
+ if(H5T_init_hw() < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to initialize interface")
/*
- * Initialize pre-defined native data types from code generated during
+ * Initialize pre-defined native datatypes from code generated during
* the library configuration by H5detect.
*/
if(H5TN_init_interface()<0)
@@ -788,7 +792,7 @@ H5T_init_interface(void)
#endif
/*------------------------------------------------------------
- * Native types
+ * Derived native types
*------------------------------------------------------------
*/
@@ -849,7 +853,7 @@ H5T_init_interface(void)
H5T_INIT_TYPE(DOUBLEVAX,H5T_VAX_F64_g,COPY,native_double,SET,8)
/*------------------------------------------------------------
- * Other "standard" types
+ * C99 types
*------------------------------------------------------------
*/
@@ -911,34 +915,34 @@ H5T_init_interface(void)
std_u64be=dt; /* Keep type for later */
/*------------------------------------------------------------
- * Little- & Big-endian bitfields
+ * Native, Little- & Big-endian bitfields
*------------------------------------------------------------
*/
/* little-endian (order is irrelevant) 8-bit bitfield */
- H5T_INIT_TYPE(BITFIELD,H5T_STD_B8LE_g,COPY,std_u8le,NOSET,-)
+ H5T_INIT_TYPE(BITFIELD, H5T_STD_B8LE_g, COPY, std_u8le, NOSET, -)
bitfield=dt; /* Keep type for later */
/* big-endian (order is irrelevant) 8-bit bitfield */
- H5T_INIT_TYPE(BITFIELD,H5T_STD_B8BE_g,COPY,std_u8be,NOSET,-)
+ H5T_INIT_TYPE(BITFIELD, H5T_STD_B8BE_g, COPY, std_u8be, NOSET, -)
/* Little-endian 16-bit bitfield */
- H5T_INIT_TYPE(BITFIELD,H5T_STD_B16LE_g,COPY,std_u16le,NOSET,-)
+ H5T_INIT_TYPE(BITFIELD, H5T_STD_B16LE_g, COPY, std_u16le, NOSET, -)
/* Big-endian 16-bit bitfield */
- H5T_INIT_TYPE(BITFIELD,H5T_STD_B16BE_g,COPY,std_u16be,NOSET,-)
+ H5T_INIT_TYPE(BITFIELD, H5T_STD_B16BE_g, COPY, std_u16be, NOSET, -)
/* Little-endian 32-bit bitfield */
- H5T_INIT_TYPE(BITFIELD,H5T_STD_B32LE_g,COPY,std_u32le,NOSET,-)
+ H5T_INIT_TYPE(BITFIELD, H5T_STD_B32LE_g, COPY, std_u32le, NOSET, -)
/* Big-endian 32-bit bitfield */
- H5T_INIT_TYPE(BITFIELD,H5T_STD_B32BE_g,COPY,std_u32be,NOSET,-)
+ H5T_INIT_TYPE(BITFIELD, H5T_STD_B32BE_g, COPY, std_u32be, NOSET, -)
/* Little-endian 64-bit bitfield */
- H5T_INIT_TYPE(BITFIELD,H5T_STD_B64LE_g,COPY,std_u64le,NOSET,-)
+ H5T_INIT_TYPE(BITFIELD, H5T_STD_B64LE_g, COPY, std_u64le, NOSET, -)
/* Big-endian 64-bit bitfield */
- H5T_INIT_TYPE(BITFIELD,H5T_STD_B64BE_g,COPY,std_u64be,NOSET,-)
+ H5T_INIT_TYPE(BITFIELD, H5T_STD_B64BE_g, COPY, std_u64be, NOSET, -)
/*------------------------------------------------------------
* The Unix architecture for dates and times.
@@ -946,25 +950,25 @@ H5T_init_interface(void)
*/
/* Little-endian 32-bit UNIX time_t */
- H5T_INIT_TYPE(TIME,H5T_UNIX_D32LE_g,COPY,std_u32le,NOSET,-)
+ H5T_INIT_TYPE(TIME, H5T_UNIX_D32LE_g, COPY, std_u32le, NOSET, -)
/* Big-endian 32-bit UNIX time_t */
- H5T_INIT_TYPE(TIME,H5T_UNIX_D32BE_g,COPY,std_u32be,NOSET,-)
+ H5T_INIT_TYPE(TIME, H5T_UNIX_D32BE_g, COPY, std_u32be, NOSET, -)
/* Little-endian 64-bit UNIX time_t */
- H5T_INIT_TYPE(TIME,H5T_UNIX_D64LE_g,COPY,std_u64le,NOSET,-)
+ H5T_INIT_TYPE(TIME, H5T_UNIX_D64LE_g, COPY, std_u64le, NOSET, -)
/* Big-endian 64-bit UNIX time_t */
- H5T_INIT_TYPE(TIME,H5T_UNIX_D64BE_g,COPY,std_u64be,NOSET,-)
+ H5T_INIT_TYPE(TIME, H5T_UNIX_D64BE_g, COPY, std_u64be, NOSET, -)
/* Indicate that the types that are created from here down are allocated
* H5FL_ALLOC(), not copied with H5T_copy()
*/
- copied_dtype=0;
+ copied_dtype = FALSE;
/* Opaque data */
- H5T_INIT_TYPE(OPAQ,H5T_NATIVE_OPAQUE_g,ALLOC,-,SET,1)
+ H5T_INIT_TYPE(OPAQ, H5T_NATIVE_OPAQUE_g, ALLOC, -, SET, 1)
/*------------------------------------------------------------
* The `C' architecture
@@ -972,7 +976,7 @@ H5T_init_interface(void)
*/
/* One-byte character string */
- H5T_INIT_TYPE(CSTRING,H5T_C_S1_g,ALLOC,-,SET,1)
+ H5T_INIT_TYPE(CSTRING, H5T_C_S1_g, ALLOC, -, SET, 1)
string=dt; /* Keep type for later */
/*------------------------------------------------------------
@@ -981,19 +985,19 @@ H5T_init_interface(void)
*/
/* One-byte character string */
- H5T_INIT_TYPE(FORSTRING,H5T_FORTRAN_S1_g,ALLOC,-,SET,1)
+ H5T_INIT_TYPE(FORSTRING, H5T_FORTRAN_S1_g, ALLOC, -, SET, 1)
/*------------------------------------------------------------
- * Pointer types
+ * Reference types
*------------------------------------------------------------
*/
- /* Object pointer (i.e. object header address in file) */
- H5T_INIT_TYPE(OBJREF,H5T_STD_REF_OBJ_g,ALLOC,-,SET,H5R_OBJ_REF_BUF_SIZE)
+ /* Object reference (i.e. object header address in file) */
+ H5T_INIT_TYPE(OBJREF, H5T_STD_REF_OBJ_g, ALLOC, -, SET, H5R_OBJ_REF_BUF_SIZE)
objref=dt; /* Keep type for later */
- /* Dataset Region pointer (i.e. selection inside a dataset) */
- H5T_INIT_TYPE(REGREF,H5T_STD_REF_DSETREG_g,ALLOC,-,SET,H5R_DSET_REG_REF_BUF_SIZE)
+ /* Dataset Region reference (i.e. selection inside a dataset) */
+ H5T_INIT_TYPE(REGREF, H5T_STD_REF_DSETREG_g, ALLOC, -, SET, H5R_DSET_REG_REF_BUF_SIZE)
/*
* Register conversion functions beginning with the most general and
@@ -1312,7 +1316,7 @@ H5T_init_interface(void)
assert(H5P_CLS_DATATYPE_CREATE_g!=-1);
/* Get the pointer to group creation class */
- if(NULL == (crt_pclass = H5I_object(H5P_CLS_DATATYPE_CREATE_g)))
+ if(NULL == (crt_pclass = (H5P_genclass_t *)H5I_object(H5P_CLS_DATATYPE_CREATE_g)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list class")
/* Register datatype creation property class properties here. See similar
@@ -1320,9 +1324,9 @@ H5T_init_interface(void)
*/
/* Only register the default property list if it hasn't been created yet */
- if(H5P_LST_DATATYPE_CREATE_g==(-1)) {
+ if(H5P_LST_DATATYPE_CREATE_g == (-1)) {
/* Register the default datatype creation property list */
- if((H5P_LST_DATATYPE_CREATE_g = H5P_create_id(crt_pclass))<0)
+ if((H5P_LST_DATATYPE_CREATE_g = H5P_create_id(crt_pclass, FALSE)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "can't insert property into class")
} /* end if */
@@ -1338,16 +1342,15 @@ done:
H5T_close(array);
/* Error cleanup */
- if(ret_value<0) {
- if(dt!=NULL) {
+ if(ret_value < 0) {
+ if(dt) {
/* Check if we should call H5T_close or H5FL_FREE */
if(copied_dtype)
H5T_close(dt);
- else
- {
- H5FL_FREE(H5T_shared_t, dt->shared);
- H5FL_FREE(H5T_t,dt);
- }
+ else {
+ (void)H5FL_FREE(H5T_shared_t, dt->shared);
+ (void)H5FL_FREE(H5T_t,dt);
+ } /* end else */
} /* end if */
} /* end if */
@@ -1358,32 +1361,30 @@ done:
/*-------------------------------------------------------------------------
* Function: H5T_unlock_cb
*
- * Purpose: Clear the immutable flag for a data type. This function is
+ * Purpose: Clear the immutable flag for a datatype. This function is
* called when the library is closing in order to unlock all
- * registered data types and thus make them free-able.
+ * registered datatypes and thus make them free-able.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Robb Matzke
* Monday, April 27, 1998
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static int
-H5T_unlock_cb (void *_dt, hid_t UNUSED id, void UNUSED *key)
+H5T_unlock_cb(void *_dt, hid_t UNUSED id, void UNUSED *key)
{
H5T_t *dt = (H5T_t *)_dt;
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_unlock_cb);
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_unlock_cb)
HDassert (dt && dt->shared);
if (H5T_STATE_IMMUTABLE==dt->shared->state)
dt->shared->state = H5T_STATE_RDONLY;
- FUNC_LEAVE_NOAPI(SUCCEED);
-}
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5T_unlock_cb() */
/*-------------------------------------------------------------------------
@@ -1400,10 +1401,6 @@ H5T_unlock_cb (void *_dt, hid_t UNUSED id, void UNUSED *key)
* Programmer: Robb Matzke
* Friday, November 20, 1998
*
- * Modifications:
- * Robb Matzke, 1998-06-11
- * Statistics are only printed for conversion functions that were
- * called.
*-------------------------------------------------------------------------
*/
int
@@ -1412,7 +1409,7 @@ H5T_term_interface(void)
int i, nprint=0, n=0;
H5T_path_t *path = NULL;
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_term_interface);
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_term_interface)
if (H5_interface_initialize_g) {
/* Unregister all conversion functions */
@@ -1452,7 +1449,7 @@ H5T_term_interface(void)
H5T_g.nsoft = H5T_g.asoft = 0;
/* Unlock all datatypes, then free them */
- H5I_search (H5I_DATATYPE, H5T_unlock_cb, NULL);
+ H5I_search (H5I_DATATYPE, H5T_unlock_cb, NULL, FALSE);
H5I_dec_type_ref(H5I_DATATYPE);
/* Reset all the datatype IDs */
@@ -1554,9 +1551,10 @@ H5T_term_interface(void)
/* Mark interface as closed */
H5_interface_initialize_g = 0;
n = 1; /*H5I*/
- }
- FUNC_LEAVE_NOAPI(n);
-}
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(n)
+} /* end H5T_term_interface() */
/*-------------------------------------------------------------------------
@@ -1572,7 +1570,7 @@ H5T_term_interface(void)
* Errors:
* ARGS BADVALUE Invalid size.
* DATATYPE CANTINIT Can't create type.
- * DATATYPE CANTREGISTER Can't register data type atom.
+ * DATATYPE CANTREGISTER Can't register datatype atom.
*
* Programmer: Robb Matzke
* Friday, December 5, 1997
@@ -1584,37 +1582,37 @@ H5T_term_interface(void)
hid_t
H5Tcreate(H5T_class_t type, size_t size)
{
- H5T_t *dt = NULL;
- hid_t ret_value;
+ H5T_t *dt = NULL; /* New datatype constructed */
+ hid_t ret_value; /* Return value */
- FUNC_ENTER_API(H5Tcreate, FAIL);
+ FUNC_ENTER_API(H5Tcreate, FAIL)
H5TRACE2("i", "Ttz", type, size);
/* check args */
- if (size == 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid size");
+ if(size == 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid size")
/* create the type */
- if (NULL == (dt = H5T_create(type, size)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to create type");
+ if(NULL == (dt = H5T_create(type, size)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to create type")
- /* Make it an atom */
- if ((ret_value = H5I_register(H5I_DATATYPE, dt)) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register data type atom");
+ /* Get an ID for the datatype */
+ if((ret_value = H5I_register(H5I_DATATYPE, dt, TRUE)) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register datatype ID")
done:
- FUNC_LEAVE_API(ret_value);
-}
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Tcreate() */
/*-------------------------------------------------------------------------
* Function: H5Tcopy
*
- * Purpose: Copies a data type. The resulting data type is not locked.
- * The data type should be closed when no longer needed by
+ * Purpose: Copies a datatype. The resulting datatype is not locked.
+ * The datatype should be closed when no longer needed by
* calling H5Tclose().
*
- * Return: Success: The ID of a new data type.
+ * Return: Success: The ID of a new datatype.
*
* Failure: Negative
*
@@ -1625,64 +1623,66 @@ done:
*
* Robb Matzke, 4 Jun 1998
* The returned type is always transient and unlocked. If the TYPE_ID
- * argument is a dataset instead of a data type then this function
- * returns a transient, modifiable data type which is a copy of the
- * dataset's data type.
+ * argument is a dataset instead of a datatype then this function
+ * returns a transient, modifiable datatype which is a copy of the
+ * dataset's datatype.
*
*-------------------------------------------------------------------------
*/
hid_t
H5Tcopy(hid_t type_id)
{
- H5T_t *dt = NULL;
+ H5T_t *dt; /* Pointer to the datatype to copy */
H5T_t *new_dt = NULL;
- H5D_t *dset = NULL;
- hid_t ret_value;
+ hid_t ret_value; /* Return value */
- FUNC_ENTER_API(H5Tcopy, FAIL);
+ FUNC_ENTER_API(H5Tcopy, FAIL)
H5TRACE1("i", "i", type_id);
- switch (H5I_get_type (type_id)) {
+ switch(H5I_get_type(type_id)) {
case H5I_DATATYPE:
- /* The argument is a data type handle */
- if (NULL==(dt=H5I_object (type_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
+ /* The argument is a datatype handle */
+ if(NULL == (dt = (H5T_t *)H5I_object(type_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
break;
case H5I_DATASET:
- /* The argument is a dataset handle */
- if (NULL==(dset=H5I_object (type_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset");
- if (NULL==(dt=H5D_typeof (dset)))
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to get the dataset data type");
+ {
+ H5D_t *dset; /* Dataset for datatype */
+
+ /* The argument is a dataset handle */
+ if(NULL == (dset = (H5D_t *)H5I_object(type_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
+ if(NULL == (dt = H5D_typeof(dset)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to get the dataset datatype")
+ }
break;
default:
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type or dataset");
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype or dataset")
} /* end switch */
- /* Copy */
- if (NULL == (new_dt = H5T_copy(dt, H5T_COPY_TRANSIENT)))
+ /* Copy datatype */
+ if(NULL == (new_dt = H5T_copy(dt, H5T_COPY_TRANSIENT)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy");
/* Atomize result */
- if ((ret_value = H5I_register(H5I_DATATYPE, new_dt)) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register data type atom");
+ if((ret_value = H5I_register(H5I_DATATYPE, new_dt, TRUE)) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register datatype atom")
done:
- if(ret_value<0) {
- if(new_dt!=NULL)
- H5T_close(new_dt);
- } /* end if */
+ if(ret_value < 0)
+ if(new_dt && H5T_close(new_dt) < 0)
+ HDONE_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "unable to release datatype info")
- FUNC_LEAVE_API(ret_value);
+ FUNC_LEAVE_API(ret_value)
} /* end H5Tcopy() */
/*-------------------------------------------------------------------------
* Function: H5Tclose
*
- * Purpose: Frees a data type and all associated memory.
+ * Purpose: Frees a datatype and all associated memory.
*
* Return: Non-negative on success/Negative on failure
*
@@ -1696,76 +1696,73 @@ done:
herr_t
H5Tclose(hid_t type_id)
{
- H5T_t *dt = NULL;
- herr_t ret_value=SUCCEED; /* Return value */
+ H5T_t *dt; /* Pointer to datatype to close */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_API(H5Tclose, FAIL);
+ FUNC_ENTER_API(H5Tclose, FAIL)
H5TRACE1("e", "i", type_id);
/* Check args */
- if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
- if (H5T_STATE_IMMUTABLE==dt->shared->state)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "immutable data type");
+ if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
+ if(H5T_STATE_IMMUTABLE==dt->shared->state)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "immutable datatype")
/* When the reference count reaches zero the resources are freed */
- if (H5I_dec_ref(type_id) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "problem freeing id");
+ if(H5I_dec_ref(type_id, TRUE) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "problem freeing id")
done:
- FUNC_LEAVE_API(ret_value);
-}
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Tclose() */
/*-------------------------------------------------------------------------
* Function: H5Tequal
*
- * Purpose: Determines if two data types are equal.
+ * Purpose: Determines if two datatypes are equal.
*
* Return: Success: TRUE if equal, FALSE if unequal
*
* Failure: Negative
*
- * Errors:
- *
* Programmer: Robb Matzke
* Wednesday, December 10, 1997
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
htri_t
H5Tequal(hid_t type1_id, hid_t type2_id)
{
- const H5T_t *dt1 = NULL;
- const H5T_t *dt2 = NULL;
- htri_t ret_value;
+ const H5T_t *dt1; /* Pointer to first datatype */
+ const H5T_t *dt2; /* Pointer to second datatype */
+ htri_t ret_value; /* Return value */
- FUNC_ENTER_API(H5Tequal, FAIL);
+ FUNC_ENTER_API(H5Tequal, FAIL)
H5TRACE2("t", "ii", type1_id, type2_id);
/* check args */
- if (NULL == (dt1 = H5I_object_verify(type1_id,H5I_DATATYPE)) ||
- NULL == (dt2 = H5I_object_verify(type2_id,H5I_DATATYPE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
+ if(NULL == (dt1 = (H5T_t *)H5I_object_verify(type1_id, H5I_DATATYPE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
+ if(NULL == (dt2 = (H5T_t *)H5I_object_verify(type2_id, H5I_DATATYPE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
ret_value = (0 == H5T_cmp(dt1, dt2, FALSE)) ? TRUE : FALSE;
done:
- FUNC_LEAVE_API(ret_value);
-}
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Tequal() */
/*-------------------------------------------------------------------------
* Function: H5Tlock
*
* Purpose: Locks a type, making it read only and non-destructable. This
- * is normally done by the library for predefined data types so
+ * is normally done by the library for predefined datatypes so
* the application doesn't inadvertently change or delete a
* predefined type.
*
- * Once a data type is locked it can never be unlocked unless
+ * Once a datatype is locked it can never be unlocked unless
* the entire library is closed.
*
* Return: Non-negative on success/Negative on failure
@@ -1776,7 +1773,7 @@ done:
* Modifications:
*
* Robb Matzke, 1 Jun 1998
- * It is illegal to lock a named data type since we must allow named
+ * It is illegal to lock a named datatype since we must allow named
* types to be closed (to release file resources) but locking a type
* prevents that.
*-------------------------------------------------------------------------
@@ -1784,32 +1781,32 @@ done:
herr_t
H5Tlock(hid_t type_id)
{
- H5T_t *dt = NULL;
- herr_t ret_value=SUCCEED; /* Return value */
+ H5T_t *dt; /* Datatype to operate on */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_API(H5Tlock, FAIL);
+ FUNC_ENTER_API(H5Tlock, FAIL)
H5TRACE1("e", "i", type_id);
/* Check args */
- if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
- if (H5T_STATE_NAMED==dt->shared->state || H5T_STATE_OPEN==dt->shared->state)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to lock named data type");
+ if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id,H5I_DATATYPE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
+ if(H5T_STATE_NAMED==dt->shared->state || H5T_STATE_OPEN==dt->shared->state)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to lock named datatype")
- if (H5T_lock (dt, TRUE)<0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to lock transient data type");
+ if(H5T_lock(dt, TRUE) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to lock transient datatype")
done:
- FUNC_LEAVE_API(ret_value);
-}
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Tlock() */
/*-------------------------------------------------------------------------
* Function: H5Tget_class
*
- * Purpose: Returns the data type class identifier for data type TYPE_ID.
+ * Purpose: Returns the datatype class identifier for datatype TYPE_ID.
*
- * Return: Success: One of the non-negative data type class
+ * Return: Success: One of the non-negative datatype class
* constants.
*
* Failure: H5T_NO_CLASS (Negative)
@@ -1817,29 +1814,27 @@ done:
* Programmer: Robb Matzke
* Monday, December 8, 1997
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
H5T_class_t
H5Tget_class(hid_t type_id)
{
- H5T_t *dt = NULL;
- H5T_class_t ret_value; /* Return value */
+ H5T_t *dt; /* Pointer to datatype */
+ H5T_class_t ret_value; /* Return value */
- FUNC_ENTER_API(H5Tget_class, H5T_NO_CLASS);
+ FUNC_ENTER_API(H5Tget_class, H5T_NO_CLASS)
H5TRACE1("Tt", "i", type_id);
/* Check args */
- if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a data type");
+ if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a datatype")
/* Set return value */
- ret_value= H5T_get_class(dt, FALSE);
+ ret_value = H5T_get_class(dt, FALSE);
done:
- FUNC_LEAVE_API(ret_value);
-}
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Tget_class() */
/*-------------------------------------------------------------------------
@@ -1908,28 +1903,28 @@ done:
htri_t
H5Tdetect_class(hid_t type, H5T_class_t cls)
{
- H5T_t *dt = NULL;
+ H5T_t *dt; /* Datatype to query */
htri_t ret_value; /* Return value */
- FUNC_ENTER_API(H5Tdetect_class, FAIL);
+ FUNC_ENTER_API(H5Tdetect_class, FAIL)
H5TRACE2("t", "iTt", type, cls);
/* Check args */
- if (NULL == (dt = H5I_object_verify(type,H5I_DATATYPE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a data type");
- if (!(cls>H5T_NO_CLASS && cls<H5T_NCLASSES))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a data type class");
+ if(NULL == (dt = (H5T_t *)H5I_object_verify(type,H5I_DATATYPE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a datatype")
+ if(!(cls > H5T_NO_CLASS && cls < H5T_NCLASSES))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a datatype class")
/* Set return value. Consider VL string as a string for API, as a VL for
* internal use. */
if(H5T_IS_VL_STRING(dt->shared))
- ret_value = (H5T_STRING==cls);
+ ret_value = (H5T_STRING == cls);
else
- ret_value=H5T_detect_class(dt,cls);
+ ret_value = H5T_detect_class(dt, cls);
done:
- FUNC_LEAVE_API(ret_value);
-}
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Tdetect_class() */
/*-------------------------------------------------------------------------
@@ -2015,12 +2010,12 @@ H5Tis_variable_str(hid_t dtype_id)
H5TRACE1("t", "i", dtype_id);
/* Check args */
- if(NULL == (dt = H5I_object_verify(dtype_id, H5I_DATATYPE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
+ if(NULL == (dt = (H5T_t *)H5I_object_verify(dtype_id, H5I_DATATYPE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
/* Set return value */
if((ret_value = H5T_is_variable_str(dt)) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "can't determine if datatype is VL-string");
+ HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "can't determine if datatype is VL-string")
done:
FUNC_LEAVE_API(ret_value);
@@ -2062,28 +2057,26 @@ H5T_is_variable_str(const H5T_t *dt)
* Programmer: Robb Matzke
* Monday, December 8, 1997
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
size_t
H5Tget_size(hid_t type_id)
{
- H5T_t *dt = NULL;
- size_t ret_value;
+ H5T_t *dt; /* Datatype to query */
+ size_t ret_value; /* Return value */
- FUNC_ENTER_API(H5Tget_size, 0);
+ FUNC_ENTER_API(H5Tget_size, 0)
H5TRACE1("z", "i", type_id);
/* Check args */
- if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a datatype");
+ if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a datatype")
/* size */
- ret_value = H5T_get_size(dt);
+ ret_value = H5T_GET_SIZE(dt);
done:
- FUNC_LEAVE_API(ret_value);
+ FUNC_LEAVE_API(ret_value)
} /* end H5Tget_size() */
@@ -2102,51 +2095,47 @@ done:
* Adjusting the size of an H5T_STRING automatically sets the
* precision to 8*size.
*
- * All data types have a positive size.
+ * All datatypes have a positive size.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Robb Matzke
* Wednesday, January 7, 1998
*
- * Modifications:
- * Robb Matzke, 22 Dec 1998
- * Moved the real work into a private function.
- *
*-------------------------------------------------------------------------
*/
herr_t
H5Tset_size(hid_t type_id, size_t size)
{
- H5T_t *dt = NULL;
- herr_t ret_value=SUCCEED; /* Return value */
+ H5T_t *dt; /* Datatype to modify */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_API(H5Tset_size, FAIL);
+ FUNC_ENTER_API(H5Tset_size, FAIL)
H5TRACE2("e", "iz", type_id, size);
/* Check args */
- if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
- if (H5T_STATE_TRANSIENT!=dt->shared->state)
- HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only");
- if (size <= 0 && size!=H5T_VARIABLE)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "size must be positive");
- if (size == H5T_VARIABLE && dt->shared->type!=H5T_STRING)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "only strings may be variable length");
- if (H5T_ENUM==dt->shared->type && dt->shared->u.enumer.nmembs>0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not allowed after members are defined");
- if (H5T_REFERENCE==dt->shared->type)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for this datatype");
- if (size==0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "can't adjust size to 0");
-
- /* Do the work */
- if (H5T_set_size(dt, size)<0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to set size for data type");
+ if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
+ if(H5T_STATE_TRANSIENT!=dt->shared->state)
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "datatype is read-only")
+ if(size <= 0 && size != H5T_VARIABLE)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "size must be positive")
+ if(size == H5T_VARIABLE && dt->shared->type != H5T_STRING)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "only strings may be variable length")
+ if(H5T_ENUM == dt->shared->type && dt->shared->u.enumer.nmembs > 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not allowed after members are defined")
+ if(H5T_REFERENCE == dt->shared->type)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for this datatype")
+ if(size == 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "can't adjust size to 0")
+
+ /* Modify the datatype */
+ if(H5T_set_size(dt, size) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to set size for datatype")
done:
- FUNC_LEAVE_API(ret_value);
-}
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Tset_size() */
/*-------------------------------------------------------------------------
@@ -2155,7 +2144,7 @@ done:
* Purpose: Returns the type from which TYPE is derived. In the case of
* an enumeration type the return value is an integer type.
*
- * Return: Success: Type ID for base data type.
+ * Return: Success: Type ID for base datatype.
*
* Failure: negative
*
@@ -2169,27 +2158,27 @@ done:
hid_t
H5Tget_super(hid_t type)
{
- H5T_t *dt=NULL, *super=NULL;
- hid_t ret_value;
+ H5T_t *dt; /* Datatype to query */
+ H5T_t *super = NULL; /* Supertype */
+ hid_t ret_value; /* Return value */
- FUNC_ENTER_API(H5Tget_super, FAIL);
+ FUNC_ENTER_API(H5Tget_super, FAIL)
H5TRACE1("i", "i", type);
- if (NULL==(dt=H5I_object_verify(type,H5I_DATATYPE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
- if((super=H5T_get_super(dt))==NULL)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "not a data type");
- if ((ret_value=H5I_register(H5I_DATATYPE, super))<0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register parent data type");
+ if(NULL == (dt = (H5T_t *)H5I_object_verify(type,H5I_DATATYPE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
+ if(NULL == (super = H5T_get_super(dt)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "not a datatype")
+ if((ret_value = H5I_register(H5I_DATATYPE, super, TRUE)) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register parent datatype")
done:
- if(ret_value<0) {
- if(super!=NULL)
- H5T_close(super);
- } /* end if */
+ if(ret_value < 0)
+ if(super && H5T_close(super) < 0)
+ HDONE_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "unable to release super datatype info")
- FUNC_LEAVE_API(ret_value);
-}
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Tget_super() */
/*-------------------------------------------------------------------------
@@ -2323,15 +2312,15 @@ H5T_register(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst,
old_path->dst->shared->type!=dst->shared->type) {
continue;
}
- if ((tmp_sid = H5I_register(H5I_DATATYPE, H5T_copy(old_path->src, H5T_COPY_ALL)))<0 ||
- (tmp_did = H5I_register(H5I_DATATYPE, H5T_copy(old_path->dst, H5T_COPY_ALL)))<0)
+ if ((tmp_sid = H5I_register(H5I_DATATYPE, H5T_copy(old_path->src, H5T_COPY_ALL), FALSE))<0 ||
+ (tmp_did = H5I_register(H5I_DATATYPE, H5T_copy(old_path->dst, H5T_COPY_ALL), FALSE))<0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register data types for conv query");
HDmemset(&cdata, 0, sizeof cdata);
cdata.command = H5T_CONV_INIT;
if ((func)(tmp_sid, tmp_did, &cdata, (size_t)0, (size_t)0, (size_t)0,
NULL, NULL, dxpl_id)<0) {
- H5I_dec_ref(tmp_sid);
- H5I_dec_ref(tmp_did);
+ H5I_dec_ref(tmp_sid, FALSE);
+ H5I_dec_ref(tmp_did, FALSE);
tmp_sid = tmp_did = -1;
H5E_clear_stack(NULL);
continue;
@@ -2371,8 +2360,8 @@ H5T_register(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst,
H5FL_FREE(H5T_path_t,old_path);
/* Release temporary atoms */
- H5I_dec_ref(tmp_sid);
- H5I_dec_ref(tmp_did);
+ H5I_dec_ref(tmp_sid, FALSE);
+ H5I_dec_ref(tmp_did, FALSE);
tmp_sid = tmp_did = -1;
/* We don't care about any failures during the freeing process */
@@ -2390,9 +2379,9 @@ done:
H5FL_FREE(H5T_path_t,new_path);
} /* end if */
if (tmp_sid>=0)
- H5I_dec_ref(tmp_sid);
+ H5I_dec_ref(tmp_sid, FALSE);
if (tmp_did>=0)
- H5I_dec_ref(tmp_did);
+ H5I_dec_ref(tmp_did, FALSE);
} /* end if */
FUNC_LEAVE_NOAPI(ret_value);
@@ -2824,7 +2813,7 @@ H5Tdecode(const void *buf)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "can't decode object")
/* Register the type and return the ID */
- if((ret_value = H5I_register(H5I_DATATYPE, dt)) < 0)
+ if((ret_value = H5I_register(H5I_DATATYPE, dt, FALSE)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register data type")
done:
@@ -3080,7 +3069,7 @@ H5T_t *
H5T_copy(const H5T_t *old_dt, H5T_copy_t method)
{
H5T_t *new_dt = NULL, *tmp = NULL;
- H5T_shared_t *reopened_fo;
+ H5T_shared_t *reopened_fo = NULL;
unsigned i;
char *s;
H5T_t *ret_value;
@@ -3099,10 +3088,6 @@ H5T_copy(const H5T_t *old_dt, H5T_copy_t method)
/* Copy shared information (entry information is copied last) */
*(new_dt->shared) = *(old_dt->shared);
- /* Copy parent information */
- if(new_dt->shared->parent)
- new_dt->shared->parent = H5T_copy(new_dt->shared->parent, method);
-
/* Check what sort of copy we are making */
switch (method) {
case H5T_COPY_TRANSIENT:
@@ -3130,7 +3115,7 @@ H5T_copy(const H5T_t *old_dt, H5T_copy_t method)
*/
if(old_dt->sh_loc.type == H5O_SHARE_TYPE_COMMITTED) {
/* Check if the object is already open */
- if((reopened_fo = H5FO_opened(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr)) == NULL) {
+ if(NULL == (reopened_fo = H5FO_opened(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr))) {
/* Clear any errors from H5FO_opened() */
H5E_clear_stack(NULL);
@@ -3174,6 +3159,10 @@ H5T_copy(const H5T_t *old_dt, H5T_copy_t method)
break;
} /* end switch */
+ /* Copy parent information, if we aren't sharing an already opened committed datatype */
+ if(NULL == reopened_fo && old_dt->shared->parent)
+ new_dt->shared->parent = H5T_copy(old_dt->shared->parent, method);
+
switch(new_dt->shared->type) {
case H5T_COMPOUND:
{
@@ -3537,7 +3526,8 @@ H5T_close(H5T_t *dt)
HDassert(dt && dt->shared);
- dt->shared->fo_count--;
+ if(dt->shared->state == H5T_STATE_OPEN)
+ dt->shared->fo_count--;
if(dt->shared->state != H5T_STATE_OPEN || dt->shared->fo_count == 0) {
if(H5T_free(dt) < 0)
@@ -4359,17 +4349,17 @@ H5T_path_find(const H5T_t *src, const H5T_t *dst, const char *name,
assert(path!=table);
assert(NULL==path->func);
if (path->src && (src_id=H5I_register(H5I_DATATYPE,
- H5T_copy(path->src, H5T_COPY_ALL)))<0)
+ H5T_copy(path->src, H5T_COPY_ALL), FALSE))<0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, "unable to register source conversion type for query");
if (path->dst && (dst_id=H5I_register(H5I_DATATYPE,
- H5T_copy(path->dst, H5T_COPY_ALL)))<0)
+ H5T_copy(path->dst, H5T_COPY_ALL), FALSE))<0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, "unable to register destination conversion type for query");
path->cdata.command = H5T_CONV_INIT;
if ((func)(src_id, dst_id, &(path->cdata), (size_t)0, (size_t)0, (size_t)0,
NULL, NULL, dxpl_id)<0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to initialize conversion function");
- if (src_id>=0) H5I_dec_ref(src_id);
- if (dst_id>=0) H5I_dec_ref(dst_id);
+ if (src_id>=0) H5I_dec_ref(src_id, FALSE);
+ if (dst_id>=0) H5I_dec_ref(dst_id, FALSE);
src_id = dst_id = -1;
path->func = func;
path->is_hard = TRUE;
@@ -4388,9 +4378,9 @@ H5T_path_find(const H5T_t *src, const H5T_t *dst, const char *name,
continue;
}
if ((src_id=H5I_register(H5I_DATATYPE,
- H5T_copy(path->src, H5T_COPY_ALL)))<0 ||
+ H5T_copy(path->src, H5T_COPY_ALL), FALSE))<0 ||
(dst_id=H5I_register(H5I_DATATYPE,
- H5T_copy(path->dst, H5T_COPY_ALL)))<0)
+ H5T_copy(path->dst, H5T_COPY_ALL), FALSE))<0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, "unable to register conversion types for query");
path->cdata.command = H5T_CONV_INIT;
if ((H5T_g.soft[i].func) (src_id, dst_id, &(path->cdata),
@@ -4402,8 +4392,8 @@ H5T_path_find(const H5T_t *src, const H5T_t *dst, const char *name,
path->func = H5T_g.soft[i].func;
path->is_hard = FALSE;
}
- H5I_dec_ref(src_id);
- H5I_dec_ref(dst_id);
+ H5I_dec_ref(src_id, FALSE);
+ H5I_dec_ref(dst_id, FALSE);
src_id = dst_id = -1;
}
if (!path->func)
@@ -4473,7 +4463,7 @@ H5T_path_find(const H5T_t *src, const H5T_t *dst, const char *name,
}
/* Set the flag to indicate both source and destination types are compound types
- * for the optimization of data reading (in H5Dio.c). */
+ * for the optimization of data reading (in H5Dio.c). */
if(H5T_COMPOUND==H5T_get_class(src, TRUE) && H5T_COMPOUND==H5T_get_class(dst, TRUE))
path->are_compounds = TRUE;
@@ -4486,8 +4476,8 @@ done:
if (path->dst) H5T_close(path->dst);
H5FL_FREE(H5T_path_t,path);
}
- if (src_id>=0) H5I_dec_ref(src_id);
- if (dst_id>=0) H5I_dec_ref(dst_id);
+ if (src_id>=0) H5I_dec_ref(src_id, FALSE);
+ if (dst_id>=0) H5I_dec_ref(dst_id, FALSE);
FUNC_LEAVE_NOAPI(ret_value);
}
@@ -4525,8 +4515,8 @@ H5T_path_noop(const H5T_path_t *p)
* Function: H5T_path_compound_subset
*
* Purpose: Checks if the source and destination types are both compound.
- * Tells whether whether the source members are a subset of
- * destination, and the order is the same, and no conversion
+ * Tells whether whether the source members are a subset of
+ * destination, and the order is the same, and no conversion
* is needed. For example:
* struct source { struct destination {
* TYPE1 A; --> TYPE1 A;
@@ -4536,23 +4526,27 @@ H5T_path_noop(const H5T_path_t *p)
* TYPE5 E;
* };
*
- * Return: One of the values of H5T_subset_t (can't fail).
+ * Return: A pointer to the subset info struct in p, or NULL if there are
+ * no compounds. Points directly into the H5T_path_t structure.
*
* Programmer: Raymond Lu
* 8 June 2007
*
- * Modifications:
+ * Modifications: Neil Fortner
+ * 19 September 2008
+ * Changed return value to H5T_subset_info_t
+ * (to allow it to return copy_size)
*
*-------------------------------------------------------------------------
*/
-H5T_subset_t
+H5T_subset_info_t *
H5T_path_compound_subset(const H5T_path_t *p)
{
- H5T_subset_t ret_value = FALSE;
+ H5T_subset_info_t *ret_value = NULL;
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_path_compound_subset);
- assert(p);
+ HDassert(p);
if(p->are_compounds)
ret_value = H5T_conv_struct_subset(&(p->cdata));
@@ -5149,6 +5143,11 @@ H5T_upgrade_version_cb(H5T_t *dt, void *op_value)
dt->shared->version = *(unsigned *)op_value;
break;
+ case H5T_VLEN:
+ if(dt->shared->parent->shared->version > dt->shared->version)
+ dt->shared->version = dt->shared->parent->shared->version;
+ break;
+
default:
break;
} /* end switch */
diff --git a/src/H5TS.c b/src/H5TS.c
index e311c29..5d38487 100644
--- a/src/H5TS.c
+++ b/src/H5TS.c
@@ -96,10 +96,6 @@ H5TS_first_thread_init(void)
{
H5_g.H5_libinit_g = FALSE;
- /* set the owner objects to initial values */
- H5_g.init_lock.owner_thread = pthread_self();
- H5_g.init_lock.owner_valid = FALSE;
-
/* initialize global API mutex lock */
pthread_mutex_init(&H5_g.init_lock.atomic_lock, NULL);
pthread_cond_init(&H5_g.init_lock.cond_var, NULL);
@@ -150,26 +146,17 @@ H5TS_mutex_lock(H5TS_mutex_t *mutex)
if (ret_value)
return ret_value;
- if (mutex->owner_valid && pthread_equal(pthread_self(), mutex->owner_thread)) {
+ if(mutex->lock_count && pthread_equal(HDpthread_self(), mutex->owner_thread)) {
/* already owned by self - increment count */
mutex->lock_count++;
- } else if (!mutex->owner_valid) {
- /* no one else has locked it - set owner and grab lock */
- mutex->owner_thread = pthread_self();
- mutex->owner_valid = TRUE;
- mutex->lock_count = 1;
} else {
- /* if already locked by someone else */
- for (;;) {
- pthread_cond_wait(&mutex->cond_var, &mutex->atomic_lock);
-
- if (!mutex->owner_valid) {
- mutex->owner_thread = pthread_self();
- mutex->owner_valid = TRUE;
- mutex->lock_count = 1;
- break;
- }
- }
+ /* if owned by other thread, wait for condition signal */
+ while(mutex->lock_count)
+ pthread_cond_wait(&mutex->cond_var, &mutex->atomic_lock);
+
+ /* After we've received the signal, take ownership of the mutex */
+ mutex->owner_thread = HDpthread_self();
+ mutex->lock_count = 1;
}
return pthread_mutex_unlock(&mutex->atomic_lock);
@@ -204,26 +191,26 @@ H5TS_mutex_lock(H5TS_mutex_t *mutex)
herr_t
H5TS_mutex_unlock(H5TS_mutex_t *mutex)
{
- herr_t ret_value;
+ herr_t ret_value; /* Return value */
ret_value = pthread_mutex_lock(&mutex->atomic_lock);
- if (ret_value)
- return ret_value;
+ if(ret_value)
+ return ret_value;
mutex->lock_count--;
- if (mutex->lock_count == 0) {
- mutex->owner_valid = FALSE;
- ret_value = pthread_cond_signal(&mutex->cond_var);
+ ret_value = pthread_mutex_unlock(&mutex->atomic_lock);
- if (ret_value) {
- pthread_mutex_unlock(&mutex->atomic_lock);
- return ret_value;
- }
- }
+ if(mutex->lock_count == 0) {
+ int err;
- return pthread_mutex_unlock(&mutex->atomic_lock);
+ err = pthread_cond_signal(&mutex->cond_var);
+ if(err != 0)
+ ret_value = err;
+ } /* end if */
+
+ return ret_value;
}
/*--------------------------------------------------------------------------
diff --git a/src/H5TSprivate.h b/src/H5TSprivate.h
index f817120..0d0b620 100644
--- a/src/H5TSprivate.h
+++ b/src/H5TSprivate.h
@@ -37,7 +37,6 @@
typedef struct H5TS_mutex_struct {
pthread_t owner_thread; /* current lock owner */
- unsigned owner_valid; /* if current lock owner info is valid */
pthread_mutex_t atomic_lock; /* lock for atomicity of new mechanism */
pthread_cond_t cond_var; /* condition variable */
unsigned int lock_count;
diff --git a/src/H5Tarray.c b/src/H5Tarray.c
index 00f1177..f7cddb9 100644
--- a/src/H5Tarray.c
+++ b/src/H5Tarray.c
@@ -18,17 +18,65 @@
* the H5T interface.
*/
+/****************/
+/* Module Setup */
+/****************/
+
#define H5T_PACKAGE /*suppress error about including H5Tpkg */
/* Interface initialization */
#define H5_INTERFACE_INIT_FUNC H5T_init_array_interface
+/***********/
+/* Headers */
+/***********/
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
#include "H5Iprivate.h" /* IDs */
#include "H5Tpkg.h" /* Datatypes */
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Public Variables */
+/*********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
/*--------------------------------------------------------------------------
NAME
@@ -46,16 +94,16 @@ DESCRIPTION
static herr_t
H5T_init_array_interface(void)
{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_init_array_interface);
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_init_array_interface)
- FUNC_LEAVE_NOAPI(H5T_init());
+ FUNC_LEAVE_NOAPI(H5T_init())
} /* H5T_init_array_interface() */
/*-------------------------------------------------------------------------
* Function: H5Tarray_create2
*
- * Purpose: Create a new array data type based on the specified BASE_TYPE.
+ * Purpose: Create a new array datatype based on the specified BASE_TYPE.
* The type is an array with NDIMS dimensionality and the size of the
* array is DIMS. The total member size should be relatively small.
* Array datatypes are currently limited to H5S_MAX_RANK number of
@@ -63,7 +111,7 @@ H5T_init_array_interface(void)
* 0. (i.e. 0 > ndims <= H5S_MAX_RANK) All dimensions sizes must be greater
* than 0 also.
*
- * Return: Success: ID of new array data type
+ * Return: Success: ID of new array datatype
* Failure: Negative
*
* Programmer: Quincey Koziol
@@ -74,8 +122,8 @@ H5T_init_array_interface(void)
hid_t
H5Tarray_create2(hid_t base_id, unsigned ndims, const hsize_t dim[/* ndims */])
{
- H5T_t *base; /* base data type */
- H5T_t *dt; /* new array data type */
+ H5T_t *base; /* base datatype */
+ H5T_t *dt = NULL; /* new array datatype */
unsigned u; /* local index variable */
hid_t ret_value; /* return value */
@@ -90,18 +138,23 @@ H5Tarray_create2(hid_t base_id, unsigned ndims, const hsize_t dim[/* ndims */])
for(u = 0; u < ndims; u++)
if(!(dim[u] > 0))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "zero-sized dimension specified")
- if(NULL == (base = H5I_object_verify(base_id, H5I_DATATYPE)))
+ if(NULL == (base = (H5T_t *)H5I_object_verify(base_id, H5I_DATATYPE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an valid base datatype")
- /* Create the actual array datatype */
- if((dt = H5T_array_create(base, ndims, dim)) == NULL)
+ /* Create the array datatype */
+ if(NULL == (dt = H5T_array_create(base, ndims, dim)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to create datatype")
/* Atomize the type */
- if((ret_value = H5I_register(H5I_DATATYPE, dt)) < 0)
+ if((ret_value = H5I_register(H5I_DATATYPE, dt, TRUE)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register datatype")
done:
+ if(ret_value < 0) {
+ if(dt && H5T_close(dt) < 0)
+ HDONE_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "can't release datatype")
+ } /* end if */
+
FUNC_LEAVE_API(ret_value)
} /* end H5Tarray_create2() */
@@ -183,14 +236,14 @@ done:
int
H5Tget_array_ndims(hid_t type_id)
{
- H5T_t *dt; /* pointer to array data type */
+ H5T_t *dt; /* pointer to array datatype */
int ret_value; /* return value */
FUNC_ENTER_API(H5Tget_array_ndims, FAIL)
H5TRACE1("Is", "i", type_id);
/* Check args */
- if(NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE)))
+ if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id,H5I_DATATYPE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object")
if(dt->shared->type != H5T_ARRAY)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an array datatype")
@@ -253,7 +306,7 @@ H5Tget_array_dims2(hid_t type_id, hsize_t dims[])
H5TRACE2("Is", "i*h", type_id, dims);
/* Check args */
- if(NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE)))
+ if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id,H5I_DATATYPE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object")
if(dt->shared->type != H5T_ARRAY)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an array datatype")
@@ -308,7 +361,7 @@ done:
/*-------------------------------------------------------------------------
* Function: H5Tarray_create1
*
- * Purpose: Create a new array data type based on the specified BASE_TYPE.
+ * Purpose: Create a new array datatype based on the specified BASE_TYPE.
* The type is an array with NDIMS dimensionality and the size of the
* array is DIMS. The total member size should be relatively small.
* Array datatypes are currently limited to H5S_MAX_RANK number of
@@ -316,7 +369,7 @@ done:
* 0. (i.e. 0 > ndims <= H5S_MAX_RANK) All dimensions sizes must be greater
* than 0 also.
*
- * Return: Success: ID of new array data type
+ * Return: Success: ID of new array datatype
* Failure: Negative
*
* Programmer: Quincey Koziol
@@ -328,8 +381,8 @@ hid_t
H5Tarray_create1(hid_t base_id, int ndims, const hsize_t dim[/* ndims */],
const int UNUSED perm[/* ndims */])
{
- H5T_t *base; /* base data type */
- H5T_t *dt; /* new array data type */
+ H5T_t *base; /* base datatype */
+ H5T_t *dt = NULL; /* new array datatype */
unsigned u; /* local index variable */
hid_t ret_value; /* return value */
@@ -344,18 +397,23 @@ H5Tarray_create1(hid_t base_id, int ndims, const hsize_t dim[/* ndims */],
for(u = 0; u < (unsigned)ndims; u++)
if(!(dim[u] > 0))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "zero-sized dimension specified")
- if(NULL == (base = H5I_object_verify(base_id, H5I_DATATYPE)))
+ if(NULL == (base = (H5T_t *)H5I_object_verify(base_id, H5I_DATATYPE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an valid base datatype")
- /* Create the actual array datatype */
- if((dt = H5T_array_create(base, (unsigned)ndims, dim)) == NULL)
+ /* Create the array datatype */
+ if(NULL == (dt = H5T_array_create(base, (unsigned)ndims, dim)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to create datatype")
/* Atomize the type */
- if((ret_value = H5I_register(H5I_DATATYPE, dt)) < 0)
+ if((ret_value = H5I_register(H5I_DATATYPE, dt, TRUE)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register datatype")
done:
+ if(ret_value < 0) {
+ if(dt && H5T_close(dt) < 0)
+ HDONE_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "can't release datatype")
+ } /* end if */
+
FUNC_LEAVE_API(ret_value)
} /* end H5Tarray_create1() */
@@ -376,14 +434,14 @@ done:
int
H5Tget_array_dims1(hid_t type_id, hsize_t dims[], int UNUSED perm[])
{
- H5T_t *dt; /* pointer to array data type */
+ H5T_t *dt; /* Array datatype to query */
int ret_value; /* return value */
FUNC_ENTER_API(H5Tget_array_dims1, FAIL)
H5TRACE3("Is", "i*h*Is", type_id, dims, perm);
/* Check args */
- if(NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE)))
+ if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object")
if(dt->shared->type != H5T_ARRAY)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an array datatype")
@@ -391,9 +449,9 @@ H5Tget_array_dims1(hid_t type_id, hsize_t dims[], int UNUSED perm[])
/* Retrieve the sizes of the dimensions */
if((ret_value = H5T_get_array_dims(dt, dims)) < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "unable to get dimension sizes")
+
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Tget_array_dims1() */
-
#endif /* H5_NO_DEPRECATED_SYMBOLS */
diff --git a/src/H5Tbit.c b/src/H5Tbit.c
index 948a6eb..a5340a6 100644
--- a/src/H5Tbit.c
+++ b/src/H5Tbit.c
@@ -395,10 +395,10 @@ H5T_bit_set (uint8_t *buf, size_t offset, size_t size, hbool_t value)
*-------------------------------------------------------------------------
*/
ssize_t
-H5T_bit_find (uint8_t *buf, size_t offset, size_t size, H5T_sdir_t direction,
+H5T_bit_find(uint8_t *buf, size_t offset, size_t size, H5T_sdir_t direction,
hbool_t value)
{
- ssize_t base=(ssize_t)offset;
+ ssize_t base = (ssize_t)offset;
ssize_t idx, i;
size_t iu;
ssize_t ret_value=(-1); /* Return value */
@@ -407,78 +407,81 @@ H5T_bit_find (uint8_t *buf, size_t offset, size_t size, H5T_sdir_t direction,
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_bit_find);
/* Some functions call this with value=TRUE */
- assert (TRUE==1);
-
- switch (direction) {
- case H5T_BIT_LSB:
- /* Calculate index */
- idx = (ssize_t)(offset / 8);
- offset %= 8;
-
- /* Beginning */
- if (offset) {
- for (iu=offset; iu<8 && size>0; iu++, size--) {
- if (value==(hbool_t)((buf[idx]>>iu) & 0x01))
- HGOTO_DONE(8*idx+(ssize_t)iu - base);
- }
- offset = 0;
- idx++;
- }
- /* Middle */
- while (size>=8) {
- if ((value?0x00:0xff)!=buf[idx]) {
- for (i=0; i<8; i++) {
- if (value==(hbool_t)((buf[idx]>>i) & 0x01))
- HGOTO_DONE(8*idx+i - base);
- }
- }
- size -= 8;
- idx++;
- }
- /* End */
- for (i=0; i<(ssize_t)size; i++) {
- if (value==(hbool_t)((buf[idx]>>i) & 0x01))
- HGOTO_DONE(8*idx+i - base);
- }
- break;
-
- case H5T_BIT_MSB:
- /* Calculate index */
- idx = (ssize_t)((offset+size-1) / 8);
- offset %= 8;
-
- /* Beginning */
- if (size>8-offset && (offset+size)%8) {
- for (iu=(offset+size)%8; iu>0; --iu, --size) {
- if (value==(hbool_t)((buf[idx]>>(iu-1)) & 0x01))
- HGOTO_DONE(8*idx+(ssize_t)(iu-1) - base);
- }
- --idx;
- }
- /* Middle */
- while (size>=8) {
- if ((value?0x00:0xff)!=buf[idx]) {
- for (i=7; i>=0; --i) {
- if (value==(hbool_t)((buf[idx]>>i) & 0x01))
- HGOTO_DONE(8*idx+i - base);
- }
- }
- size -= 8;
- --idx;
- }
- /* End */
- if (size>0) {
- for (iu=offset+size; iu>offset; --iu) {
- if (value==(hbool_t)((buf[idx]>>(iu-1)) & 0x01))
- HGOTO_DONE(8*idx+(ssize_t)(iu-1) - base);
- }
- }
- break;
- }
+ HDassert(TRUE == 1);
+
+ switch(direction) {
+ case H5T_BIT_LSB:
+ /* Calculate index */
+ idx = (ssize_t)(offset / 8);
+ offset %= 8;
+
+ /* Beginning */
+ if (offset) {
+ for (iu=offset; iu<8 && size>0; iu++, size--) {
+ if (value==(hbool_t)((buf[idx]>>iu) & 0x01))
+ HGOTO_DONE(8*idx+(ssize_t)iu - base);
+ }
+ offset = 0;
+ idx++;
+ }
+ /* Middle */
+ while (size>=8) {
+ if ((value?0x00:0xff)!=buf[idx]) {
+ for (i=0; i<8; i++) {
+ if (value==(hbool_t)((buf[idx]>>i) & 0x01))
+ HGOTO_DONE(8*idx+i - base);
+ }
+ }
+ size -= 8;
+ idx++;
+ }
+ /* End */
+ for (i=0; i<(ssize_t)size; i++) {
+ if (value==(hbool_t)((buf[idx]>>i) & 0x01))
+ HGOTO_DONE(8*idx+i - base);
+ }
+ break;
+
+ case H5T_BIT_MSB:
+ /* Calculate index */
+ idx = (ssize_t)((offset+size-1) / 8);
+ offset %= 8;
+
+ /* Beginning */
+ if (size>8-offset && (offset+size)%8) {
+ for (iu=(offset+size)%8; iu>0; --iu, --size) {
+ if (value==(hbool_t)((buf[idx]>>(iu-1)) & 0x01))
+ HGOTO_DONE(8*idx+(ssize_t)(iu-1) - base);
+ }
+ --idx;
+ }
+ /* Middle */
+ while (size>=8) {
+ if ((value?0x00:0xff)!=buf[idx]) {
+ for (i=7; i>=0; --i) {
+ if (value==(hbool_t)((buf[idx]>>i) & 0x01))
+ HGOTO_DONE(8*idx+i - base);
+ }
+ }
+ size -= 8;
+ --idx;
+ }
+ /* End */
+ if (size>0) {
+ for (iu=offset+size; iu>offset; --iu) {
+ if (value==(hbool_t)((buf[idx]>>(iu-1)) & 0x01))
+ HGOTO_DONE(8*idx+(ssize_t)(iu-1) - base);
+ }
+ }
+ break;
+
+ default:
+ HDassert(0 && "Unknown bit search direction");
+ } /* end switch */
done:
FUNC_LEAVE_NOAPI(ret_value);
-}
+} /* end H5T_bit_find() */
/*-------------------------------------------------------------------------
diff --git a/src/H5Tcommit.c b/src/H5Tcommit.c
index bcb9962..df35789 100644
--- a/src/H5Tcommit.c
+++ b/src/H5Tcommit.c
@@ -18,12 +18,19 @@
* to a file for the H5T interface.
*/
+/****************/
+/* Module Setup */
+/****************/
+
#define H5T_PACKAGE /*suppress error about including H5Tpkg */
/* Interface initialization */
#define H5_INTERFACE_INIT_FUNC H5T_init_commit_interface
+/***********/
+/* Headers */
+/***********/
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
#include "H5FOprivate.h" /* File objects */
@@ -32,9 +39,48 @@
#include "H5Pprivate.h" /* Property lists */
#include "H5Tpkg.h" /* Datatypes */
-/* Static local functions */
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
static H5T_t *H5T_open_oid(const H5G_loc_t *loc, hid_t dxpl_id);
+
+/*********************/
+/* Public Variables */
+/*********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
/*--------------------------------------------------------------------------
NAME
@@ -87,7 +133,7 @@ H5Tcommit2(hid_t loc_id, const char *name, hid_t type_id, hid_t lcpl_id,
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name")
- if(NULL == (type = H5I_object_verify(type_id, H5I_DATATYPE)))
+ if(NULL == (type = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
/* Get correct property list */
@@ -224,17 +270,17 @@ done:
herr_t
H5Tcommit_anon(hid_t loc_id, hid_t type_id, hid_t tcpl_id, hid_t tapl_id)
{
- H5G_loc_t loc;
- H5T_t *type = NULL;
- herr_t ret_value=SUCCEED; /* Return value */
+ H5G_loc_t loc; /* Group location for location */
+ H5T_t *type = NULL; /* Datatype created */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(H5Tcommit_anon, FAIL)
H5TRACE4("e", "iiii", loc_id, type_id, tcpl_id, tapl_id);
/* Check arguments */
- if(H5G_loc (loc_id, &loc) < 0)
+ if(H5G_loc(loc_id, &loc) < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
- if(NULL == (type = H5I_object_verify(type_id, H5I_DATATYPE)))
+ if(NULL == (type = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
/* Get correct property list */
@@ -302,8 +348,9 @@ H5T_commit(H5F_t *file, H5T_t *type, hid_t tcpl_id, hid_t dxpl_id)
if(H5T_is_sensible(type) <= 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "datatype is not sensible")
- /* Mark datatype as being on disk now. This step changes the size of datatype as
- * stored on disk. */
+ /* Mark datatype as being on disk now. This step changes the size of
+ * datatype as stored on disk.
+ */
if(H5T_set_loc(type, file, H5T_LOC_DISK) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "cannot mark datatype on disk")
@@ -350,8 +397,9 @@ H5T_commit(H5F_t *file, H5T_t *type, hid_t tcpl_id, hid_t dxpl_id)
if(H5FO_insert(type->sh_loc.file, type->sh_loc.u.loc.oh_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
- * after committed to disk, change its size back as in memory. */
+ /* Mark datatype as being on memory again. Since this datatype may still be
+ * used in memory after committed to disk, change its size back as in memory.
+ */
if(H5T_set_loc(type, NULL, H5T_LOC_MEMORY) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "cannot mark datatype in memory")
@@ -391,14 +439,14 @@ done:
htri_t
H5Tcommitted(hid_t type_id)
{
- H5T_t *type = NULL;
- htri_t ret_value; /* Return value */
+ H5T_t *type; /* Datatype to query */
+ htri_t ret_value; /* Return value */
FUNC_ENTER_API(H5Tcommitted, FAIL)
H5TRACE1("t", "i", type_id);
/* Check arguments */
- if(NULL == (type = H5I_object_verify(type_id,H5I_DATATYPE)))
+ if(NULL == (type = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
/* Set return value */
@@ -440,7 +488,6 @@ H5T_committed(const H5T_t *type)
* ADJUST to the link count.
*
* Return: Success: New link count
- *
* Failure: Negative
*
* Programmer: Quincey Koziol
@@ -484,15 +531,15 @@ done:
hid_t
H5Topen2(hid_t loc_id, const char *name, hid_t tapl_id)
{
- H5T_t *type = NULL;
- H5G_loc_t loc;
+ H5T_t *type = NULL; /* Datatype opened in file */
+ H5G_loc_t loc; /* Group location of object to open */
H5G_name_t path; /* Datatype group hier. path */
H5O_loc_t oloc; /* Datatype object location */
H5O_type_t obj_type; /* Type of object at location */
H5G_loc_t type_loc; /* Group object for datatype */
hbool_t obj_found = FALSE; /* Object at 'name' found */
hid_t dxpl_id = H5AC_dxpl_id; /* dxpl to use to open datatype */
- hid_t ret_value = FAIL;
+ hid_t ret_value = FAIL; /* Return value */
FUNC_ENTER_API(H5Topen2, FAIL)
H5TRACE3("i", "i*si", loc_id, name, tapl_id);
@@ -530,11 +577,11 @@ H5Topen2(hid_t loc_id, const char *name, hid_t tapl_id)
HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "not a named datatype")
/* Open it */
- if((type = H5T_open(&type_loc, dxpl_id)) == NULL)
+ if(NULL == (type = H5T_open(&type_loc, dxpl_id)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, FAIL, "unable to open named datatype")
/* Register the type and return the ID */
- if((ret_value = H5I_register(H5I_DATATYPE, type)) < 0)
+ if((ret_value = H5I_register(H5I_DATATYPE, type, TRUE)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register named datatype")
done:
@@ -580,13 +627,13 @@ H5Tget_create_plist(hid_t dtype_id)
H5TRACE1("i", "i", dtype_id);
/* Check arguments */
- if(NULL == (type = H5I_object_verify(dtype_id, H5I_DATATYPE)))
+ if(NULL == (type = (H5T_t *)H5I_object_verify(dtype_id, H5I_DATATYPE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
/* Copy the default datatype creation property list */
- if(NULL == (tcpl_plist = H5I_object(H5P_LST_DATATYPE_CREATE_g)))
+ if(NULL == (tcpl_plist = (H5P_genplist_t *)H5I_object(H5P_LST_DATATYPE_CREATE_g)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get default creation property list")
- if((new_tcpl_id = H5P_copy_plist(tcpl_plist)) < 0)
+ if((new_tcpl_id = H5P_copy_plist(tcpl_plist, TRUE)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to copy the creation property list")
/* Check if the datatype is committed */
@@ -598,7 +645,7 @@ H5Tget_create_plist(hid_t dtype_id)
H5P_genplist_t *new_plist; /* New datatype creation property list */
/* Get property list object for new TCPL */
- if(NULL == (new_plist = H5I_object(new_tcpl_id)))
+ if(NULL == (new_plist = (H5P_genplist_t *)H5I_object(new_tcpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list")
/* Retrieve any object creation properties */
@@ -612,7 +659,7 @@ H5Tget_create_plist(hid_t dtype_id)
done:
if(ret_value < 0)
if(new_tcpl_id > 0)
- (void)H5I_dec_ref(new_tcpl_id);
+ (void)H5I_dec_ref(new_tcpl_id, TRUE);
FUNC_LEAVE_API(ret_value)
} /* end H5Tget_create_plist() */
@@ -644,12 +691,12 @@ H5T_open(const H5G_loc_t *loc, hid_t dxpl_id)
HDassert(loc);
/* Check if datatype was already open */
- if((shared_fo = H5FO_opened(loc->oloc->file, loc->oloc->addr)) == NULL) {
+ if(NULL == (shared_fo = (H5T_shared_t *)H5FO_opened(loc->oloc->file, loc->oloc->addr))) {
/* Clear any errors from H5FO_opened() */
H5E_clear_stack(NULL);
/* Open the datatype object */
- if((dt = H5T_open_oid(loc, dxpl_id)) == NULL)
+ if(NULL == (dt = H5T_open_oid(loc, dxpl_id)))
HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, NULL, "not found")
/* Add the datatype to the list of opened objects in the file */
@@ -748,16 +795,19 @@ done:
static H5T_t *
H5T_open_oid(const H5G_loc_t *loc, hid_t dxpl_id)
{
- H5T_t *dt = NULL;
- H5T_t *ret_value;
+ H5T_t *dt = NULL; /* Datatype from the file */
+ H5T_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5T_open_oid)
HDassert(loc);
+ /* Open named datatype object in file */
if(H5O_open(loc->oloc) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to open named datatype")
- if(NULL == (dt = H5O_msg_read(loc->oloc, H5O_DTYPE_ID, NULL, dxpl_id)))
+
+ /* Deserialize the datatype message into a datatype in memory */
+ if(NULL == (dt = (H5T_t *)H5O_msg_read(loc->oloc, H5O_DTYPE_ID, NULL, dxpl_id)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to load type message from object header")
/* Mark the type as named and open */
diff --git a/src/H5Tcompound.c b/src/H5Tcompound.c
index 660a76d..d9b5974 100644
--- a/src/H5Tcompound.c
+++ b/src/H5Tcompound.c
@@ -18,34 +18,77 @@
* in the H5T interface.
*/
+/****************/
+/* Module Setup */
+/****************/
+
#define H5T_PACKAGE /*suppress error about including H5Tpkg */
/* Interface initialization */
#define H5_INTERFACE_INIT_FUNC H5T_init_compound_interface
+/***********/
+/* Headers */
+/***********/
#include "H5private.h" /*generic functions */
#include "H5Eprivate.h" /*error handling */
#include "H5Iprivate.h" /*ID functions */
#include "H5MMprivate.h" /*memory management */
#include "H5Tpkg.h" /*data-type functions */
-/* Static local functions */
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
static herr_t H5T_pack(const H5T_t *dt);
+
+/*********************/
+/* Public Variables */
+/*********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
/*--------------------------------------------------------------------------
NAME
H5T_init_compound_interface -- Initialize interface-specific information
USAGE
herr_t H5T_init_compound_interface()
-
RETURNS
Non-negative on success/Negative on failure
DESCRIPTION
Initializes any interface-specific data or routines. (Just calls
- H5T_init_iterface currently).
-
+ H5T_init() currently).
--------------------------------------------------------------------------*/
static herr_t
H5T_init_compound_interface(void)
@@ -79,24 +122,24 @@ H5T_init_compound_interface(void)
size_t
H5Tget_member_offset(hid_t type_id, unsigned membno)
{
- H5T_t *dt = NULL;
- size_t ret_value;
+ H5T_t *dt; /* Datatype to query */
+ size_t ret_value; /* Return value */
FUNC_ENTER_API(H5Tget_member_offset, 0)
H5TRACE2("z", "iIu", type_id, membno);
/* Check args */
- if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE)) || H5T_COMPOUND != dt->shared->type)
+ if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)) || H5T_COMPOUND != dt->shared->type)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a compound datatype")
- if (membno >= dt->shared->u.compnd.nmembs)
+ if(membno >= dt->shared->u.compnd.nmembs)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "invalid member number")
/* Value */
- ret_value = H5T_get_member_offset(dt, membno);
+ ret_value = H5T_GET_MEMBER_OFFSET(dt->shared, membno);
done:
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5Tget_member_offset() */
/*-------------------------------------------------------------------------
@@ -116,25 +159,18 @@ done:
* Programmer: Raymond Lu
* October 8, 2002
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
size_t
H5T_get_member_offset(const H5T_t *dt, unsigned membno)
{
- size_t ret_value;
-
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_get_member_offset)
- assert(dt);
- assert(membno < dt->shared->u.compnd.nmembs);
+ HDassert(dt);
+ HDassert(membno < dt->shared->u.compnd.nmembs);
- /* Value */
- ret_value = dt->shared->u.compnd.memb[membno].offset;
-
- FUNC_LEAVE_NOAPI(ret_value)
-}
+ FUNC_LEAVE_NOAPI(dt->shared->u.compnd.memb[membno].offset)
+} /* end H5T_get_member_offset() */
/*-------------------------------------------------------------------------
@@ -156,21 +192,22 @@ H5T_get_member_offset(const H5T_t *dt, unsigned membno)
H5T_class_t
H5Tget_member_class(hid_t type_id, unsigned membno)
{
- H5T_t *dt = NULL;
- H5T_class_t ret_value;
+ H5T_t *dt; /* Datatype to query */
+ H5T_class_t ret_value; /* Return value */
FUNC_ENTER_API(H5Tget_member_class, H5T_NO_CLASS)
H5TRACE2("Tt", "iIu", type_id, membno);
/* Check args */
- if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE)) || H5T_COMPOUND != dt->shared->type)
+ if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)) || H5T_COMPOUND != dt->shared->type)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a compound datatype")
- if (membno >= dt->shared->u.compnd.nmembs)
+ if(membno >= dt->shared->u.compnd.nmembs)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5T_NO_CLASS, "invalid member number")
/* Get the type's class. We have to use this function to get type class
- * because of the concern of variable-length string. */
- ret_value = H5T_get_class(dt->shared->u.compnd.memb[membno].type, FALSE);
+ * because of the concern of variable-length string.
+ */
+ ret_value = H5T_GET_CLASS(dt->shared->u.compnd.memb[membno].type->shared, FALSE);
done:
FUNC_LEAVE_API(ret_value)
@@ -193,42 +230,35 @@ done:
* Programmer: Robb Matzke
* Wednesday, January 7, 1998
*
- * Modifications:
- *
- * Robb Matzke, 4 Jun 1998
- * If the member type is a named type then this function returns a
- * handle to the re-opened named type.
- *
*-------------------------------------------------------------------------
*/
hid_t
H5Tget_member_type(hid_t type_id, unsigned membno)
{
- H5T_t *dt = NULL, *memb_dt = NULL;
- hid_t ret_value;
+ H5T_t *dt; /* Datatype to query */
+ H5T_t *memb_dt = NULL; /* Member datatype */
+ hid_t ret_value; /* Return value */
FUNC_ENTER_API(H5Tget_member_type, FAIL)
H5TRACE2("i", "iIu", type_id, membno);
/* Check args */
- if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE)) || H5T_COMPOUND != dt->shared->type)
+ if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)) || H5T_COMPOUND != dt->shared->type)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a compound datatype")
- if (membno >= dt->shared->u.compnd.nmembs)
+ if(membno >= dt->shared->u.compnd.nmembs)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid member number")
- if ((memb_dt=H5T_get_member_type(dt, membno))==NULL)
+ if(NULL == (memb_dt = H5T_get_member_type(dt, membno, H5T_COPY_REOPEN)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to retrieve member type")
- if ((ret_value = H5I_register(H5I_DATATYPE, memb_dt)) < 0)
+ if((ret_value = H5I_register(H5I_DATATYPE, memb_dt, TRUE)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable register datatype atom")
done:
- if(ret_value<0) {
- if(memb_dt!=NULL)
- if(H5T_close(memb_dt)<0)
- HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "can't close datatype")
- } /* end if */
+ if(ret_value < 0)
+ if(memb_dt && H5T_close(memb_dt) < 0)
+ HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "can't close datatype")
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5Tget_member_type() */
/*-------------------------------------------------------------------------
@@ -246,27 +276,25 @@ done:
* Programmer: Raymond Lu
* October 8, 2002
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
H5T_t *
-H5T_get_member_type(const H5T_t *dt, unsigned membno)
+H5T_get_member_type(const H5T_t *dt, unsigned membno, H5T_copy_t method)
{
- H5T_t *ret_value = NULL;
+ H5T_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5T_get_member_type, NULL)
- assert(dt);
- assert(membno < dt->shared->u.compnd.nmembs);
+ HDassert(dt);
+ HDassert(membno < dt->shared->u.compnd.nmembs);
/* Copy datatype into an atom */
- if (NULL == (ret_value = H5T_copy(dt->shared->u.compnd.memb[membno].type, H5T_COPY_REOPEN)))
+ if(NULL == (ret_value = H5T_copy(dt->shared->u.compnd.memb[membno].type, method)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy member datatype")
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5T_get_member_type() */
/*-------------------------------------------------------------------------
@@ -275,31 +303,24 @@ done:
* Purpose: Returns the size of the specified member.
*
* Return: Success: The size in bytes of the member's datatype.
- *
* Failure: 0
*
* Programmer: Quincey Koziol
* October 4, 2004
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
size_t
H5T_get_member_size(const H5T_t *dt, unsigned membno)
{
- size_t ret_value = 0;
-
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_get_member_size)
- assert(dt);
- assert(membno < dt->shared->u.compnd.nmembs);
+ HDassert(dt);
+ HDassert(membno < dt->shared->u.compnd.nmembs);
- /* Value */
- ret_value = dt->shared->u.compnd.memb[membno].type->shared->size;
- FUNC_LEAVE_NOAPI(ret_value)
-}
+ FUNC_LEAVE_NOAPI(dt->shared->u.compnd.memb[membno].type->shared->size)
+} /* end H5T_get_member_size() */
/*-------------------------------------------------------------------------
@@ -329,32 +350,32 @@ H5T_get_member_size(const H5T_t *dt, unsigned membno)
herr_t
H5Tinsert(hid_t parent_id, const char *name, size_t offset, hid_t member_id)
{
- H5T_t *parent = NULL; /*the compound parent datatype */
- H5T_t *member = NULL; /*the atomic member type */
- herr_t ret_value=SUCCEED; /* Return value */
+ H5T_t *parent; /* The compound parent datatype */
+ H5T_t *member; /* The member datatype */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(H5Tinsert, FAIL)
H5TRACE4("e", "i*szi", parent_id, name, offset, member_id);
/* Check args */
- if (parent_id==member_id)
+ if(parent_id == member_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "can't insert compound datatype within itself")
- if (NULL == (parent = H5I_object_verify(parent_id,H5I_DATATYPE)) || H5T_COMPOUND != parent->shared->type)
+ if(NULL == (parent = (H5T_t *)H5I_object_verify(parent_id, H5I_DATATYPE)) || H5T_COMPOUND != parent->shared->type)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a compound datatype")
- if (H5T_STATE_TRANSIENT!=parent->shared->state)
+ if(H5T_STATE_TRANSIENT != parent->shared->state)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "parent type read-only")
- if (!name || !*name)
+ if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no member name")
- if (NULL == (member = H5I_object_verify(member_id,H5I_DATATYPE)))
+ if(NULL == (member = (H5T_t *)H5I_object_verify(member_id, H5I_DATATYPE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
/* Insert */
- if (H5T_insert(parent, name, offset, member) < 0)
+ if(H5T_insert(parent, name, offset, member) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "unable to insert member")
done:
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5Tinsert() */
/*-------------------------------------------------------------------------
@@ -375,23 +396,23 @@ done:
herr_t
H5Tpack(hid_t type_id)
{
- H5T_t *dt = NULL;
- herr_t ret_value=SUCCEED; /* Return value */
+ H5T_t *dt; /* Datatype to modify */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(H5Tpack, FAIL)
H5TRACE1("e", "i", type_id);
/* Check args */
- if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE)) || H5T_detect_class(dt,H5T_COMPOUND)<=0)
+ if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)) || H5T_detect_class(dt, H5T_COMPOUND) <= 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a compound datatype")
/* Pack */
- if (H5T_pack(dt) < 0)
+ if(H5T_pack(dt) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to pack compound datatype")
done:
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5Tpack() */
/*-------------------------------------------------------------------------
@@ -407,17 +428,15 @@ done:
* Programmer: Robb Matzke
* Monday, December 8, 1997
*
- * Modifications:
- * Took out arrayness parameters - QAK, 10/6/00
- *
*-------------------------------------------------------------------------
*/
herr_t
H5T_insert(H5T_t *parent, const char *name, size_t offset, const H5T_t *member)
{
- unsigned idx, i;
+ unsigned idx; /* Index of member to insert */
size_t total_size;
- herr_t ret_value = SUCCEED; /* Return value */
+ unsigned i; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5T_insert, FAIL)
@@ -436,10 +455,10 @@ H5T_insert(H5T_t *parent, const char *name, size_t offset, const H5T_t *member)
total_size = member->shared->size;
for(i = 0; i < parent->shared->u.compnd.nmembs; i++)
if((offset <= parent->shared->u.compnd.memb[i].offset &&
- offset + total_size > parent->shared->u.compnd.memb[i].offset) ||
+ (offset + total_size) > parent->shared->u.compnd.memb[i].offset) ||
(parent->shared->u.compnd.memb[i].offset <= offset &&
- parent->shared->u.compnd.memb[i].offset +
- parent->shared->u.compnd.memb[i].size > offset))
+ (parent->shared->u.compnd.memb[i].offset +
+ parent->shared->u.compnd.memb[i].size) > offset))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "member overlaps with another member")
/* Does the new member overlap the end of the compound type? */
@@ -449,10 +468,10 @@ H5T_insert(H5T_t *parent, const char *name, size_t offset, const H5T_t *member)
/* Increase member array if necessary */
if(parent->shared->u.compnd.nmembs >= parent->shared->u.compnd.nalloc) {
unsigned na = MAX(1, parent->shared->u.compnd.nalloc * 2);
- H5T_cmemb_t *x = H5MM_realloc(parent->shared->u.compnd.memb, na * sizeof(H5T_cmemb_t));
+ H5T_cmemb_t *x = (H5T_cmemb_t *)H5MM_realloc(parent->shared->u.compnd.memb, na * sizeof(H5T_cmemb_t));
if(!x)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "memory allocation failed")
parent->shared->u.compnd.nalloc = na;
parent->shared->u.compnd.memb = x;
} /* end if */
@@ -519,28 +538,24 @@ done:
* Programmer: Robb Matzke
* Wednesday, January 7, 1998
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
static herr_t
H5T_pack(const H5T_t *dt)
{
- unsigned i;
- size_t offset;
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5T_pack)
- assert(dt);
+ HDassert(dt);
- if(H5T_detect_class(dt,H5T_COMPOUND)>0) {
+ if(H5T_detect_class(dt, H5T_COMPOUND) > 0) {
/* If datatype has been packed, skip packing it and indicate success */
- if(H5T_is_packed(dt)== TRUE)
+ if(TRUE == H5T_is_packed(dt))
HGOTO_DONE(SUCCEED)
/* Check for packing unmodifiable datatype */
- if (H5T_STATE_TRANSIENT!=dt->shared->state)
+ if(H5T_STATE_TRANSIENT != dt->shared->state)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "datatype is read-only")
if(dt->shared->parent) {
@@ -548,21 +563,28 @@ H5T_pack(const H5T_t *dt)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to pack parent of datatype")
/* Adjust size of datatype appropriately */
- if(dt->shared->type==H5T_ARRAY)
+ if(dt->shared->type == H5T_ARRAY)
dt->shared->size = dt->shared->parent->shared->size * dt->shared->u.array.nelem;
- else if(dt->shared->type!=H5T_VLEN)
+ else if(dt->shared->type != H5T_VLEN)
dt->shared->size = dt->shared->parent->shared->size;
} /* end if */
- else if(dt->shared->type==H5T_COMPOUND) {
+ else if(dt->shared->type == H5T_COMPOUND) {
+ size_t offset; /* Offset of member */
+ unsigned i; /* Local index variable */
+
/* Recursively pack the members */
- for (i=0; i<dt->shared->u.compnd.nmembs; i++)
- if (H5T_pack(dt->shared->u.compnd.memb[i].type) < 0)
+ for(i = 0; i < dt->shared->u.compnd.nmembs; i++) {
+ if(H5T_pack(dt->shared->u.compnd.memb[i].type) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to pack part of a compound datatype")
+ /* Update the member size */
+ dt->shared->u.compnd.memb[i].size = (dt->shared->u.compnd.memb[i].type)->shared->size;
+ } /* end for */
+
/* Remove padding between members */
- if(H5T_sort_value(dt, NULL)<0)
+ if(H5T_sort_value(dt, NULL) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOMPARE, FAIL, "value sort failed")
- for (i=0, offset=0; i<dt->shared->u.compnd.nmembs; i++) {
+ for(i = 0, offset = 0; i < dt->shared->u.compnd.nmembs; i++) {
dt->shared->u.compnd.memb[i].offset = offset;
offset += dt->shared->u.compnd.memb[i].size;
}
@@ -571,13 +593,13 @@ H5T_pack(const H5T_t *dt)
dt->shared->size = MAX(1, offset);
/* Mark the type as packed now */
- dt->shared->u.compnd.packed=TRUE;
+ dt->shared->u.compnd.packed = TRUE;
} /* end if */
} /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5T_pack() */
/*-------------------------------------------------------------------------
@@ -598,19 +620,19 @@ done:
htri_t
H5T_is_packed(const H5T_t *dt)
{
- htri_t ret_value=TRUE; /* Return value */
+ htri_t ret_value = TRUE; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_is_packed)
- assert(dt);
+ HDassert(dt);
/* Go up the chain as far as possible */
while(dt->shared->parent)
- dt=dt->shared->parent;
+ dt = dt->shared->parent;
/* If this is a compound datatype, check if it is packed */
- if(dt->shared->type==H5T_COMPOUND)
- ret_value=(htri_t)dt->shared->u.compnd.packed;
+ if(dt->shared->type == H5T_COMPOUND)
+ ret_value = (htri_t)dt->shared->u.compnd.packed;
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T_is_packed() */
diff --git a/src/H5Tconv.c b/src/H5Tconv.c
index 0da4d53..05277a8 100644
--- a/src/H5Tconv.c
+++ b/src/H5Tconv.c
@@ -14,11 +14,22 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
- * Module Info: Data type conversions for the H5T interface.
+ * Module Info: Datatype conversions for the H5T interface.
*/
+/****************/
+/* Module Setup */
+/****************/
+
#define H5T_PACKAGE /*suppress error about including H5Tpkg */
+/* Interface initialization */
+#define H5_INTERFACE_INIT_FUNC H5T_init_conv_interface
+
+
+/***********/
+/* Headers */
+/***********/
#include "H5private.h" /* Generic Functions */
#include "H5Dprivate.h" /* Datasets */
#include "H5Eprivate.h" /* Error handling */
@@ -29,33 +40,10 @@
#include "H5Pprivate.h" /* Property lists */
#include "H5Tpkg.h" /* Datatypes */
-/* Conversion data for H5T_conv_struct() */
-typedef struct H5T_conv_struct_t {
- int *src2dst; /*mapping from src to dst member num */
- hid_t *src_memb_id; /*source member type ID's */
- hid_t *dst_memb_id; /*destination member type ID's */
- H5T_path_t **memb_path; /*conversion path for each member */
- H5T_subset_t smembs_subset; /*are source and dest members a subset of each other? */
-} H5T_conv_struct_t;
-
-/* Conversion data for H5T_conv_enum() */
-typedef struct H5T_enum_struct_t {
- int base; /*lowest `in' value */
- int length; /*num elements in arrays */
- int *src2dst; /*map from src to dst index */
-} H5T_enum_struct_t;
-
-/* Conversion data for the hardware conversion functions */
-typedef struct H5T_conv_hw_t {
- size_t s_aligned; /*number source elements aligned */
- size_t d_aligned; /*number destination elements aligned*/
-} H5T_conv_hw_t;
-/* Declare a free list to manage pieces of vlen data */
-H5FL_BLK_DEFINE_STATIC(vlen_seq);
-
-/* Declare a free list to manage pieces of array data */
-H5FL_BLK_DEFINE_STATIC(array_seq);
+/****************/
+/* Local Macros */
+/****************/
/*
* These macros are for the bodies of functions that convert buffers of one
@@ -138,17 +126,17 @@ H5FL_BLK_DEFINE_STATIC(array_seq);
* CDATA: A pointer to the H5T_cdata_t structure that was passed to the
* conversion function.
*
- * STYPE: The hid_t value for the source data type.
+ * STYPE: The hid_t value for the source datatype.
*
- * DTYPE: The hid_t value for the destination data type.
+ * DTYPE: The hid_t value for the destination datatype.
*
* BUF: A pointer to the conversion buffer.
*
* NELMTS: The number of values to be converted.
*
- * ST: The C name for source data type (e.g., int)
+ * ST: The C name for source datatype (e.g., int)
*
- * DT: The C name for the destination data type (e.g., signed char)
+ * DT: The C name for the destination datatype (e.g., signed char)
*
* D_MIN: The minimum possible destination value. For unsigned
* destination types this should be zero. For signed
@@ -621,7 +609,7 @@ H5FL_BLK_DEFINE_STATIC(array_seq);
uint8_t *src, *s; /*source buffer */ \
uint8_t *dst, *d; /*destination buffer */ \
H5T_class_t tclass; /*datatype's class */ \
- H5T_t *st, *dt; /*data type descriptors */ \
+ H5T_t *st, *dt; /*datatype descriptors */ \
ATYPE aligned; /*aligned type */ \
hbool_t s_mv, d_mv; /*move data to align it? */ \
ssize_t s_stride, d_stride; /*src and dst strides */ \
@@ -885,9 +873,91 @@ H5FL_BLK_DEFINE_STATIC(array_seq);
/* Minimum size of variable-length conversion buffer */
#define H5T_VLEN_MIN_CONF_BUF_SIZE 4096
+/******************/
+/* Local Typedefs */
+/******************/
+
+/* Conversion data for H5T_conv_struct() */
+typedef struct H5T_conv_struct_t {
+ int *src2dst; /*mapping from src to dst member num */
+ hid_t *src_memb_id; /*source member type ID's */
+ hid_t *dst_memb_id; /*destination member type ID's */
+ H5T_path_t **memb_path; /*conversion path for each member */
+ H5T_subset_info_t subset_info; /*info related to compound subsets */
+ unsigned src_nmembs; /*needed by free function */
+} H5T_conv_struct_t;
+
+/* Conversion data for H5T_conv_enum() */
+typedef struct H5T_enum_struct_t {
+ int base; /*lowest `in' value */
+ int length; /*num elements in arrays */
+ int *src2dst; /*map from src to dst index */
+} H5T_enum_struct_t;
+
+/* Conversion data for the hardware conversion functions */
+typedef struct H5T_conv_hw_t {
+ size_t s_aligned; /*number source elements aligned */
+ size_t d_aligned; /*number destination elements aligned*/
+} H5T_conv_hw_t;
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
static herr_t H5T_reverse_order(uint8_t *rev, uint8_t *s, size_t size, H5T_order_t order);
+/*********************/
+/* Public Variables */
+/*********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* Declare a free list to manage pieces of vlen data */
+H5FL_BLK_DEFINE_STATIC(vlen_seq);
+
+/* Declare a free list to manage pieces of array data */
+H5FL_BLK_DEFINE_STATIC(array_seq);
+
+
+/*--------------------------------------------------------------------------
+NAME
+ H5T_init_conv_interface -- Initialize interface-specific information
+USAGE
+ herr_t H5T_init_conv_interface()
+RETURNS
+ Non-negative on success/Negative on failure
+DESCRIPTION
+ Initializes any interface-specific data or routines. (Just calls
+ H5T_init() currently).
+--------------------------------------------------------------------------*/
+static herr_t
+H5T_init_conv_interface(void)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_init_conv_interface)
+
+ FUNC_LEAVE_NOAPI(H5T_init())
+} /* H5T_init_conv_interface() */
+
+
/*-------------------------------------------------------------------------
* Function: H5T_conv_noop
*
@@ -899,8 +969,6 @@ static herr_t H5T_reverse_order(uint8_t *rev, uint8_t *s, size_t size, H5T_order
* Programmer: Robb Matzke
* Wednesday, January 14, 1998
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
herr_t
@@ -909,11 +977,11 @@ H5T_conv_noop(hid_t UNUSED src_id, hid_t UNUSED dst_id, H5T_cdata_t *cdata,
size_t UNUSED bkg_stride, void UNUSED *buf,
void UNUSED *background, hid_t UNUSED dxpl_id)
{
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_noop, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_noop, FAIL)
- switch (cdata->command) {
+ switch(cdata->command) {
case H5T_CONV_INIT:
cdata->need_bkg = H5T_BKG_NO;
break;
@@ -926,12 +994,12 @@ H5T_conv_noop(hid_t UNUSED src_id, hid_t UNUSED dst_id, H5T_cdata_t *cdata,
break;
default:
- HGOTO_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command");
- }
+ HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command")
+ } /* end switch */
done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T_conv_noop() */
/*-------------------------------------------------------------------------
@@ -962,377 +1030,380 @@ H5T_conv_order_opt(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
H5T_t *src = NULL;
H5T_t *dst = NULL;
size_t i;
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_order_opt, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_order_opt, FAIL)
- switch (cdata->command) {
- case H5T_CONV_INIT:
- /* Capability query */
- if (NULL == (src = H5I_object(src_id)) ||
- NULL == (dst = H5I_object(dst_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
- if (src->shared->size != dst->shared->size ||
- 0 != src->shared->u.atomic.offset ||
- 0 != dst->shared->u.atomic.offset)
- HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported");
- if((src->shared->type==H5T_REFERENCE && dst->shared->type!=H5T_REFERENCE) ||
- (dst->shared->type==H5T_REFERENCE && src->shared->type!=H5T_REFERENCE))
- HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported");
- if(src->shared->type!=H5T_REFERENCE &&
- !((H5T_ORDER_BE == src->shared->u.atomic.order && H5T_ORDER_LE == dst->shared->u.atomic.order) ||
- (H5T_ORDER_LE == src->shared->u.atomic.order && H5T_ORDER_BE == dst->shared->u.atomic.order)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported");
- if (src->shared->size!=1 && src->shared->size!=2 && src->shared->size!=4 &&
- src->shared->size!=8 && src->shared->size!=16)
- HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported");
- switch (src->shared->type) {
- case H5T_INTEGER:
- case H5T_BITFIELD:
- case H5T_REFERENCE:
- /* nothing to check */
- break;
-
- case H5T_FLOAT:
- if (src->shared->u.atomic.u.f.sign != dst->shared->u.atomic.u.f.sign ||
- src->shared->u.atomic.u.f.epos != dst->shared->u.atomic.u.f.epos ||
- src->shared->u.atomic.u.f.esize != dst->shared->u.atomic.u.f.esize ||
- src->shared->u.atomic.u.f.ebias != dst->shared->u.atomic.u.f.ebias ||
- src->shared->u.atomic.u.f.mpos != dst->shared->u.atomic.u.f.mpos ||
- src->shared->u.atomic.u.f.msize != dst->shared->u.atomic.u.f.msize ||
- src->shared->u.atomic.u.f.norm != dst->shared->u.atomic.u.f.norm ||
- src->shared->u.atomic.u.f.pad != dst->shared->u.atomic.u.f.pad)
- HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported");
- break;
-
- default:
- HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported");
- }
- cdata->need_bkg = H5T_BKG_NO;
- break;
-
- case H5T_CONV_CONV:
- /* The conversion */
- if (NULL == (src = H5I_object(src_id)) ||
- NULL == (dst = H5I_object(dst_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
-
- /* Check for "no op" reference conversion */
- if(src->shared->type==H5T_REFERENCE) {
- /* Sanity check */
- assert(dst->shared->type==H5T_REFERENCE);
-
- /* Check if we are on a little-endian machine (the order that
- * the addresses in the file must be) and just get out now, there
- * is no need to convert the object reference. Yes, this is
- * icky and non-portable, but I can't think of a better way to
- * support allowing the objno in the H5O_info_t struct and the
- * hobj_ref_t type to be compared directly without introducing a
- * "native" hobj_ref_t datatype and I think that would break a
- * lot of existing programs. -QAK
- */
- if(H5T_native_order_g == H5T_ORDER_LE)
- break;
- } /* end if */
+ switch(cdata->command) {
+ case H5T_CONV_INIT:
+ /* Capability query */
+ if(NULL == (src = H5I_object(src_id)) ||
+ NULL == (dst = H5I_object(dst_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type")
+ if(src->shared->size != dst->shared->size ||
+ 0 != src->shared->u.atomic.offset ||
+ 0 != dst->shared->u.atomic.offset)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported")
+ if((src->shared->type == H5T_REFERENCE && dst->shared->type != H5T_REFERENCE) ||
+ (dst->shared->type == H5T_REFERENCE && src->shared->type != H5T_REFERENCE))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported")
+ if(src->shared->type != H5T_REFERENCE &&
+ !((H5T_ORDER_BE == src->shared->u.atomic.order && H5T_ORDER_LE == dst->shared->u.atomic.order) ||
+ (H5T_ORDER_LE == src->shared->u.atomic.order && H5T_ORDER_BE == dst->shared->u.atomic.order)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported")
+ if (src->shared->size != 1 && src->shared->size != 2 && src->shared->size != 4 &&
+ src->shared->size != 8 && src->shared->size != 16)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported")
+ switch(src->shared->type) {
+ case H5T_INTEGER:
+ case H5T_BITFIELD:
+ case H5T_REFERENCE:
+ /* nothing to check */
+ break;
- buf_stride = buf_stride ? buf_stride : src->shared->size;
- switch (src->shared->size) {
- case 1:
- /*no-op*/
- break;
- case 2:
- for (/*void*/; nelmts>=20; nelmts-=20) {
- H5_SWAP_BYTES(buf, 0, 1); /* 0 */
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 1); /* 1 */
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 1); /* 2 */
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 1); /* 3 */
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 1); /* 4 */
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 1); /* 5 */
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 1); /* 6 */
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 1); /* 7 */
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 1); /* 8 */
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 1); /* 9 */
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 1); /* 10 */
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 1); /* 11 */
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 1); /* 12 */
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 1); /* 13 */
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 1); /* 14 */
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 1); /* 15 */
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 1); /* 16 */
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 1); /* 17 */
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 1); /* 18 */
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 1); /* 19 */
- buf += buf_stride;
- }
- for (i=0; i<nelmts; i++, buf+=buf_stride) {
- H5_SWAP_BYTES(buf, 0, 1);
- }
- break;
- case 4:
- for (/*void*/; nelmts>=20; nelmts-=20) {
- H5_SWAP_BYTES(buf, 0, 3); /* 0 */
- H5_SWAP_BYTES(buf, 1, 2);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 3); /* 1 */
- H5_SWAP_BYTES(buf, 1, 2);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 3); /* 2 */
- H5_SWAP_BYTES(buf, 1, 2);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 3); /* 3 */
- H5_SWAP_BYTES(buf, 1, 2);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 3); /* 4 */
- H5_SWAP_BYTES(buf, 1, 2);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 3); /* 5 */
- H5_SWAP_BYTES(buf, 1, 2);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 3); /* 6 */
- H5_SWAP_BYTES(buf, 1, 2);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 3); /* 7 */
- H5_SWAP_BYTES(buf, 1, 2);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 3); /* 8 */
- H5_SWAP_BYTES(buf, 1, 2);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 3); /* 9 */
- H5_SWAP_BYTES(buf, 1, 2);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 3); /* 10 */
- H5_SWAP_BYTES(buf, 1, 2);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 3); /* 11 */
- H5_SWAP_BYTES(buf, 1, 2);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 3); /* 12 */
- H5_SWAP_BYTES(buf, 1, 2);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 3); /* 13 */
- H5_SWAP_BYTES(buf, 1, 2);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 3); /* 14 */
- H5_SWAP_BYTES(buf, 1, 2);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 3); /* 15 */
- H5_SWAP_BYTES(buf, 1, 2);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 3); /* 16 */
- H5_SWAP_BYTES(buf, 1, 2);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 3); /* 17 */
- H5_SWAP_BYTES(buf, 1, 2);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 3); /* 18 */
- H5_SWAP_BYTES(buf, 1, 2);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 3); /* 19 */
- H5_SWAP_BYTES(buf, 1, 2);
- buf += buf_stride;
- }
- for (i=0; i<nelmts; i++, buf+=buf_stride) {
- H5_SWAP_BYTES(buf, 0, 3);
- H5_SWAP_BYTES(buf, 1, 2);
- }
- break;
- case 8:
- for (/*void*/; nelmts>=10; nelmts-=10) {
- H5_SWAP_BYTES(buf, 0, 7); /* 0 */
- H5_SWAP_BYTES(buf, 1, 6);
- H5_SWAP_BYTES(buf, 2, 5);
- H5_SWAP_BYTES(buf, 3, 4);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 7); /* 1 */
- H5_SWAP_BYTES(buf, 1, 6);
- H5_SWAP_BYTES(buf, 2, 5);
- H5_SWAP_BYTES(buf, 3, 4);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 7); /* 2 */
- H5_SWAP_BYTES(buf, 1, 6);
- H5_SWAP_BYTES(buf, 2, 5);
- H5_SWAP_BYTES(buf, 3, 4);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 7); /* 3 */
- H5_SWAP_BYTES(buf, 1, 6);
- H5_SWAP_BYTES(buf, 2, 5);
- H5_SWAP_BYTES(buf, 3, 4);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 7); /* 4 */
- H5_SWAP_BYTES(buf, 1, 6);
- H5_SWAP_BYTES(buf, 2, 5);
- H5_SWAP_BYTES(buf, 3, 4);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 7); /* 5 */
- H5_SWAP_BYTES(buf, 1, 6);
- H5_SWAP_BYTES(buf, 2, 5);
- H5_SWAP_BYTES(buf, 3, 4);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 7); /* 6 */
- H5_SWAP_BYTES(buf, 1, 6);
- H5_SWAP_BYTES(buf, 2, 5);
- H5_SWAP_BYTES(buf, 3, 4);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 7); /* 7 */
- H5_SWAP_BYTES(buf, 1, 6);
- H5_SWAP_BYTES(buf, 2, 5);
- H5_SWAP_BYTES(buf, 3, 4);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 7); /* 8 */
- H5_SWAP_BYTES(buf, 1, 6);
- H5_SWAP_BYTES(buf, 2, 5);
- H5_SWAP_BYTES(buf, 3, 4);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 7); /* 9 */
- H5_SWAP_BYTES(buf, 1, 6);
- H5_SWAP_BYTES(buf, 2, 5);
- H5_SWAP_BYTES(buf, 3, 4);
- buf += buf_stride;
- }
- for (i=0; i<nelmts; i++, buf+=buf_stride) {
- H5_SWAP_BYTES(buf, 0, 7);
- H5_SWAP_BYTES(buf, 1, 6);
- H5_SWAP_BYTES(buf, 2, 5);
- H5_SWAP_BYTES(buf, 3, 4);
+ case H5T_FLOAT:
+ if(src->shared->u.atomic.u.f.sign != dst->shared->u.atomic.u.f.sign ||
+ src->shared->u.atomic.u.f.epos != dst->shared->u.atomic.u.f.epos ||
+ src->shared->u.atomic.u.f.esize != dst->shared->u.atomic.u.f.esize ||
+ src->shared->u.atomic.u.f.ebias != dst->shared->u.atomic.u.f.ebias ||
+ src->shared->u.atomic.u.f.mpos != dst->shared->u.atomic.u.f.mpos ||
+ src->shared->u.atomic.u.f.msize != dst->shared->u.atomic.u.f.msize ||
+ src->shared->u.atomic.u.f.norm != dst->shared->u.atomic.u.f.norm ||
+ src->shared->u.atomic.u.f.pad != dst->shared->u.atomic.u.f.pad)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported")
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported")
}
+ cdata->need_bkg = H5T_BKG_NO;
break;
- case 16:
- for (/*void*/; nelmts>=10; nelmts-=10) {
- H5_SWAP_BYTES(buf, 0, 15); /* 0 */
- H5_SWAP_BYTES(buf, 1, 14);
- H5_SWAP_BYTES(buf, 2, 13);
- H5_SWAP_BYTES(buf, 3, 12);
- H5_SWAP_BYTES(buf, 4, 11);
- H5_SWAP_BYTES(buf, 5, 10);
- H5_SWAP_BYTES(buf, 6, 9);
- H5_SWAP_BYTES(buf, 7, 8);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 15); /* 1 */
- H5_SWAP_BYTES(buf, 1, 14);
- H5_SWAP_BYTES(buf, 2, 13);
- H5_SWAP_BYTES(buf, 3, 12);
- H5_SWAP_BYTES(buf, 4, 11);
- H5_SWAP_BYTES(buf, 5, 10);
- H5_SWAP_BYTES(buf, 6, 9);
- H5_SWAP_BYTES(buf, 7, 8);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 15); /* 2 */
- H5_SWAP_BYTES(buf, 1, 14);
- H5_SWAP_BYTES(buf, 2, 13);
- H5_SWAP_BYTES(buf, 3, 12);
- H5_SWAP_BYTES(buf, 4, 11);
- H5_SWAP_BYTES(buf, 5, 10);
- H5_SWAP_BYTES(buf, 6, 9);
- H5_SWAP_BYTES(buf, 7, 8);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 15); /* 3 */
- H5_SWAP_BYTES(buf, 1, 14);
- H5_SWAP_BYTES(buf, 2, 13);
- H5_SWAP_BYTES(buf, 3, 12);
- H5_SWAP_BYTES(buf, 4, 11);
- H5_SWAP_BYTES(buf, 5, 10);
- H5_SWAP_BYTES(buf, 6, 9);
- H5_SWAP_BYTES(buf, 7, 8);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 15); /* 4 */
- H5_SWAP_BYTES(buf, 1, 14);
- H5_SWAP_BYTES(buf, 2, 13);
- H5_SWAP_BYTES(buf, 3, 12);
- H5_SWAP_BYTES(buf, 4, 11);
- H5_SWAP_BYTES(buf, 5, 10);
- H5_SWAP_BYTES(buf, 6, 9);
- H5_SWAP_BYTES(buf, 7, 8);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 15); /* 5 */
- H5_SWAP_BYTES(buf, 1, 14);
- H5_SWAP_BYTES(buf, 2, 13);
- H5_SWAP_BYTES(buf, 3, 12);
- H5_SWAP_BYTES(buf, 4, 11);
- H5_SWAP_BYTES(buf, 5, 10);
- H5_SWAP_BYTES(buf, 6, 9);
- H5_SWAP_BYTES(buf, 7, 8);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 15); /* 6 */
- H5_SWAP_BYTES(buf, 1, 14);
- H5_SWAP_BYTES(buf, 2, 13);
- H5_SWAP_BYTES(buf, 3, 12);
- H5_SWAP_BYTES(buf, 4, 11);
- H5_SWAP_BYTES(buf, 5, 10);
- H5_SWAP_BYTES(buf, 6, 9);
- H5_SWAP_BYTES(buf, 7, 8);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 15); /* 7 */
- H5_SWAP_BYTES(buf, 1, 14);
- H5_SWAP_BYTES(buf, 2, 13);
- H5_SWAP_BYTES(buf, 3, 12);
- H5_SWAP_BYTES(buf, 4, 11);
- H5_SWAP_BYTES(buf, 5, 10);
- H5_SWAP_BYTES(buf, 6, 9);
- H5_SWAP_BYTES(buf, 7, 8);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 15); /* 8 */
- H5_SWAP_BYTES(buf, 1, 14);
- H5_SWAP_BYTES(buf, 2, 13);
- H5_SWAP_BYTES(buf, 3, 12);
- H5_SWAP_BYTES(buf, 4, 11);
- H5_SWAP_BYTES(buf, 5, 10);
- H5_SWAP_BYTES(buf, 6, 9);
- H5_SWAP_BYTES(buf, 7, 8);
- buf += buf_stride;
- H5_SWAP_BYTES(buf, 0, 15); /* 9 */
- H5_SWAP_BYTES(buf, 1, 14);
- H5_SWAP_BYTES(buf, 2, 13);
- H5_SWAP_BYTES(buf, 3, 12);
- H5_SWAP_BYTES(buf, 4, 11);
- H5_SWAP_BYTES(buf, 5, 10);
- H5_SWAP_BYTES(buf, 6, 9);
- H5_SWAP_BYTES(buf, 7, 8);
- buf += buf_stride;
- }
- for (i=0; i<nelmts; i++, buf+=buf_stride) {
- H5_SWAP_BYTES(buf, 0, 15);
- H5_SWAP_BYTES(buf, 1, 14);
- H5_SWAP_BYTES(buf, 2, 13);
- H5_SWAP_BYTES(buf, 3, 12);
- H5_SWAP_BYTES(buf, 4, 11);
- H5_SWAP_BYTES(buf, 5, 10);
- H5_SWAP_BYTES(buf, 6, 9);
- H5_SWAP_BYTES(buf, 7, 8);
- }
+
+ case H5T_CONV_CONV:
+ /* The conversion */
+ if(NULL == (src = H5I_object(src_id)) ||
+ NULL == (dst = H5I_object(dst_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type")
+
+ /* Check for "no op" reference conversion */
+ if(src->shared->type == H5T_REFERENCE) {
+ /* Sanity check */
+ HDassert(dst->shared->type == H5T_REFERENCE);
+
+ /* Check if we are on a little-endian machine (the order that
+ * the addresses in the file must be) and just get out now, there
+ * is no need to convert the object reference. Yes, this is
+ * icky and non-portable, but I can't think of a better way to
+ * support allowing the objno in the H5O_info_t struct and the
+ * hobj_ref_t type to be compared directly without introducing a
+ * "native" hobj_ref_t datatype and I think that would break a
+ * lot of existing programs. -QAK
+ */
+ if(H5T_native_order_g == H5T_ORDER_LE)
+ break;
+ } /* end if */
+
+ buf_stride = buf_stride ? buf_stride : src->shared->size;
+ switch(src->shared->size) {
+ case 1:
+ /*no-op*/
+ break;
+
+ case 2:
+ for(/*void*/; nelmts >= 20; nelmts -= 20) {
+ H5_SWAP_BYTES(buf, 0, 1); /* 0 */
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 1); /* 1 */
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 1); /* 2 */
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 1); /* 3 */
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 1); /* 4 */
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 1); /* 5 */
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 1); /* 6 */
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 1); /* 7 */
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 1); /* 8 */
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 1); /* 9 */
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 1); /* 10 */
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 1); /* 11 */
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 1); /* 12 */
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 1); /* 13 */
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 1); /* 14 */
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 1); /* 15 */
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 1); /* 16 */
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 1); /* 17 */
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 1); /* 18 */
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 1); /* 19 */
+ buf += buf_stride;
+ } /* end for */
+ for(i = 0; i < nelmts; i++, buf += buf_stride)
+ H5_SWAP_BYTES(buf, 0, 1);
+ break;
+
+ case 4:
+ for(/*void*/; nelmts >= 20; nelmts -= 20) {
+ H5_SWAP_BYTES(buf, 0, 3); /* 0 */
+ H5_SWAP_BYTES(buf, 1, 2);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 3); /* 1 */
+ H5_SWAP_BYTES(buf, 1, 2);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 3); /* 2 */
+ H5_SWAP_BYTES(buf, 1, 2);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 3); /* 3 */
+ H5_SWAP_BYTES(buf, 1, 2);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 3); /* 4 */
+ H5_SWAP_BYTES(buf, 1, 2);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 3); /* 5 */
+ H5_SWAP_BYTES(buf, 1, 2);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 3); /* 6 */
+ H5_SWAP_BYTES(buf, 1, 2);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 3); /* 7 */
+ H5_SWAP_BYTES(buf, 1, 2);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 3); /* 8 */
+ H5_SWAP_BYTES(buf, 1, 2);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 3); /* 9 */
+ H5_SWAP_BYTES(buf, 1, 2);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 3); /* 10 */
+ H5_SWAP_BYTES(buf, 1, 2);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 3); /* 11 */
+ H5_SWAP_BYTES(buf, 1, 2);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 3); /* 12 */
+ H5_SWAP_BYTES(buf, 1, 2);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 3); /* 13 */
+ H5_SWAP_BYTES(buf, 1, 2);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 3); /* 14 */
+ H5_SWAP_BYTES(buf, 1, 2);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 3); /* 15 */
+ H5_SWAP_BYTES(buf, 1, 2);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 3); /* 16 */
+ H5_SWAP_BYTES(buf, 1, 2);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 3); /* 17 */
+ H5_SWAP_BYTES(buf, 1, 2);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 3); /* 18 */
+ H5_SWAP_BYTES(buf, 1, 2);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 3); /* 19 */
+ H5_SWAP_BYTES(buf, 1, 2);
+ buf += buf_stride;
+ } /* end for */
+ for(i = 0; i < nelmts; i++, buf += buf_stride) {
+ H5_SWAP_BYTES(buf, 0, 3);
+ H5_SWAP_BYTES(buf, 1, 2);
+ } /* end for */
+ break;
+
+ case 8:
+ for(/*void*/; nelmts >= 10; nelmts -= 10) {
+ H5_SWAP_BYTES(buf, 0, 7); /* 0 */
+ H5_SWAP_BYTES(buf, 1, 6);
+ H5_SWAP_BYTES(buf, 2, 5);
+ H5_SWAP_BYTES(buf, 3, 4);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 7); /* 1 */
+ H5_SWAP_BYTES(buf, 1, 6);
+ H5_SWAP_BYTES(buf, 2, 5);
+ H5_SWAP_BYTES(buf, 3, 4);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 7); /* 2 */
+ H5_SWAP_BYTES(buf, 1, 6);
+ H5_SWAP_BYTES(buf, 2, 5);
+ H5_SWAP_BYTES(buf, 3, 4);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 7); /* 3 */
+ H5_SWAP_BYTES(buf, 1, 6);
+ H5_SWAP_BYTES(buf, 2, 5);
+ H5_SWAP_BYTES(buf, 3, 4);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 7); /* 4 */
+ H5_SWAP_BYTES(buf, 1, 6);
+ H5_SWAP_BYTES(buf, 2, 5);
+ H5_SWAP_BYTES(buf, 3, 4);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 7); /* 5 */
+ H5_SWAP_BYTES(buf, 1, 6);
+ H5_SWAP_BYTES(buf, 2, 5);
+ H5_SWAP_BYTES(buf, 3, 4);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 7); /* 6 */
+ H5_SWAP_BYTES(buf, 1, 6);
+ H5_SWAP_BYTES(buf, 2, 5);
+ H5_SWAP_BYTES(buf, 3, 4);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 7); /* 7 */
+ H5_SWAP_BYTES(buf, 1, 6);
+ H5_SWAP_BYTES(buf, 2, 5);
+ H5_SWAP_BYTES(buf, 3, 4);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 7); /* 8 */
+ H5_SWAP_BYTES(buf, 1, 6);
+ H5_SWAP_BYTES(buf, 2, 5);
+ H5_SWAP_BYTES(buf, 3, 4);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 7); /* 9 */
+ H5_SWAP_BYTES(buf, 1, 6);
+ H5_SWAP_BYTES(buf, 2, 5);
+ H5_SWAP_BYTES(buf, 3, 4);
+ buf += buf_stride;
+ } /* end for */
+ for(i = 0; i < nelmts; i++, buf += buf_stride) {
+ H5_SWAP_BYTES(buf, 0, 7);
+ H5_SWAP_BYTES(buf, 1, 6);
+ H5_SWAP_BYTES(buf, 2, 5);
+ H5_SWAP_BYTES(buf, 3, 4);
+ } /* end for */
+ break;
+
+ case 16:
+ for(/*void*/; nelmts >= 10; nelmts -= 10) {
+ H5_SWAP_BYTES(buf, 0, 15); /* 0 */
+ H5_SWAP_BYTES(buf, 1, 14);
+ H5_SWAP_BYTES(buf, 2, 13);
+ H5_SWAP_BYTES(buf, 3, 12);
+ H5_SWAP_BYTES(buf, 4, 11);
+ H5_SWAP_BYTES(buf, 5, 10);
+ H5_SWAP_BYTES(buf, 6, 9);
+ H5_SWAP_BYTES(buf, 7, 8);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 15); /* 1 */
+ H5_SWAP_BYTES(buf, 1, 14);
+ H5_SWAP_BYTES(buf, 2, 13);
+ H5_SWAP_BYTES(buf, 3, 12);
+ H5_SWAP_BYTES(buf, 4, 11);
+ H5_SWAP_BYTES(buf, 5, 10);
+ H5_SWAP_BYTES(buf, 6, 9);
+ H5_SWAP_BYTES(buf, 7, 8);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 15); /* 2 */
+ H5_SWAP_BYTES(buf, 1, 14);
+ H5_SWAP_BYTES(buf, 2, 13);
+ H5_SWAP_BYTES(buf, 3, 12);
+ H5_SWAP_BYTES(buf, 4, 11);
+ H5_SWAP_BYTES(buf, 5, 10);
+ H5_SWAP_BYTES(buf, 6, 9);
+ H5_SWAP_BYTES(buf, 7, 8);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 15); /* 3 */
+ H5_SWAP_BYTES(buf, 1, 14);
+ H5_SWAP_BYTES(buf, 2, 13);
+ H5_SWAP_BYTES(buf, 3, 12);
+ H5_SWAP_BYTES(buf, 4, 11);
+ H5_SWAP_BYTES(buf, 5, 10);
+ H5_SWAP_BYTES(buf, 6, 9);
+ H5_SWAP_BYTES(buf, 7, 8);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 15); /* 4 */
+ H5_SWAP_BYTES(buf, 1, 14);
+ H5_SWAP_BYTES(buf, 2, 13);
+ H5_SWAP_BYTES(buf, 3, 12);
+ H5_SWAP_BYTES(buf, 4, 11);
+ H5_SWAP_BYTES(buf, 5, 10);
+ H5_SWAP_BYTES(buf, 6, 9);
+ H5_SWAP_BYTES(buf, 7, 8);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 15); /* 5 */
+ H5_SWAP_BYTES(buf, 1, 14);
+ H5_SWAP_BYTES(buf, 2, 13);
+ H5_SWAP_BYTES(buf, 3, 12);
+ H5_SWAP_BYTES(buf, 4, 11);
+ H5_SWAP_BYTES(buf, 5, 10);
+ H5_SWAP_BYTES(buf, 6, 9);
+ H5_SWAP_BYTES(buf, 7, 8);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 15); /* 6 */
+ H5_SWAP_BYTES(buf, 1, 14);
+ H5_SWAP_BYTES(buf, 2, 13);
+ H5_SWAP_BYTES(buf, 3, 12);
+ H5_SWAP_BYTES(buf, 4, 11);
+ H5_SWAP_BYTES(buf, 5, 10);
+ H5_SWAP_BYTES(buf, 6, 9);
+ H5_SWAP_BYTES(buf, 7, 8);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 15); /* 7 */
+ H5_SWAP_BYTES(buf, 1, 14);
+ H5_SWAP_BYTES(buf, 2, 13);
+ H5_SWAP_BYTES(buf, 3, 12);
+ H5_SWAP_BYTES(buf, 4, 11);
+ H5_SWAP_BYTES(buf, 5, 10);
+ H5_SWAP_BYTES(buf, 6, 9);
+ H5_SWAP_BYTES(buf, 7, 8);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 15); /* 8 */
+ H5_SWAP_BYTES(buf, 1, 14);
+ H5_SWAP_BYTES(buf, 2, 13);
+ H5_SWAP_BYTES(buf, 3, 12);
+ H5_SWAP_BYTES(buf, 4, 11);
+ H5_SWAP_BYTES(buf, 5, 10);
+ H5_SWAP_BYTES(buf, 6, 9);
+ H5_SWAP_BYTES(buf, 7, 8);
+ buf += buf_stride;
+ H5_SWAP_BYTES(buf, 0, 15); /* 9 */
+ H5_SWAP_BYTES(buf, 1, 14);
+ H5_SWAP_BYTES(buf, 2, 13);
+ H5_SWAP_BYTES(buf, 3, 12);
+ H5_SWAP_BYTES(buf, 4, 11);
+ H5_SWAP_BYTES(buf, 5, 10);
+ H5_SWAP_BYTES(buf, 6, 9);
+ H5_SWAP_BYTES(buf, 7, 8);
+ buf += buf_stride;
+ } /* end for */
+ for(i = 0; i < nelmts; i++, buf += buf_stride) {
+ H5_SWAP_BYTES(buf, 0, 15);
+ H5_SWAP_BYTES(buf, 1, 14);
+ H5_SWAP_BYTES(buf, 2, 13);
+ H5_SWAP_BYTES(buf, 3, 12);
+ H5_SWAP_BYTES(buf, 4, 11);
+ H5_SWAP_BYTES(buf, 5, 10);
+ H5_SWAP_BYTES(buf, 6, 9);
+ H5_SWAP_BYTES(buf, 7, 8);
+ } /* end for */
+ break;
+ } /* end switch */
break;
- }
- break;
- case H5T_CONV_FREE:
- /* Free private data */
- break;
+ case H5T_CONV_FREE:
+ /* Free private data */
+ break;
- default:
- HGOTO_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command");
- }
+ default:
+ HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command")
+ } /* end switch */
done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T_conv_order_opt() */
/*-------------------------------------------------------------------------
@@ -1368,73 +1439,72 @@ H5T_conv_order(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
H5T_t *dst = NULL;
size_t i;
size_t j, md;
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_order, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_order, FAIL)
- switch (cdata->command) {
- case H5T_CONV_INIT:
- /* Capability query */
- if (NULL == (src = H5I_object(src_id)) ||
- NULL == (dst = H5I_object(dst_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
- if (src->shared->size != dst->shared->size || 0 != src->shared->u.atomic.offset ||
- 0 != dst->shared->u.atomic.offset ||
- !((H5T_ORDER_BE == src->shared->u.atomic.order &&
- H5T_ORDER_LE == dst->shared->u.atomic.order) ||
- (H5T_ORDER_LE == src->shared->u.atomic.order &&
- H5T_ORDER_BE == dst->shared->u.atomic.order)))
- HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported");
- switch (src->shared->type) {
- case H5T_INTEGER:
- case H5T_BITFIELD:
- /* nothing to check */
- break;
-
- case H5T_FLOAT:
- if (src->shared->u.atomic.u.f.sign != dst->shared->u.atomic.u.f.sign ||
- src->shared->u.atomic.u.f.epos != dst->shared->u.atomic.u.f.epos ||
- src->shared->u.atomic.u.f.esize != dst->shared->u.atomic.u.f.esize ||
- src->shared->u.atomic.u.f.ebias != dst->shared->u.atomic.u.f.ebias ||
- src->shared->u.atomic.u.f.mpos != dst->shared->u.atomic.u.f.mpos ||
- src->shared->u.atomic.u.f.msize != dst->shared->u.atomic.u.f.msize ||
- src->shared->u.atomic.u.f.norm != dst->shared->u.atomic.u.f.norm ||
- src->shared->u.atomic.u.f.pad != dst->shared->u.atomic.u.f.pad) {
- HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported");
- }
- break;
+ switch(cdata->command) {
+ case H5T_CONV_INIT:
+ /* Capability query */
+ if(NULL == (src = H5I_object(src_id)) ||
+ NULL == (dst = H5I_object(dst_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type")
+ if(src->shared->size != dst->shared->size || 0 != src->shared->u.atomic.offset ||
+ 0 != dst->shared->u.atomic.offset ||
+ !((H5T_ORDER_BE == src->shared->u.atomic.order &&
+ H5T_ORDER_LE == dst->shared->u.atomic.order) ||
+ (H5T_ORDER_LE == src->shared->u.atomic.order &&
+ H5T_ORDER_BE == dst->shared->u.atomic.order)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported")
+ switch(src->shared->type) {
+ case H5T_INTEGER:
+ case H5T_BITFIELD:
+ /* nothing to check */
+ break;
- default:
- HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported");
- }
- cdata->need_bkg = H5T_BKG_NO;
- break;
-
- case H5T_CONV_CONV:
- /* The conversion */
- if (NULL == (src = H5I_object(src_id)) ||
- NULL == (dst = H5I_object(dst_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
-
- buf_stride = buf_stride ? buf_stride : src->shared->size;
- md = src->shared->size / 2;
- for (i=0; i<nelmts; i++, buf+=buf_stride) {
- for (j=0; j<md; j++)
- H5_SWAP_BYTES(buf, j, src->shared->size-(j+1));
- }
- break;
+ case H5T_FLOAT:
+ if(src->shared->u.atomic.u.f.sign != dst->shared->u.atomic.u.f.sign ||
+ src->shared->u.atomic.u.f.epos != dst->shared->u.atomic.u.f.epos ||
+ src->shared->u.atomic.u.f.esize != dst->shared->u.atomic.u.f.esize ||
+ src->shared->u.atomic.u.f.ebias != dst->shared->u.atomic.u.f.ebias ||
+ src->shared->u.atomic.u.f.mpos != dst->shared->u.atomic.u.f.mpos ||
+ src->shared->u.atomic.u.f.msize != dst->shared->u.atomic.u.f.msize ||
+ src->shared->u.atomic.u.f.norm != dst->shared->u.atomic.u.f.norm ||
+ src->shared->u.atomic.u.f.pad != dst->shared->u.atomic.u.f.pad) {
+ HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported")
+ } /* end if */
+ break;
- case H5T_CONV_FREE:
- /* Free private data */
- break;
+ default:
+ HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported")
+ } /* end switch */
+ cdata->need_bkg = H5T_BKG_NO;
+ break;
- default:
- HGOTO_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command");
- }
+ case H5T_CONV_CONV:
+ /* The conversion */
+ if(NULL == (src = H5I_object(src_id)) ||
+ NULL == (dst = H5I_object(dst_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type")
+
+ buf_stride = buf_stride ? buf_stride : src->shared->size;
+ md = src->shared->size / 2;
+ for(i = 0; i < nelmts; i++, buf += buf_stride)
+ for(j = 0; j < md; j++)
+ H5_SWAP_BYTES(buf, j, src->shared->size - (j + 1));
+ break;
+
+ case H5T_CONV_FREE:
+ /* Free private data */
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command")
+ } /* end switch */
done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T_conv_order() */
/*-------------------------------------------------------------------------
@@ -1461,7 +1531,7 @@ H5T_conv_b_b(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
void UNUSED *background, hid_t dxpl_id)
{
uint8_t *buf = (uint8_t*)_buf;
- H5T_t *src=NULL, *dst=NULL; /*source and dest data types */
+ H5T_t *src = NULL, *dst = NULL; /*source and dest data types */
int direction; /*direction of traversal */
size_t elmtno; /*element number */
size_t olap; /*num overlapping elements */
@@ -1472,25 +1542,25 @@ H5T_conv_b_b(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
size_t i;
uint8_t *src_rev=NULL; /*order-reversed source buffer */
H5P_genplist_t *plist; /*property list pointer */
- H5T_conv_cb_t cb_struct={NULL, NULL}; /*conversion callback structure */
+ H5T_conv_cb_t cb_struct = {NULL, NULL}; /*conversion callback structure */
H5T_conv_ret_t except_ret; /*return of callback function */
hbool_t reverse; /*if reverse the order of destination */
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_b_b, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_b_b, FAIL)
switch(cdata->command) {
case H5T_CONV_INIT:
/* Capability query */
- if (NULL == (src = H5I_object(src_id)) ||
+ if(NULL == (src = H5I_object(src_id)) ||
NULL == (dst = H5I_object(dst_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
- if (H5T_ORDER_LE!=src->shared->u.atomic.order &&
- H5T_ORDER_BE!=src->shared->u.atomic.order)
- HGOTO_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported byte order");
- if (H5T_ORDER_LE!=dst->shared->u.atomic.order &&
- H5T_ORDER_BE!=dst->shared->u.atomic.order)
- HGOTO_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported byte order");
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type")
+ if(H5T_ORDER_LE != src->shared->u.atomic.order &&
+ H5T_ORDER_BE != src->shared->u.atomic.order)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported byte order")
+ if(H5T_ORDER_LE != dst->shared->u.atomic.order &&
+ H5T_ORDER_BE != dst->shared->u.atomic.order)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported byte order")
cdata->need_bkg = H5T_BKG_NO;
break;
@@ -1499,29 +1569,29 @@ H5T_conv_b_b(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
case H5T_CONV_CONV:
/* Get the data types */
- if (NULL==(src=H5I_object(src_id)) ||
- NULL==(dst=H5I_object(dst_id)))
- HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
+ if(NULL == (src = H5I_object(src_id)) ||
+ NULL == (dst = H5I_object(dst_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type")
/*
* Do we process the values from beginning to end or vice versa? Also,
* how many of the elements have the source and destination areas
* overlapping?
*/
- if (src->shared->size==dst->shared->size || buf_stride) {
+ if(src->shared->size == dst->shared->size || buf_stride) {
sp = dp = (uint8_t*)buf;
direction = 1;
olap = nelmts;
- } else if (src->shared->size>=dst->shared->size) {
- double olap_d = HDceil((double)(dst->shared->size)/
- (double)(src->shared->size-dst->shared->size));
+ } else if(src->shared->size >= dst->shared->size) {
+ double olap_d = HDceil((double)(dst->shared->size) /
+ (double)(src->shared->size - dst->shared->size));
olap = (size_t)olap_d;
sp = dp = (uint8_t*)buf;
direction = 1;
} else {
- double olap_d = HDceil((double)(src->shared->size)/
- (double)(dst->shared->size-src->shared->size));
+ double olap_d = HDceil((double)(src->shared->size) /
+ (double)(dst->shared->size - src->shared->size));
olap = (size_t)olap_d;
sp = (uint8_t*)buf + (nelmts-1) * src->shared->size;
dp = (uint8_t*)buf + (nelmts-1) * dst->shared->size;
@@ -1529,39 +1599,39 @@ H5T_conv_b_b(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
}
/* Get the plist structure */
- if(NULL == (plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER)))
- HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find property list for ID");
+ if(NULL == (plist = H5P_object_verify(dxpl_id, H5P_DATASET_XFER)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find property list for ID")
/* Get conversion exception callback property */
- if (H5P_get(plist,H5D_XFER_CONV_CB_NAME,&cb_struct)<0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get conversion exception callback");
+ if(H5P_get(plist, H5D_XFER_CONV_CB_NAME, &cb_struct) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get conversion exception callback")
/* Allocate space for order-reversed source buffer */
- src_rev = (uint8_t*)H5MM_calloc(src->shared->size);
+ src_rev = (uint8_t *)H5MM_calloc(src->shared->size);
/* The conversion loop */
- for (elmtno=0; elmtno<nelmts; elmtno++) {
+ for(elmtno = 0; elmtno < nelmts; elmtno++) {
/*
* If the source and destination buffers overlap then use a
* temporary buffer for the destination.
*/
- if (direction>0) {
+ if(direction > 0) {
s = sp;
- d = elmtno<olap ? dbuf : dp;
- } else {
+ d = elmtno < olap ? dbuf : dp;
+ } /* end if */
+ else {
s = sp;
- d = elmtno+olap >= nelmts ? dbuf : dp;
- }
+ d = (elmtno + olap) >= nelmts ? dbuf : dp;
+ } /* end else */
#ifndef NDEBUG
/* I don't quite trust the overlap calculations yet --rpm */
- if (d==dbuf) {
- assert ((dp>=sp && dp<sp+src->shared->size) ||
- (sp>=dp && sp<dp+dst->shared->size));
- } else {
- assert ((dp<sp && dp+dst->shared->size<=sp) ||
- (sp<dp && sp+src->shared->size<=dp));
- }
+ if(d == dbuf)
+ HDassert((dp >= sp && dp < sp + src->shared->size) ||
+ (sp >= dp && sp < dp + dst->shared->size));
+ else
+ HDassert((dp < sp && dp + dst->shared->size<=sp) ||
+ (sp < dp && sp + src->shared->size<=dp));
#endif
/*
@@ -1569,14 +1639,14 @@ H5T_conv_b_b(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
* complicated. We'll do all the conversion stuff assuming
* little endian and then we'll fix the order at the end.
*/
- if (H5T_ORDER_BE==src->shared->u.atomic.order) {
- half_size = src->shared->size/2;
- for (i=0; i<half_size; i++) {
- uint8_t tmp = s[src->shared->size-(i+1)];
- s[src->shared->size-(i+1)] = s[i];
+ if(H5T_ORDER_BE == src->shared->u.atomic.order) {
+ half_size = src->shared->size / 2;
+ for(i = 0; i < half_size; i++) {
+ uint8_t tmp = s[src->shared->size - (i + 1)];
+ s[src->shared->size - (i + 1)] = s[i];
s[i] = tmp;
- }
- }
+ } /* end for */
+ } /* end if */
/* Initiate these variables */
except_ret = H5T_CONV_UNHANDLED;
@@ -1587,13 +1657,13 @@ H5T_conv_b_b(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
* than the destination then invoke the overflow function or copy
* as many bits as possible. Zero extra bits in the destination.
*/
- if (src->shared->u.atomic.prec>dst->shared->u.atomic.prec) {
+ if(src->shared->u.atomic.prec > dst->shared->u.atomic.prec) {
/*overflow*/
if(cb_struct.func) { /*If user's exception handler is present, use it*/
H5T_reverse_order(src_rev, s, src->shared->size, src->shared->u.atomic.order); /*reverse order first*/
except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, src_id, dst_id,
src_rev, d, cb_struct.user_data);
- }
+ } /* end if */
if(except_ret == H5T_CONV_UNHANDLED) {
H5T_bit_copy(d, dst->shared->u.atomic.offset,
@@ -1614,67 +1684,112 @@ H5T_conv_b_b(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
/*
* Fill the destination padding areas.
*/
- switch (dst->shared->u.atomic.lsb_pad) {
+ switch(dst->shared->u.atomic.lsb_pad) {
case H5T_PAD_ZERO:
H5T_bit_set(d, (size_t)0, dst->shared->u.atomic.offset, FALSE);
break;
+
case H5T_PAD_ONE:
H5T_bit_set(d, (size_t)0, dst->shared->u.atomic.offset, TRUE);
break;
+
default:
- HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported LSB padding");
- }
+ HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported LSB padding")
+ } /* end switch */
msb_pad_offset = dst->shared->u.atomic.offset + dst->shared->u.atomic.prec;
- switch (dst->shared->u.atomic.msb_pad) {
+ switch(dst->shared->u.atomic.msb_pad) {
case H5T_PAD_ZERO:
- H5T_bit_set(d, msb_pad_offset, 8*dst->shared->size-msb_pad_offset,
- FALSE);
+ H5T_bit_set(d, msb_pad_offset, 8 * dst->shared->size - msb_pad_offset, FALSE);
break;
+
case H5T_PAD_ONE:
- H5T_bit_set(d, msb_pad_offset, 8*dst->shared->size-msb_pad_offset,
- TRUE);
+ H5T_bit_set(d, msb_pad_offset, 8 * dst->shared->size - msb_pad_offset, TRUE);
break;
default:
- HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported MSB padding");
- }
+ HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported MSB padding")
+ } /* end switch */
/*
* Put the destination in the correct byte order. See note at
* beginning of loop.
*/
- if (H5T_ORDER_BE==dst->shared->u.atomic.order && reverse) {
- half_size = dst->shared->size/2;
- for (i=0; i<half_size; i++) {
- uint8_t tmp = d[dst->shared->size-(i+1)];
- d[dst->shared->size-(i+1)] = d[i];
+ if(H5T_ORDER_BE == dst->shared->u.atomic.order && reverse) {
+ half_size = dst->shared->size / 2;
+ for(i = 0; i < half_size; i++) {
+ uint8_t tmp = d[dst->shared->size - (i + 1)];
+ d[dst->shared->size - (i + 1)] = d[i];
d[i] = tmp;
- }
- }
+ } /* end for */
+ } /* end if */
/*
* If we had used a temporary buffer for the destination then we
* should copy the value to the true destination buffer.
*/
- if (d==dbuf) HDmemcpy (dp, d, dst->shared->size);
- if (buf_stride) {
+ if(d == dbuf)
+ HDmemcpy(dp, d, dst->shared->size);
+ if(buf_stride) {
sp += direction * buf_stride;
dp += direction * buf_stride;
- } else {
+ } /* end if */
+ else {
sp += direction * src->shared->size;
dp += direction * dst->shared->size;
- }
- }
+ } /* end else */
+ } /* end for */
break;
default:
- HGOTO_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command");
- }
+ HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command")
+ } /* end switch */
done:
if(src_rev)
H5MM_free(src_rev);
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T_conv_b_b() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5T_conv_struct_free
+ *
+ * Purpose: Free the private data structure used by the compound
+ * conversion functions.
+ *
+ * Return: The result of H5MM_xfree(priv) (NULL)
+ *
+ * Programmer: Neil Fortner
+ * Wednesday, October 1, 2008
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5T_conv_struct_t *
+H5T_conv_struct_free(H5T_conv_struct_t *priv)
+{
+ int *src2dst = priv->src2dst;
+ hid_t *src_memb_id = priv->src_memb_id,
+ *dst_memb_id = priv->dst_memb_id;
+ unsigned i;
+ int status;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_conv_struct_free)
+
+ for (i=0; i<priv->src_nmembs; i++)
+ if (src2dst[i] >= 0) {
+ status = H5I_dec_ref(src_memb_id[i], FALSE);
+ HDassert(status >= 0);
+ status = H5I_dec_ref(dst_memb_id[src2dst[i]], FALSE);
+ HDassert(status >= 0);
+ }
+
+ H5MM_xfree(src2dst);
+ H5MM_xfree(src_memb_id);
+ H5MM_xfree(dst_memb_id);
+ H5MM_xfree(priv->memb_path);
+ FUNC_LEAVE_NOAPI(H5MM_xfree(priv));
}
@@ -1688,8 +1803,8 @@ done:
*
* Priv fields are indexed by source member number or
* destination member number depending on whether the field
- * contains information about the source data type or the
- * destination data type (fields that contains the same
+ * contains information about the source datatype or the
+ * destination datatype (fields that contains the same
* information for both source and destination are indexed by
* source member number). The src2dst[] priv array maps source
* member numbers to destination member numbers, but if the
@@ -1703,8 +1818,8 @@ done:
*
* Modifications:
* Raymond Lu, 3 May 2007
- * Added the detection for a special optimization case when the
- * source and destination members are a subset of each other, and
+ * Added the detection for a special optimization case when the
+ * source and destination members are a subset of each other, and
* the order is the same, and no conversion is needed. For example:
* struct source { struct destination {
* TYPE1 A; --> TYPE1 A;
@@ -1721,13 +1836,13 @@ done:
* }; TYPE4 D;
* TYPE5 E;
* };
- * The optimization is simply moving data to the appropriate
+ * The optimization is simply moving data to the appropriate
* places in the buffer.
- *
+ *
*-------------------------------------------------------------------------
*/
static herr_t
-H5T_conv_struct_init (H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, hid_t dxpl_id)
+H5T_conv_struct_init(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, hid_t dxpl_id)
{
H5T_conv_struct_t *priv = (H5T_conv_struct_t*)(cdata->priv);
int *src2dst = NULL;
@@ -1737,25 +1852,27 @@ H5T_conv_struct_init (H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, hid_t dxpl_id)
hid_t tid;
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5T_conv_struct_init);
+ FUNC_ENTER_NOAPI_NOINIT(H5T_conv_struct_init)
src_nmembs = src->shared->u.compnd.nmembs;
dst_nmembs = dst->shared->u.compnd.nmembs;
- if (!priv) {
+ if(!priv) {
/*
* Allocate private data structure and arrays.
*/
- if (NULL==(priv=cdata->priv=H5MM_calloc(sizeof(H5T_conv_struct_t))) ||
- NULL==(priv->src2dst=H5MM_malloc(src_nmembs * sizeof(int))) ||
- NULL==(priv->src_memb_id=H5MM_malloc(src_nmembs * sizeof(hid_t))) ||
- NULL==(priv->dst_memb_id=H5MM_malloc(dst_nmembs * sizeof(hid_t))))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
+ if(NULL == (priv = cdata->priv=H5MM_calloc(sizeof(H5T_conv_struct_t))) ||
+ NULL == (priv->src2dst = H5MM_malloc(src_nmembs * sizeof(int))) ||
+ NULL == (priv->src_memb_id = H5MM_malloc(src_nmembs * sizeof(hid_t))) ||
+ NULL == (priv->dst_memb_id = H5MM_malloc(dst_nmembs * sizeof(hid_t))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
src2dst = priv->src2dst;
+ priv->src_nmembs = src_nmembs;
/* The flag of special optimization to indicate if source members and destination
* members are a subset of each other. Initialize it to FALSE */
- priv->smembs_subset = H5T_SUBSET_FALSE;
+ priv->subset_info.subset = H5T_SUBSET_FALSE;
+ priv->subset_info.copy_size = 0;
/*
* Insure that members are sorted.
@@ -1767,32 +1884,30 @@ H5T_conv_struct_init (H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, hid_t dxpl_id)
* Build a mapping from source member number to destination member
* number. If some source member is not a destination member then that
* mapping element will be negative. Also create atoms for each
- * source and destination member data type so we can look up the
- * member data type conversion functions later.
+ * source and destination member datatype so we can look up the
+ * member datatype conversion functions later.
*/
- for (i=0; i<src_nmembs; i++) {
+ for(i = 0; i < src_nmembs; i++) {
src2dst[i] = -1;
- for (j=0; j<dst_nmembs; j++) {
- if (!HDstrcmp (src->shared->u.compnd.memb[i].name,
- dst->shared->u.compnd.memb[j].name)) {
+ for(j = 0; j < dst_nmembs; j++) {
+ if(!HDstrcmp(src->shared->u.compnd.memb[i].name, dst->shared->u.compnd.memb[j].name)) {
src2dst[i] = j;
break;
- }
- }
- if (src2dst[i]>=0) {
- type = H5T_copy (src->shared->u.compnd.memb[i].type, H5T_COPY_ALL);
- tid = H5I_register (H5I_DATATYPE, type);
- assert (tid>=0);
+ } /* end if */
+ } /* end for */
+ if(src2dst[i] >= 0) {
+ type = H5T_copy(src->shared->u.compnd.memb[i].type, H5T_COPY_ALL);
+ tid = H5I_register(H5I_DATATYPE, type, FALSE);
+ HDassert(tid>=0);
priv->src_memb_id[i] = tid;
- type = H5T_copy (dst->shared->u.compnd.memb[src2dst[i]].type,
- H5T_COPY_ALL);
- tid = H5I_register (H5I_DATATYPE, type);
- assert (tid>=0);
+ type = H5T_copy(dst->shared->u.compnd.memb[src2dst[i]].type, H5T_COPY_ALL);
+ tid = H5I_register(H5I_DATATYPE, type, FALSE);
+ HDassert(tid >= 0);
priv->dst_memb_id[src2dst[i]] = tid;
- }
- }
- }
+ } /* end if */
+ } /* end for */
+ } /* end if */
else {
/* Restore sorted conditions for the datatypes */
/* (Required for the src2dst array to be valid) */
@@ -1806,61 +1921,71 @@ H5T_conv_struct_init (H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, hid_t dxpl_id)
*/
src2dst = priv->src2dst;
H5MM_xfree(priv->memb_path);
- if (NULL==(priv->memb_path=H5MM_malloc(src->shared->u.compnd.nmembs *
- sizeof(H5T_path_t*))))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
+ if(NULL == (priv->memb_path = H5MM_malloc(src->shared->u.compnd.nmembs * sizeof(H5T_path_t*))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
- for (i=0; i<src_nmembs; i++) {
- if (src2dst[i]>=0) {
- H5T_path_t *tpath = H5T_path_find(src->shared->u.compnd.memb[i].type,
- dst->shared->u.compnd.memb[src2dst[i]].type, NULL, NULL, dxpl_id, FALSE);
+ for(i = 0; i < src_nmembs; i++) {
+ if(src2dst[i] >= 0) {
+ H5T_path_t *tpath = H5T_path_find(src->shared->u.compnd.memb[i].type, dst->shared->u.compnd.memb[src2dst[i]].type, NULL, NULL, dxpl_id, FALSE);
- if (NULL==(priv->memb_path[i] = tpath)) {
- H5MM_xfree(priv->src2dst);
- H5MM_xfree(priv->src_memb_id);
- H5MM_xfree(priv->dst_memb_id);
- H5MM_xfree(priv->memb_path);
- cdata->priv = priv = H5MM_xfree (priv);
- HGOTO_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unable to convert member data type");
- }
- }
- }
+ if(NULL == (priv->memb_path[i] = tpath)) {
+ cdata->priv = priv = H5T_conv_struct_free(priv);
+ HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unable to convert member datatype")
+ } /* end if */
+ } /* end if */
+ } /* end for */
/* Check if we need a background buffer */
- if (H5T_detect_class(src,H5T_COMPOUND)==TRUE || H5T_detect_class(dst,H5T_COMPOUND)==TRUE) {
+ if(H5T_detect_class(src, H5T_COMPOUND) == TRUE || H5T_detect_class(dst, H5T_COMPOUND) == TRUE) {
cdata->need_bkg = H5T_BKG_YES;
if(src_nmembs < dst_nmembs) {
- priv->smembs_subset = H5T_SUBSET_SRC;
- for (i=0; i<src_nmembs; i++) {
- /* If any of source members doesn't have counterpart in the same order or
- * there's conversion between members, don't do the optimization. */
- if(src2dst[i] != i || (src->shared->u.compnd.memb[i].offset !=
- dst->shared->u.compnd.memb[i].offset) || (priv->memb_path[i])->is_noop ==
- FALSE)
- priv->smembs_subset = H5T_SUBSET_FALSE;
- }
+ priv->subset_info.subset = H5T_SUBSET_SRC;
+ for(i = 0; i < src_nmembs; i++) {
+ /* If any of source members doesn't have counterpart in the same
+ * order or there's conversion between members, don't do the
+ * optimization.
+ */
+ if(src2dst[i] != i || (src->shared->u.compnd.memb[i].offset != dst->shared->u.compnd.memb[i].offset) || (priv->memb_path[i])->is_noop == FALSE) {
+ priv->subset_info.subset = H5T_SUBSET_FALSE;
+ break;
+ } /* end if */
+ } /* end for */
+ /* Compute the size of the data to be copied for each element. It
+ * may be smaller than either src or dst if there is extra space at
+ * the end of src.
+ */
+ if(priv->subset_info.subset == H5T_SUBSET_SRC)
+ priv->subset_info.copy_size = src->shared->u.compnd.memb[src_nmembs-1].offset
+ + src->shared->u.compnd.memb[src_nmembs-1].size;
} else if(dst_nmembs < src_nmembs) {
- priv->smembs_subset = H5T_SUBSET_DST;
- for (i=0; i<dst_nmembs; i++) {
+ priv->subset_info.subset = H5T_SUBSET_DST;
+ for(i = 0; i < dst_nmembs; i++) {
/* If any of source members doesn't have counterpart in the same order or
- * there's conversion between members, don't do the optimization. */
- if(src2dst[i] != i || (src->shared->u.compnd.memb[i].offset !=
- dst->shared->u.compnd.memb[i].offset) || (priv->memb_path[i])->is_noop ==
- FALSE)
- priv->smembs_subset = H5T_SUBSET_FALSE;
- }
+ * there's conversion between members, don't do the optimization. */
+ if(src2dst[i] != i || (src->shared->u.compnd.memb[i].offset != dst->shared->u.compnd.memb[i].offset) || (priv->memb_path[i])->is_noop == FALSE) {
+ priv->subset_info.subset = H5T_SUBSET_FALSE;
+ break;
+ }
+ } /* end for */
+ /* Compute the size of the data to be copied for each element. It
+ * may be smaller than either src or dst if there is extra space at
+ * the end of dst.
+ */
+ if(priv->subset_info.subset == H5T_SUBSET_DST)
+ priv->subset_info.copy_size = dst->shared->u.compnd.memb[dst_nmembs-1].offset
+ + dst->shared->u.compnd.memb[dst_nmembs-1].size;
} else /* If the numbers of source and dest members are equal and no conversion is needed,
* the case should have been handled as noop earlier in H5Dio.c. */
;
-
- }
+
+ } /* end if */
cdata->recalc = FALSE;
done:
- FUNC_LEAVE_NOAPI(ret_value);
-}
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5T_conv_struct_init() */
/*-------------------------------------------------------------------------
@@ -1868,7 +1993,7 @@ done:
*
* Purpose: A quick way to return a field in a struct private in this
* file. The flag SMEMBS_SUBSET indicates whether the source
- * members are a subset of destination or the destination
+ * members are a subset of destination or the destination
* members are a subset of the source, and the order is the
* same, and no conversion is needed. For example:
* struct source { struct destination {
@@ -1879,35 +2004,34 @@ done:
* TYPE5 E;
* };
*
- * Return: One of the value from H5T_subset_t.
+ * Return: A pointer to the subset info struct in p. Points directly
+ * into the structure.
*
* Programmer: Raymond Lu
* 8 June 2007
*
*-------------------------------------------------------------------------
*/
-H5T_subset_t
+H5T_subset_info_t *
H5T_conv_struct_subset(const H5T_cdata_t *cdata)
{
H5T_conv_struct_t *priv;
- H5T_subset_t ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_conv_struct_subset)
HDassert(cdata);
HDassert(cdata->priv);
- priv = (H5T_conv_struct_t*)(cdata->priv);
- ret_value = priv->smembs_subset;
+ priv = (H5T_conv_struct_t *)(cdata->priv);
- FUNC_LEAVE_NOAPI(ret_value)
+ FUNC_LEAVE_NOAPI((H5T_subset_info_t *) &priv->subset_info)
} /* end H5T_conv_struct_subset() */
/*-------------------------------------------------------------------------
* Function: H5T_conv_struct
*
- * Purpose: Converts between compound data types. This is a soft
+ * Purpose: Converts between compound datatypes. This is a soft
* conversion function. The algorithm is basically:
*
* For each element do
@@ -1952,8 +2076,8 @@ H5T_conv_struct(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
uint8_t *buf = (uint8_t *)_buf; /*cast for pointer arithmetic */
uint8_t *bkg = (uint8_t *)_bkg; /*background pointer arithmetic */
uint8_t *xbuf=buf, *xbkg=bkg; /*temp pointers into buf and bkg*/
- H5T_t *src = NULL; /*source data type */
- H5T_t *dst = NULL; /*destination data type */
+ H5T_t *src = NULL; /*source datatype */
+ H5T_t *dst = NULL; /*destination datatype */
int *src2dst = NULL; /*maps src member to dst member */
H5T_cmemb_t *src_memb = NULL; /*source struct member descript.*/
H5T_cmemb_t *dst_memb = NULL; /*destination struct memb desc. */
@@ -1965,7 +2089,7 @@ H5T_conv_struct(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
H5T_conv_struct_t *priv = (H5T_conv_struct_t *)(cdata->priv);
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_struct, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_struct, FAIL)
switch (cdata->command) {
case H5T_CONV_INIT:
@@ -1977,7 +2101,7 @@ H5T_conv_struct(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
*/
if (NULL == (src = H5I_object(src_id)) ||
NULL == (dst = H5I_object(dst_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
assert (H5T_COMPOUND==src->shared->type);
assert (H5T_COMPOUND==dst->shared->type);
@@ -1989,11 +2113,7 @@ H5T_conv_struct(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
/*
* Free the private conversion data.
*/
- H5MM_xfree(priv->src2dst);
- H5MM_xfree(priv->src_memb_id);
- H5MM_xfree(priv->dst_memb_id);
- H5MM_xfree(priv->memb_path);
- cdata->priv = priv = H5MM_xfree (priv);
+ cdata->priv = priv = H5T_conv_struct_free(priv);
break;
case H5T_CONV_CONV:
@@ -2002,7 +2122,7 @@ H5T_conv_struct(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
*/
if (NULL == (src = H5I_object(src_id)) ||
NULL == (dst = H5I_object(dst_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
assert (priv);
assert (bkg && cdata->need_bkg);
@@ -2054,7 +2174,7 @@ H5T_conv_struct(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
(size_t)1, (size_t)0, (size_t)0, /*no striding (packed array)*/
xbuf + src_memb->offset, xbkg + dst_memb->offset,
dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert compound data type member");
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert compound datatype member");
HDmemmove(xbuf + offset, xbuf + src_memb->offset, dst_memb->size);
offset += dst_memb->size;
} else {
@@ -2083,7 +2203,7 @@ H5T_conv_struct(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
(size_t)1, (size_t)0, (size_t)0, /*no striding (packed array)*/
xbuf + offset, xbkg + dst_memb->offset,
dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert compound data type member");
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert compound datatype member");
} else
offset -= dst_memb->size;
HDmemmove(xbkg + dst_memb->offset, xbuf + offset, dst_memb->size);
@@ -2118,14 +2238,14 @@ H5T_conv_struct(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
}
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
/*-------------------------------------------------------------------------
* Function: H5T_conv_struct_opt
*
- * Purpose: Converts between compound data types in a manner more
+ * Purpose: Converts between compound datatypes in a manner more
* efficient than the general-purpose H5T_conv_struct()
* function. This function isn't applicable if the destination
* is larger than the source type. This is a soft conversion
@@ -2175,8 +2295,8 @@ done:
* datatype.
*
* Raymond Lu, 3 May 2007
- * Optimize a special case when the source and destination members
- * are a subset of each other, and the order is the same, and no
+ * Optimize a special case when the source and destination members
+ * are a subset of each other, and the order is the same, and no
* conversion is needed. For example:
* struct source { struct destination {
* TYPE1 A; --> TYPE1 A;
@@ -2185,9 +2305,9 @@ done:
* }; TYPE4 D;
* TYPE5 E;
* };
- * The optimization is simply moving data to the appropriate
+ * The optimization is simply moving data to the appropriate
* places in the buffer.
- *
+ *
*-------------------------------------------------------------------------
*/
herr_t
@@ -2199,8 +2319,8 @@ H5T_conv_struct_opt(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
uint8_t *bkg = (uint8_t *)_bkg; /*background pointer arithmetic */
uint8_t *xbuf = NULL; /*temporary pointer into `buf' */
uint8_t *xbkg = NULL; /*temporary pointer into `bkg' */
- H5T_t *src = NULL; /*source data type */
- H5T_t *dst = NULL; /*destination data type */
+ H5T_t *src = NULL; /*source datatype */
+ H5T_t *dst = NULL; /*destination datatype */
int *src2dst = NULL; /*maps src member to dst member */
H5T_cmemb_t *src_memb = NULL; /*source struct member descript.*/
H5T_cmemb_t *dst_memb = NULL; /*destination struct memb desc. */
@@ -2213,7 +2333,7 @@ H5T_conv_struct_opt(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
hbool_t no_stride = FALSE; /*flag to indicate no stride */
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_struct_opt, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_struct_opt, FAIL)
switch (cdata->command) {
case H5T_CONV_INIT:
@@ -2225,7 +2345,7 @@ H5T_conv_struct_opt(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
*/
if (NULL == (src = H5I_object(src_id)) ||
NULL == (dst = H5I_object(dst_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
assert (H5T_COMPOUND==src->shared->type);
assert (H5T_COMPOUND==dst->shared->type);
@@ -2262,11 +2382,7 @@ H5T_conv_struct_opt(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
if (dst_memb->size > src_memb->size) {
offset -= src_memb->size;
if (dst_memb->size > src->shared->size-offset) {
- H5MM_xfree(priv->src2dst);
- H5MM_xfree(priv->src_memb_id);
- H5MM_xfree(priv->dst_memb_id);
- H5MM_xfree(priv->memb_path);
- cdata->priv = priv = H5MM_xfree (priv);
+ cdata->priv = priv = H5T_conv_struct_free(priv);
HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "convertion is unsupported by this function");
}
}
@@ -2279,11 +2395,7 @@ H5T_conv_struct_opt(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
* Free the private conversion data.
*/
priv = (H5T_conv_struct_t *)(cdata->priv);
- H5MM_xfree(priv->src2dst);
- H5MM_xfree(priv->src_memb_id);
- H5MM_xfree(priv->dst_memb_id);
- H5MM_xfree(priv->memb_path);
- cdata->priv = priv = H5MM_xfree (priv);
+ cdata->priv = priv = H5T_conv_struct_free(priv);
break;
case H5T_CONV_CONV:
@@ -2292,7 +2404,7 @@ H5T_conv_struct_opt(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
*/
if (NULL == (src = H5I_object(src_id)) ||
NULL == (dst = H5I_object(dst_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
/* Update cached data if necessary */
if (cdata->recalc && H5T_conv_struct_init (src, dst, cdata, dxpl_id)<0)
@@ -2324,25 +2436,15 @@ H5T_conv_struct_opt(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
buf_stride = src->shared->size;
}
- if(priv->smembs_subset == H5T_SUBSET_SRC || priv->smembs_subset == H5T_SUBSET_DST) {
- /* If the optimization flag is set to indicate source members are a subset and
+ if(priv->subset_info.subset == H5T_SUBSET_SRC || priv->subset_info.subset == H5T_SUBSET_DST) {
+ /* If the optimization flag is set to indicate source members are a subset and
* in the top of the destination, simply copy the source members to background buffer. */
xbuf = buf;
xbkg = bkg;
- if(dst->shared->size <= src->shared->size)
- /* This is to deal with a very special situation when the fields and their
- * offset for both source and destination are identical but the datatype
- * sizes of source and destination are different. The library still
- * considers these two types different and does conversion. It happens
- * in table API test (hdf5/hl/test/test_table.c) when a table field is
- * deleted.
- */
- copy_size = dst->shared->size;
- else
- copy_size = src->shared->size;
+ copy_size = priv->subset_info.copy_size;
for (elmtno=0; elmtno<nelmts; elmtno++) {
- HDmemmove(xbkg, xbuf, copy_size);
+ HDmemmove(xbkg, xbuf, copy_size);
/* Update pointers */
xbuf += buf_stride;
@@ -2368,7 +2470,7 @@ H5T_conv_struct_opt(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
priv->src_memb_id[u],
priv->dst_memb_id[src2dst[u]], nelmts,
buf_stride, bkg_stride, xbuf, xbkg, dxpl_id)<0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert compound data type member");
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert compound datatype member");
for (elmtno=0; elmtno<nelmts; elmtno++) {
HDmemmove(xbkg, xbuf, dst_memb->size);
xbuf += buf_stride;
@@ -2406,7 +2508,7 @@ H5T_conv_struct_opt(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
buf_stride,
bkg_stride, xbuf, xbkg,
dxpl_id)<0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert compound data type member");
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert compound datatype member");
for (elmtno=0; elmtno<nelmts; elmtno++) {
HDmemmove(xbkg, xbuf, dst_memb->size);
xbuf += buf_stride;
@@ -2433,7 +2535,7 @@ H5T_conv_struct_opt(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
}
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -2464,7 +2566,7 @@ H5T_conv_enum_init(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata)
unsigned i, j; /*counters */
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5T_conv_enum_init);
+ FUNC_ENTER_NOAPI_NOINIT(H5T_conv_enum_init)
cdata->need_bkg = H5T_BKG_NO;
if (NULL==(priv=cdata->priv=H5MM_calloc(sizeof(*priv))))
@@ -2497,7 +2599,7 @@ H5T_conv_enum_init(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata)
* value converted. However, if all of the following constraints are met
* then we can build a perfect hash table and use an O(1) lookup method.
*
- * A: The source data type size matches one of our native data type
+ * A: The source datatype size matches one of our native datatype
* sizes.
*
* B: After casting the source value bit pattern to a native type
@@ -2569,7 +2671,7 @@ done:
H5MM_xfree(priv);
cdata->priv = NULL;
}
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -2599,7 +2701,7 @@ H5T_conv_enum(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
void UNUSED *bkg, hid_t UNUSED dxpl_id)
{
uint8_t *buf = (uint8_t*)_buf; /*cast for pointer arithmetic */
- H5T_t *src=NULL, *dst=NULL; /*src and dst data types */
+ H5T_t *src=NULL, *dst=NULL; /*src and dst datatypes */
uint8_t *s=NULL, *d=NULL; /*src and dst BUF pointers */
int src_delta, dst_delta; /*conversion strides */
int n; /*src value cast as native int */
@@ -2610,7 +2712,7 @@ H5T_conv_enum(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
H5T_conv_ret_t except_ret; /*return of callback function */
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_enum, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_enum, FAIL)
switch (cdata->command) {
case H5T_CONV_INIT:
@@ -2622,7 +2724,7 @@ H5T_conv_enum(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
*/
if (NULL == (src = H5I_object(src_id)) ||
NULL == (dst = H5I_object(dst_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
assert (H5T_ENUM==src->shared->type);
assert (H5T_ENUM==dst->shared->type);
if (H5T_conv_enum_init(src, dst, cdata)<0)
@@ -2647,7 +2749,7 @@ H5T_conv_enum(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
case H5T_CONV_CONV:
if (NULL == (src = H5I_object(src_id)) ||
NULL == (dst = H5I_object(dst_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
assert (H5T_ENUM==src->shared->type);
assert (H5T_ENUM==dst->shared->type);
@@ -2754,14 +2856,14 @@ H5T_conv_enum(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
}
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
/*-------------------------------------------------------------------------
* Function: H5T_conv_vlen
*
- * Purpose: Converts between VL data types in memory and on disk.
+ * Purpose: Converts between VL datatypes in memory and on disk.
* This is a soft conversion function. The algorithm is
* basically:
*
@@ -2797,8 +2899,7 @@ done:
*/
herr_t
H5T_conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
- size_t buf_stride, size_t bkg_stride, void *buf,
- void *bkg, hid_t dxpl_id)
+ size_t buf_stride, size_t bkg_stride, void *buf, void *bkg, hid_t dxpl_id)
{
H5T_vlen_alloc_info_t _vl_alloc_info; /* VL allocation info buffer */
H5T_vlen_alloc_info_t *vl_alloc_info=&_vl_alloc_info; /* VL allocation info */
@@ -2807,8 +2908,8 @@ H5T_conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
hbool_t write_to_file=FALSE; /* Flag to indicate writing to file */
hbool_t parent_is_vlen; /* Flag to indicate parent is vlen datatyp */
hid_t tsrc_id = -1, tdst_id = -1;/*temporary type atoms */
- H5T_t *src = NULL; /*source data type */
- H5T_t *dst = NULL; /*destination data type */
+ H5T_t *src = NULL; /*source datatype */
+ H5T_t *dst = NULL; /*destination datatype */
H5HG_t bg_hobjid, parent_hobjid;
uint8_t *s; /*source buffer */
uint8_t *d; /*destination buffer */
@@ -2827,7 +2928,7 @@ H5T_conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
size_t elmtno; /*element number counter */
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_vlen, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_vlen, FAIL)
switch (cdata->command) {
case H5T_CONV_INIT:
@@ -2838,11 +2939,10 @@ H5T_conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
* information that remains (almost) constant for this
* conversion path.
*/
- if (NULL == (src = H5I_object(src_id)) ||
- NULL == (dst = H5I_object(dst_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
- assert (H5T_VLEN==src->shared->type);
- assert (H5T_VLEN==dst->shared->type);
+ if(NULL == (src = H5I_object(src_id)) || NULL == (dst = H5I_object(dst_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
+ HDassert(H5T_VLEN == src->shared->type);
+ HDassert(H5T_VLEN == dst->shared->type);
/* Variable-length types don't need a background buffer */
cdata->need_bkg = H5T_BKG_NO;
@@ -2857,66 +2957,66 @@ H5T_conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
/*
* Conversion.
*/
- if (NULL == (src = H5I_object(src_id)) ||
- NULL == (dst = H5I_object(dst_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
+ if(NULL == (src = H5I_object(src_id)) || NULL == (dst = H5I_object(dst_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
/* Initialize source & destination strides */
- if (buf_stride) {
- assert(buf_stride>=src->shared->size);
- assert(buf_stride>=dst->shared->size);
- H5_CHECK_OVERFLOW(buf_stride,size_t,ssize_t);
+ if(buf_stride) {
+ HDassert(buf_stride >= src->shared->size);
+ HDassert(buf_stride >= dst->shared->size);
+ H5_CHECK_OVERFLOW(buf_stride, size_t, ssize_t);
s_stride = d_stride = (ssize_t)buf_stride;
- } else {
- H5_CHECK_OVERFLOW(src->shared->size,size_t,ssize_t);
- H5_CHECK_OVERFLOW(dst->shared->size,size_t,ssize_t);
+ } /* end if */
+ else {
+ H5_CHECK_OVERFLOW(src->shared->size, size_t, ssize_t);
+ H5_CHECK_OVERFLOW(dst->shared->size, size_t, ssize_t);
s_stride = (ssize_t)src->shared->size;
d_stride = (ssize_t)dst->shared->size;
- }
+ } /* end else */
if(bkg) {
if(bkg_stride) {
- H5_CHECK_OVERFLOW(bkg_stride,size_t,ssize_t);
- b_stride=(ssize_t)bkg_stride;
+ H5_CHECK_OVERFLOW(bkg_stride, size_t, ssize_t);
+ b_stride = (ssize_t)bkg_stride;
} /* end if */
else
- b_stride=d_stride;
+ b_stride = d_stride;
} /* end if */
else
- b_stride=0;
+ b_stride = 0;
/* Get the size of the base types in src & dst */
- src_base_size=H5T_get_size(src->shared->parent);
- dst_base_size=H5T_get_size(dst->shared->parent);
+ src_base_size = H5T_get_size(src->shared->parent);
+ dst_base_size = H5T_get_size(dst->shared->parent);
/* Set up conversion path for base elements */
- if (NULL==(tpath=H5T_path_find(src->shared->parent, dst->shared->parent, NULL, NULL, dxpl_id, FALSE))) {
- HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest datatypes");
- } else if (!H5T_path_noop(tpath)) {
- if ((tsrc_id = H5I_register(H5I_DATATYPE, H5T_copy(src->shared->parent, H5T_COPY_ALL)))<0 ||
- (tdst_id = H5I_register(H5I_DATATYPE, H5T_copy(dst->shared->parent, H5T_COPY_ALL)))<0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register types for conversion");
+ if(NULL == (tpath = H5T_path_find(src->shared->parent, dst->shared->parent, NULL, NULL, dxpl_id, FALSE)))
+ HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest datatypes")
+ else if(!H5T_path_noop(tpath)) {
+ if((tsrc_id = H5I_register(H5I_DATATYPE, H5T_copy(src->shared->parent, H5T_COPY_ALL), FALSE)) < 0 ||
+ (tdst_id = H5I_register(H5I_DATATYPE, H5T_copy(dst->shared->parent, H5T_COPY_ALL), FALSE)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register types for conversion")
} else
- noop_conv=TRUE;
+ noop_conv = TRUE;
/* Check if we need a temporary buffer for this conversion */
- parent_is_vlen=H5T_detect_class(dst->shared->parent,H5T_VLEN);
+ parent_is_vlen = H5T_detect_class(dst->shared->parent, H5T_VLEN);
if(tpath->cdata.need_bkg || parent_is_vlen) {
/* Set up initial background buffer */
- tmp_buf_size=MAX(src_base_size,dst_base_size);
- if ((tmp_buf=H5FL_BLK_MALLOC(vlen_seq,tmp_buf_size))==NULL)
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion");
+ tmp_buf_size = MAX(src_base_size,dst_base_size);
+ if(NULL == (tmp_buf = H5FL_BLK_MALLOC(vlen_seq,tmp_buf_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion")
} /* end if */
/* Get the allocation info */
- if(H5T_vlen_get_alloc_info(dxpl_id,&vl_alloc_info)<0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to retrieve VL allocation info");
+ if(H5T_vlen_get_alloc_info(dxpl_id,&vl_alloc_info) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to retrieve VL allocation info")
/* Set flags to indicate we are writing to or reading from the file */
- if(dst->shared->u.vlen.f!=NULL)
+ if(dst->shared->u.vlen.f != NULL)
write_to_file = TRUE;
/* Set the flag for nested VL case */
- if(write_to_file && parent_is_vlen && bkg!=NULL)
+ if(write_to_file && parent_is_vlen && bkg != NULL)
nested = TRUE;
/* The outer loop of the type conversion macro, controlling which */
@@ -3051,7 +3151,7 @@ H5T_conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
uint8_t *tmp_p;
/* TMP_P is reset each time in the loop because DST_BASE_SIZE may include some data in addition to VL info. - SLU */
for(u=seq_len; u<bg_seq_len; u++) {
- tmp_p = (uint8_t*)tmp_buf + u*dst_base_size;
+ tmp_p = (uint8_t*)tmp_buf + u*dst_base_size;
UINT32DECODE(tmp_p, parent_seq_len);
if(parent_seq_len>0) {
H5F_addr_decode(dst->shared->u.vlen.f, (const uint8_t **)&tmp_p, &(parent_hobjid.addr));
@@ -3076,9 +3176,9 @@ H5T_conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
/* Release the temporary datatype IDs used */
if (tsrc_id >= 0)
- H5I_dec_ref(tsrc_id);
+ H5I_dec_ref(tsrc_id, FALSE);
if (tdst_id >= 0)
- H5I_dec_ref(tdst_id);
+ H5I_dec_ref(tdst_id, FALSE);
break;
default: /* Some other command we don't know about yet.*/
@@ -3096,14 +3196,14 @@ done:
if(tmp_buf!=NULL)
H5FL_BLK_FREE(vlen_seq,tmp_buf);
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
/*-------------------------------------------------------------------------
* Function: H5T_conv_array
*
- * Purpose: Converts between array data types in memory and on disk.
+ * Purpose: Converts between array datatypes in memory and on disk.
* This is a soft conversion function.
*
* Return: Non-negative on success/Negative on failure
@@ -3122,8 +3222,8 @@ H5T_conv_array(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
{
H5T_path_t *tpath; /* Type conversion path */
hid_t tsrc_id = -1, tdst_id = -1;/*temporary type atoms */
- H5T_t *src = NULL; /*source data type */
- H5T_t *dst = NULL; /*destination data type */
+ H5T_t *src = NULL; /*source datatype */
+ H5T_t *dst = NULL; /*destination datatype */
uint8_t *sp, *dp; /*source and dest traversal ptrs */
size_t src_delta, dst_delta; /*source & destination stride */
int direction; /*direction of traversal */
@@ -3144,7 +3244,7 @@ H5T_conv_array(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
* conversion path.
*/
if(NULL == (src = H5I_object(src_id)) || NULL == (dst = H5I_object(dst_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type")
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
HDassert(H5T_ARRAY==src->shared->type);
HDassert(H5T_ARRAY==dst->shared->type);
@@ -3169,7 +3269,7 @@ H5T_conv_array(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
* Conversion.
*/
if (NULL == (src = H5I_object(src_id)) || NULL == (dst = H5I_object(dst_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type")
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
/*
* Do we process the values from beginning to end or vice
@@ -3197,8 +3297,8 @@ H5T_conv_array(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
if(NULL == (tpath = H5T_path_find(src->shared->parent, dst->shared->parent, NULL, NULL, dxpl_id, FALSE))) {
HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest datatypes")
} else if (!H5T_path_noop(tpath)) {
- if((tsrc_id = H5I_register(H5I_DATATYPE, H5T_copy(src->shared->parent, H5T_COPY_ALL))) < 0 ||
- (tdst_id = H5I_register(H5I_DATATYPE, H5T_copy(dst->shared->parent, H5T_COPY_ALL))) < 0)
+ if((tsrc_id = H5I_register(H5I_DATATYPE, H5T_copy(src->shared->parent, H5T_COPY_ALL), FALSE)) < 0 ||
+ (tdst_id = H5I_register(H5I_DATATYPE, H5T_copy(dst->shared->parent, H5T_COPY_ALL), FALSE)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register types for conversion")
}
@@ -3228,9 +3328,9 @@ H5T_conv_array(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
/* Release the temporary datatype IDs used */
if(tsrc_id >= 0)
- H5I_dec_ref(tsrc_id);
+ H5I_dec_ref(tsrc_id, FALSE);
if(tdst_id >= 0)
- H5I_dec_ref(tdst_id);
+ H5I_dec_ref(tdst_id, FALSE);
break;
default: /* Some other command we don't know about yet.*/
@@ -3275,12 +3375,12 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
- size_t buf_stride, size_t UNUSED bkg_stride, void *buf,
- void UNUSED *bkg, hid_t dxpl_id)
+H5T_conv_i_i(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
+ size_t buf_stride, size_t UNUSED bkg_stride, void *buf, void UNUSED *bkg,
+ hid_t dxpl_id)
{
- H5T_t *src = NULL; /*source data type */
- H5T_t *dst = NULL; /*destination data type */
+ H5T_t *src = NULL; /*source datatype */
+ H5T_t *dst = NULL; /*destination datatype */
int direction; /*direction of traversal */
size_t elmtno; /*element number */
size_t half_size; /*half the type size */
@@ -3297,13 +3397,13 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
hbool_t reverse; /*if reverse the order of destination */
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_i_i, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_i_i, FAIL)
switch (cdata->command) {
case H5T_CONV_INIT:
if (NULL==(src=H5I_object(src_id)) ||
NULL==(dst=H5I_object(dst_id)))
- HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
+ HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
if (H5T_ORDER_LE!=src->shared->u.atomic.order &&
H5T_ORDER_BE!=src->shared->u.atomic.order)
HGOTO_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported byte order");
@@ -3319,10 +3419,10 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
break;
case H5T_CONV_CONV:
- /* Get the data types */
+ /* Get the datatypes */
if (NULL==(src=H5I_object(src_id)) ||
NULL==(dst=H5I_object(dst_id)))
- HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
+ HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
/*
* Do we process the values from beginning to end or vice versa? Also,
@@ -3650,7 +3750,7 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
done:
if(src_rev)
H5MM_free(src_rev);
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -3691,8 +3791,8 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
hid_t dxpl_id)
{
/* Traversal-related variables */
- H5T_t *src_p; /*source data type */
- H5T_t *dst_p; /*destination data type */
+ H5T_t *src_p; /*source datatype */
+ H5T_t *dst_p; /*destination datatype */
H5T_atomic_t src; /*atomic source info */
H5T_atomic_t dst; /*atomic destination info */
int direction; /*forward or backward traversal */
@@ -3723,13 +3823,13 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
hbool_t reverse; /*if reverse the order of destination */
herr_t ret_value=SUCCEED; /*return value */
- FUNC_ENTER_NOAPI(H5T_conv_f_f, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_f_f, FAIL)
switch (cdata->command) {
case H5T_CONV_INIT:
if (NULL==(src_p=H5I_object(src_id)) ||
NULL==(dst_p=H5I_object(dst_id)))
- HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
+ HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
src = src_p->shared->u.atomic;
dst = dst_p->shared->u.atomic;
if (H5T_ORDER_LE!=src.order && H5T_ORDER_BE!=src.order && H5T_ORDER_VAX!=src.order)
@@ -3747,10 +3847,10 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
break;
case H5T_CONV_CONV:
- /* Get the data types */
+ /* Get the datatypes */
if (NULL==(src_p=H5I_object(src_id)) ||
NULL==(dst_p=H5I_object(dst_id)))
- HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
+ HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
src = src_p->shared->u.atomic;
dst = dst_p->shared->u.atomic;
expo_max = ((hssize_t)1 << dst.u.f.esize) - 1;
@@ -4229,7 +4329,7 @@ done:
if(src_rev)
H5MM_free(src_rev);
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -4252,12 +4352,12 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5T_conv_s_s (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
+H5T_conv_s_s(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
size_t buf_stride, size_t UNUSED bkg_stride, void *buf,
void UNUSED *bkg, hid_t UNUSED dxpl_id)
{
- H5T_t *src=NULL; /*source data type */
- H5T_t *dst=NULL; /*destination data type */
+ H5T_t *src=NULL; /*source datatype */
+ H5T_t *dst=NULL; /*destination datatype */
int direction; /*direction of traversal */
size_t elmtno; /*element number */
size_t olap; /*num overlapping elements */
@@ -4266,13 +4366,13 @@ H5T_conv_s_s (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
uint8_t *dbuf=NULL; /*temp buf for overlap convers. */
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_s_s, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_s_s, FAIL)
switch (cdata->command) {
case H5T_CONV_INIT:
if (NULL==(src=H5I_object(src_id)) ||
NULL==(dst=H5I_object(dst_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
if (8*src->shared->size != src->shared->u.atomic.prec || 8*dst->shared->size != dst->shared->u.atomic.prec)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bad precision");
if (0 != src->shared->u.atomic.offset || 0 != dst->shared->u.atomic.offset)
@@ -4291,10 +4391,10 @@ H5T_conv_s_s (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
break;
case H5T_CONV_CONV:
- /* Get the data types */
+ /* Get the datatypes */
if (NULL==(src=H5I_object(src_id)) ||
NULL==(dst=H5I_object(dst_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
/*
* Do we process the values from beginning to end or vice versa? Also,
@@ -4456,7 +4556,7 @@ H5T_conv_s_s (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
done:
H5MM_xfree(dbuf);
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -4484,12 +4584,12 @@ H5T_conv_schar_uchar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_schar_uchar, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_schar_uchar, FAIL)
H5T_CONV_su(SCHAR, UCHAR, signed char, unsigned char, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -4517,12 +4617,12 @@ H5T_conv_uchar_schar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_uchar_schar, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_uchar_schar, FAIL)
H5T_CONV_us(UCHAR, SCHAR, unsigned char, signed char, -, SCHAR_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -4550,12 +4650,12 @@ H5T_conv_schar_short(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_schar_short, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_schar_short, FAIL)
H5T_CONV_sS(SCHAR, SHORT, signed char, short, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -4583,12 +4683,12 @@ H5T_conv_schar_ushort(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_schar_ushort, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_schar_ushort, FAIL)
H5T_CONV_sU(SCHAR, USHORT, signed char, unsigned short, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -4616,12 +4716,12 @@ H5T_conv_uchar_short(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_uchar_short, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_uchar_short, FAIL)
H5T_CONV_uS(UCHAR, SHORT, unsigned char, short, -, SHRT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -4649,12 +4749,12 @@ H5T_conv_uchar_ushort(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_uchar_ushort, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_uchar_ushort, FAIL)
H5T_CONV_uU(UCHAR, USHORT, unsigned char, unsigned short, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -4681,12 +4781,12 @@ H5T_conv_schar_int(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_schar_int, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_schar_int, FAIL)
H5T_CONV_sS(SCHAR, INT, signed char, int, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -4713,12 +4813,12 @@ H5T_conv_schar_uint(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_schar_uint, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_schar_uint, FAIL)
H5T_CONV_sU(SCHAR, UINT, signed char, unsigned, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -4745,12 +4845,12 @@ H5T_conv_uchar_int(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_uchar_int, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_uchar_int, FAIL)
H5T_CONV_uS(UCHAR, INT, unsigned char, int, -, INT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -4777,12 +4877,12 @@ H5T_conv_uchar_uint(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_uchar_uint, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_uchar_uint, FAIL)
H5T_CONV_uU(UCHAR, UINT, unsigned char, unsigned, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -4809,12 +4909,12 @@ H5T_conv_schar_long(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_schar_long, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_schar_long, FAIL)
H5T_CONV_sS(SCHAR, LONG, signed char, long, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -4842,12 +4942,12 @@ H5T_conv_schar_ulong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_schar_ulong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_schar_ulong, FAIL)
H5T_CONV_sU(SCHAR, ULONG, signed char, unsigned long, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -4874,12 +4974,12 @@ H5T_conv_uchar_long(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_uchar_long, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_uchar_long, FAIL)
H5T_CONV_uS(UCHAR, LONG, unsigned char, long, -, LONG_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -4907,12 +5007,12 @@ H5T_conv_uchar_ulong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_uchar_ulong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_uchar_ulong, FAIL)
H5T_CONV_uU(UCHAR, ULONG, unsigned char, unsigned long, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -4940,12 +5040,12 @@ H5T_conv_schar_llong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_schar_llong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_schar_llong, FAIL)
H5T_CONV_sS(SCHAR, LLONG, signed char, long_long, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -4973,12 +5073,12 @@ H5T_conv_schar_ullong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_schar_ullong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_schar_ullong, FAIL)
H5T_CONV_sU(SCHAR, ULLONG, signed char, unsigned long_long, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -5006,12 +5106,12 @@ H5T_conv_uchar_llong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_uchar_llong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_uchar_llong, FAIL)
H5T_CONV_uS(UCHAR, LLONG, unsigned char, long_long, -, LLONG_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -5039,12 +5139,12 @@ H5T_conv_uchar_ullong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_uchar_ullong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_uchar_ullong, FAIL)
H5T_CONV_uU(UCHAR, ULLONG, unsigned char, unsigned long_long, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -5072,12 +5172,12 @@ H5T_conv_short_schar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_short_schar, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_short_schar, FAIL)
H5T_CONV_Ss(SHORT, SCHAR, short, signed char, SCHAR_MIN, SCHAR_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -5105,12 +5205,12 @@ H5T_conv_short_uchar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_short_uchar, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_short_uchar, FAIL)
H5T_CONV_Su(SHORT, UCHAR, short, unsigned char, -, UCHAR_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -5138,12 +5238,12 @@ H5T_conv_ushort_schar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ushort_schar, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ushort_schar, FAIL)
H5T_CONV_Us(USHORT, SCHAR, unsigned short, signed char, -, SCHAR_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -5171,12 +5271,12 @@ H5T_conv_ushort_uchar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ushort_uchar, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ushort_uchar, FAIL)
H5T_CONV_Uu(USHORT, UCHAR, unsigned short, unsigned char, -, UCHAR_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -5204,12 +5304,12 @@ H5T_conv_short_ushort(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_short_ushort, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_short_ushort, FAIL)
H5T_CONV_su(SHORT, USHORT, short, unsigned short, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -5237,12 +5337,12 @@ H5T_conv_ushort_short(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ushort_short, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ushort_short, FAIL)
H5T_CONV_us(USHORT, SHORT, unsigned short, short, -, SHRT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -5270,12 +5370,12 @@ H5T_conv_short_int(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_short_int, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_short_int, FAIL)
H5T_CONV_sS(SHORT, INT, short, int, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -5303,12 +5403,12 @@ H5T_conv_short_uint(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_short_uint, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_short_uint, FAIL)
H5T_CONV_sU(SHORT, UINT, short, unsigned, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -5336,12 +5436,12 @@ H5T_conv_ushort_int(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ushort_int, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ushort_int, FAIL)
H5T_CONV_uS(USHORT, INT, unsigned short, int, -, INT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -5369,12 +5469,12 @@ H5T_conv_ushort_uint(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ushort_uint, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ushort_uint, FAIL)
H5T_CONV_uU(USHORT, UINT, unsigned short, unsigned, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -5402,12 +5502,12 @@ H5T_conv_short_long(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_short_long, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_short_long, FAIL)
H5T_CONV_sS(SHORT, LONG, short, long, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -5435,12 +5535,12 @@ H5T_conv_short_ulong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_short_ulong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_short_ulong, FAIL)
H5T_CONV_sU(SHORT, ULONG, short, unsigned long, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -5468,12 +5568,12 @@ H5T_conv_ushort_long(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ushort_long, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ushort_long, FAIL)
H5T_CONV_uS(USHORT, LONG, unsigned short, long, -, LONG_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -5501,12 +5601,12 @@ H5T_conv_ushort_ulong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ushort_ulong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ushort_ulong, FAIL)
H5T_CONV_uU(USHORT, ULONG, unsigned short, unsigned long, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -5534,12 +5634,12 @@ H5T_conv_short_llong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_short_llong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_short_llong, FAIL)
H5T_CONV_sS(SHORT, LLONG, short, long_long, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -5567,12 +5667,12 @@ H5T_conv_short_ullong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_short_ullong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_short_ullong, FAIL)
H5T_CONV_sU(SHORT, ULLONG, short, unsigned long_long, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -5600,12 +5700,12 @@ H5T_conv_ushort_llong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ushort_llong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ushort_llong, FAIL)
H5T_CONV_uS(USHORT, LLONG, unsigned short, long_long, -, LLONG_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -5633,12 +5733,12 @@ H5T_conv_ushort_ullong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ushort_ullong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ushort_ullong, FAIL)
H5T_CONV_uU(USHORT, ULLONG, unsigned short, unsigned long_long, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -5666,12 +5766,12 @@ H5T_conv_int_schar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_int_schar, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_int_schar, FAIL)
H5T_CONV_Ss(INT, SCHAR, int, signed char, SCHAR_MIN, SCHAR_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -5699,12 +5799,12 @@ H5T_conv_int_uchar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_int_uchar, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_int_uchar, FAIL)
H5T_CONV_Su(INT, UCHAR, int, unsigned char, -, UCHAR_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -5732,12 +5832,12 @@ H5T_conv_uint_schar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_uint_schar, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_uint_schar, FAIL)
H5T_CONV_Us(UINT, SCHAR, unsigned, signed char, -, SCHAR_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -5765,12 +5865,12 @@ H5T_conv_uint_uchar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_uint_uchar, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_uint_uchar, FAIL)
H5T_CONV_Uu(UINT, UCHAR, unsigned, unsigned char, -, UCHAR_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -5798,12 +5898,12 @@ H5T_conv_int_short(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_int_short, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_int_short, FAIL)
H5T_CONV_Ss(INT, SHORT, int, short, SHRT_MIN, SHRT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -5831,12 +5931,12 @@ H5T_conv_int_ushort(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_int_ushort, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_int_ushort, FAIL)
H5T_CONV_Su(INT, USHORT, int, unsigned short, -, USHRT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -5864,12 +5964,12 @@ H5T_conv_uint_short(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_uint_short, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_uint_short, FAIL)
H5T_CONV_Us(UINT, SHORT, unsigned, short, -, SHRT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -5897,12 +5997,12 @@ H5T_conv_uint_ushort(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_uint_ushort, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_uint_ushort, FAIL)
H5T_CONV_Uu(UINT, USHORT, unsigned, unsigned short, -, USHRT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -5929,12 +6029,12 @@ H5T_conv_int_uint(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_int_uint, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_int_uint, FAIL)
H5T_CONV_su(INT, UINT, int, unsigned, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -5961,12 +6061,12 @@ H5T_conv_uint_int(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_uint_int, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_uint_int, FAIL)
H5T_CONV_us(UINT, INT, unsigned, int, -, INT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -5993,12 +6093,12 @@ H5T_conv_int_long(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_int_long, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_int_long, FAIL)
H5T_CONV_sS(INT, LONG, int, long, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -6025,12 +6125,12 @@ H5T_conv_int_ulong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_int_ulong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_int_ulong, FAIL)
H5T_CONV_sU(INT, LONG, int, unsigned long, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -6057,12 +6157,12 @@ H5T_conv_uint_long(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_uint_long, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_uint_long, FAIL)
H5T_CONV_uS(UINT, LONG, unsigned, long, -, LONG_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -6089,12 +6189,12 @@ H5T_conv_uint_ulong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_uint_ulong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_uint_ulong, FAIL)
H5T_CONV_uU(UINT, ULONG, unsigned, unsigned long, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -6121,12 +6221,12 @@ H5T_conv_int_llong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_int_llong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_int_llong, FAIL)
H5T_CONV_sS(INT, LLONG, int, long_long, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -6153,12 +6253,12 @@ H5T_conv_int_ullong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_int_ullong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_int_ullong, FAIL)
H5T_CONV_sU(INT, ULLONG, int, unsigned long_long, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -6185,12 +6285,12 @@ H5T_conv_uint_llong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_uint_llong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_uint_llong, FAIL)
H5T_CONV_uS(UINT, LLONG, unsigned, long_long, -, LLONG_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -6218,12 +6318,12 @@ H5T_conv_uint_ullong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_uint_ullong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_uint_ullong, FAIL)
H5T_CONV_uU(UINT, ULLONG, unsigned, unsigned long_long, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -6250,12 +6350,12 @@ H5T_conv_long_schar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_long_schar, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_long_schar, FAIL)
H5T_CONV_Ss(LONG, SCHAR, long, signed char, SCHAR_MIN, SCHAR_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -6282,12 +6382,12 @@ H5T_conv_long_uchar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_long_uchar, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_long_uchar, FAIL)
H5T_CONV_Su(LONG, UCHAR, long, unsigned char, -, UCHAR_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -6315,12 +6415,12 @@ H5T_conv_ulong_schar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ulong_schar, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ulong_schar, FAIL)
H5T_CONV_Us(ULONG, SCHAR, unsigned long, signed char, -, SCHAR_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -6348,12 +6448,12 @@ H5T_conv_ulong_uchar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ulong_uchar, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ulong_uchar, FAIL)
H5T_CONV_Uu(ULONG, UCHAR, unsigned long, unsigned char, -, UCHAR_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -6380,12 +6480,12 @@ H5T_conv_long_short(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_long_short, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_long_short, FAIL)
H5T_CONV_Ss(LONG, SHORT, long, short, SHRT_MIN, SHRT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -6413,12 +6513,12 @@ H5T_conv_long_ushort(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_long_ushort, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_long_ushort, FAIL)
H5T_CONV_Su(LONG, USHORT, long, unsigned short, -, USHRT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -6445,12 +6545,12 @@ H5T_conv_ulong_short(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ulong_short, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ulong_short, FAIL)
H5T_CONV_Us(ULONG, SHORT, unsigned long, short, -, SHRT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -6478,12 +6578,12 @@ H5T_conv_ulong_ushort(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ulong_ushort, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ulong_ushort, FAIL)
H5T_CONV_Uu(ULONG, USHORT, unsigned long, unsigned short, -, USHRT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -6510,12 +6610,12 @@ H5T_conv_long_int(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_long_int, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_long_int, FAIL)
H5T_CONV_Ss(LONG, INT, long, int, INT_MIN, INT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -6542,12 +6642,12 @@ H5T_conv_long_uint(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_long_uint, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_long_uint, FAIL)
H5T_CONV_Su(LONG, UINT, long, unsigned, -, UINT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -6574,12 +6674,12 @@ H5T_conv_ulong_int(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ulong_int, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ulong_int, FAIL)
H5T_CONV_Us(ULONG, INT, unsigned long, int, -, INT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -6606,12 +6706,12 @@ H5T_conv_ulong_uint(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ulong_uint, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ulong_uint, FAIL)
H5T_CONV_Uu(ULONG, UINT, unsigned long, unsigned, -, UINT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -6638,12 +6738,12 @@ H5T_conv_long_ulong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_long_ulong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_long_ulong, FAIL)
H5T_CONV_su(LONG, ULONG, long, unsigned long, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -6670,12 +6770,12 @@ H5T_conv_ulong_long(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ulong_long, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ulong_long, FAIL)
H5T_CONV_us(ULONG, LONG, unsigned long, long, -, LONG_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -6702,12 +6802,12 @@ H5T_conv_long_llong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_long_llong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_long_llong, FAIL)
H5T_CONV_sS(LONG, LLONG, long, long_long, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -6735,12 +6835,12 @@ H5T_conv_long_ullong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_long_ullong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_long_ullong, FAIL)
H5T_CONV_sU(LONG, ULLONG, long, unsigned long_long, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -6768,12 +6868,12 @@ H5T_conv_ulong_llong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ulong_llong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ulong_llong, FAIL)
H5T_CONV_uS(ULONG, LLONG, unsigned long, long_long, -, LLONG_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -6801,12 +6901,12 @@ H5T_conv_ulong_ullong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ulong_ullong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ulong_ullong, FAIL)
H5T_CONV_uU(ULONG, ULLONG, unsigned long, unsigned long_long, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -6834,12 +6934,12 @@ H5T_conv_llong_schar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_llong_schar, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_llong_schar, FAIL)
H5T_CONV_Ss(LLONG, SCHAR, long_long, signed char, SCHAR_MIN, SCHAR_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -6867,12 +6967,12 @@ H5T_conv_llong_uchar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_llong_uchar, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_llong_uchar, FAIL)
H5T_CONV_Su(LLONG, UCHAR, long_long, unsigned char, -, UCHAR_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -6900,12 +7000,12 @@ H5T_conv_ullong_schar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ullong_schar, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ullong_schar, FAIL)
H5T_CONV_Us(ULLONG, SCHAR, unsigned long_long, signed char, -, SCHAR_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -6933,12 +7033,12 @@ H5T_conv_ullong_uchar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ullong_uchar, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ullong_uchar, FAIL)
H5T_CONV_Uu(ULLONG, UCHAR, unsigned long_long, unsigned char, -, UCHAR_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -6966,12 +7066,12 @@ H5T_conv_llong_short(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_llong_short, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_llong_short, FAIL)
H5T_CONV_Ss(LLONG, SHORT, long_long, short, SHRT_MIN, SHRT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -6999,12 +7099,12 @@ H5T_conv_llong_ushort(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_llong_ushort, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_llong_ushort, FAIL)
H5T_CONV_Su(LLONG, USHORT, long_long, unsigned short, -, USHRT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -7032,12 +7132,12 @@ H5T_conv_ullong_short(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ullong_short, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ullong_short, FAIL)
H5T_CONV_Us(ULLONG, SHORT, unsigned long_long, short, -, SHRT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -7065,12 +7165,12 @@ H5T_conv_ullong_ushort(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ullong_ushort, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ullong_ushort, FAIL)
H5T_CONV_Uu(ULLONG, USHORT, unsigned long_long, unsigned short, -, USHRT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -7097,12 +7197,12 @@ H5T_conv_llong_int(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_llong_int, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_llong_int, FAIL)
H5T_CONV_Ss(LLONG, INT, long_long, int, INT_MIN, INT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -7129,12 +7229,12 @@ H5T_conv_llong_uint(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_llong_uint, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_llong_uint, FAIL)
H5T_CONV_Su(LLONG, UINT, long_long, unsigned, -, UINT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -7161,12 +7261,12 @@ H5T_conv_ullong_int(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ullong_int, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ullong_int, FAIL)
H5T_CONV_Us(ULLONG, INT, unsigned long_long, int, -, INT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -7194,12 +7294,12 @@ H5T_conv_ullong_uint(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ullong_uint, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ullong_uint, FAIL)
H5T_CONV_Uu(ULLONG, UINT, unsigned long_long, unsigned, -, UINT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -7226,12 +7326,12 @@ H5T_conv_llong_long(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_llong_long, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_llong_long, FAIL)
H5T_CONV_Ss(LLONG, LONG, long_long, long, LONG_MIN, LONG_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -7259,12 +7359,12 @@ H5T_conv_llong_ulong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_llong_ulong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_llong_ulong, FAIL)
H5T_CONV_Su(LLONG, ULONG, long_long, unsigned long, -, ULONG_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -7292,12 +7392,12 @@ H5T_conv_ullong_long(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ullong_long, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ullong_long, FAIL)
H5T_CONV_Us(ULLONG, LONG, unsigned long_long, long, -, LONG_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -7325,12 +7425,12 @@ H5T_conv_ullong_ulong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ullong_ulong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ullong_ulong, FAIL)
H5T_CONV_Uu(ULLONG, ULONG, unsigned long_long, unsigned long, -, ULONG_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -7358,12 +7458,12 @@ H5T_conv_llong_ullong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_llong_ullong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_llong_ullong, FAIL)
H5T_CONV_su(LLONG, ULLONG, long_long, unsigned long_long, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -7391,12 +7491,12 @@ H5T_conv_ullong_llong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ullong_llong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ullong_llong, FAIL)
H5T_CONV_us(ULLONG, LLONG, unsigned long_long, long_long, -, LLONG_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -7428,12 +7528,12 @@ H5T_conv_float_double (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_float_double, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_float_double, FAIL)
H5T_CONV_fF(FLOAT, DOUBLE, float, double, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /* H5T_CONV_INTERNAL_FP_FP */
@@ -7462,12 +7562,12 @@ H5T_conv_float_ldouble (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_float_ldouble, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_float_ldouble, FAIL)
H5T_CONV_fF(FLOAT, LDOUBLE, float, long double, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /*H5T_CONV_INTERNAL_FP_LDOUBLE*/
@@ -7503,12 +7603,12 @@ H5T_conv_double_float (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_double_float, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_double_float, FAIL)
H5T_CONV_Ff(DOUBLE, FLOAT, double, float, -FLT_MAX, FLT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /*H5T_CONV_INTERNAL_FP_FP*/
@@ -7537,13 +7637,13 @@ H5T_conv_double_ldouble (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_double_ldouble, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_double_ldouble, FAIL)
H5T_CONV_fF(DOUBLE, LDOUBLE, double, long double, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /*H5T_CONV_INTERNAL_FP_LDOUBLE*/
@@ -7572,12 +7672,12 @@ H5T_conv_ldouble_float (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ldouble_float, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ldouble_float, FAIL)
H5T_CONV_Ff(LDOUBLE, FLOAT, long double, float, -FLT_MAX, FLT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /* H5T_CONV_INTERNAL_FP_LDOUBLE */
@@ -7606,12 +7706,12 @@ H5T_conv_ldouble_double (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ldouble_double, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ldouble_double, FAIL)
H5T_CONV_Ff(LDOUBLE, DOUBLE, long double, double, -DBL_MAX, DBL_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /*H5T_CONV_INTERNAL_FP_LDOUBLE*/
@@ -7639,12 +7739,12 @@ H5T_conv_schar_float (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_schar_float, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_schar_float, FAIL)
H5T_CONV_xF(SCHAR, FLOAT, signed char, float, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -7671,12 +7771,12 @@ H5T_conv_schar_double (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_schar_double, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_schar_double, FAIL)
H5T_CONV_xF(SCHAR, DOUBLE, signed char, double, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -7704,12 +7804,12 @@ H5T_conv_schar_ldouble (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_schar_ldouble, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_schar_ldouble, FAIL)
H5T_CONV_xF(SCHAR, LDOUBLE, signed char, long double, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /* H5T_CONV_INTERNAL_INTEGER_LDOUBLE */
@@ -7737,12 +7837,12 @@ H5T_conv_uchar_float (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_uchar_float, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_uchar_float, FAIL)
H5T_CONV_xF(UCHAR, FLOAT, unsigned char, float, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -7769,12 +7869,12 @@ H5T_conv_uchar_double (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_uchar_double, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_uchar_double, FAIL)
H5T_CONV_xF(UCHAR, DOUBLE, unsigned char, double, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -7802,12 +7902,12 @@ H5T_conv_uchar_ldouble (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_uchar_ldouble, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_uchar_ldouble, FAIL)
H5T_CONV_xF(UCHAR, LDOUBLE, unsigned char, long double, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /* H5T_CONV_INTERNAL_INTEGER_LDOUBLE */
@@ -7835,12 +7935,12 @@ H5T_conv_short_float (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_short_float, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_short_float, FAIL)
H5T_CONV_xF(SHORT, FLOAT, short, float, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -7867,12 +7967,12 @@ H5T_conv_short_double (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_short_double, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_short_double, FAIL)
H5T_CONV_xF(SHORT, DOUBLE, short, double, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -7900,12 +8000,12 @@ H5T_conv_short_ldouble (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_short_ldouble, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_short_ldouble, FAIL)
H5T_CONV_xF(SHORT, LDOUBLE, short, long double, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /* H5T_CONV_INTERNAL_INTEGER_LDOUBLE */
@@ -7933,12 +8033,12 @@ H5T_conv_ushort_float (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ushort_float, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ushort_float, FAIL)
H5T_CONV_xF(USHORT, FLOAT, unsigned short, float, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -7965,12 +8065,12 @@ H5T_conv_ushort_double (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ushort_double, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ushort_double, FAIL)
H5T_CONV_xF(USHORT, DOUBLE, unsigned short, double, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -7998,12 +8098,12 @@ H5T_conv_ushort_ldouble (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ushort_ldouble, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ushort_ldouble, FAIL)
H5T_CONV_xF(USHORT, LDOUBLE, unsigned short, long double, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /* H5T_CONV_INTERNAL_INTEGER_LDOUBLE */
@@ -8031,12 +8131,12 @@ H5T_conv_int_float (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_int_float, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_int_float, FAIL)
H5T_CONV_xF(INT, FLOAT, int, float, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -8063,12 +8163,12 @@ H5T_conv_int_double (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_int_double, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_int_double, FAIL)
H5T_CONV_xF(INT, DOUBLE, int, double, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -8096,12 +8196,12 @@ H5T_conv_int_ldouble (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_int_ldouble, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_int_ldouble, FAIL)
H5T_CONV_xF(INT, LDOUBLE, int, long double, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /* H5T_CONV_INTERNAL_INTEGER_LDOUBLE */
@@ -8129,12 +8229,12 @@ H5T_conv_uint_float (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_uint_float, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_uint_float, FAIL)
H5T_CONV_xF(UINT, FLOAT, unsigned int, float, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -8161,12 +8261,12 @@ H5T_conv_uint_double (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_uint_double, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_uint_double, FAIL)
H5T_CONV_xF(UINT, DOUBLE, unsigned int, double, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -8194,12 +8294,12 @@ H5T_conv_uint_ldouble (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_uint_ldouble, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_uint_ldouble, FAIL)
H5T_CONV_xF(UINT, LDOUBLE, unsigned int, long double, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /* H5T_CONV_INTERNAL_INTEGER_LDOUBLE */
@@ -8227,12 +8327,12 @@ H5T_conv_long_float (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_long_float, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_long_float, FAIL)
H5T_CONV_xF(LONG, FLOAT, long, float, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -8259,12 +8359,12 @@ H5T_conv_long_double (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_long_double, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_long_double, FAIL)
H5T_CONV_xF(LONG, DOUBLE, long, double, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -8292,12 +8392,12 @@ H5T_conv_long_ldouble (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_long_ldouble, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_long_ldouble, FAIL)
H5T_CONV_xF(LONG, LDOUBLE, long, long double, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /* H5T_CONV_INTERNAL_INTEGER_LDOUBLE */
@@ -8326,12 +8426,12 @@ H5T_conv_ulong_float (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ulong_float, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ulong_float, FAIL)
H5T_CONV_xF(ULONG, FLOAT, unsigned long, float, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /* H5T_CONV_INTERNAL_ULONG_FP */
@@ -8360,12 +8460,12 @@ H5T_conv_ulong_double (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ulong_double, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ulong_double, FAIL)
H5T_CONV_xF(ULONG, DOUBLE, unsigned long, double, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /* H5T_CONV_INTERNAL_ULONG_FP */
@@ -8394,12 +8494,12 @@ H5T_conv_ulong_ldouble (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ulong_ldouble, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ulong_ldouble, FAIL)
H5T_CONV_xF(ULONG, LDOUBLE, unsigned long, long double, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /* H5T_CONV_INTERNAL_ULONG_LDOUBLE */
@@ -8427,12 +8527,12 @@ H5T_conv_llong_float (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_llong_float, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_llong_float, FAIL)
H5T_CONV_xF(LLONG, FLOAT, long_long, float, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -8459,12 +8559,12 @@ H5T_conv_llong_double (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_llong_double, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_llong_double, FAIL)
H5T_CONV_xF(LLONG, DOUBLE, long_long, double, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -8492,12 +8592,12 @@ H5T_conv_llong_ldouble (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_llong_ldouble, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_llong_ldouble, FAIL)
H5T_CONV_xF(LLONG, LDOUBLE, long_long, long double, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /* H5T_CONV_INTERNAL_LLONG_LDOUBLE */
@@ -8526,12 +8626,12 @@ H5T_conv_ullong_float (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ullong_float, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ullong_float, FAIL)
H5T_CONV_xF(ULLONG, FLOAT, unsigned long_long, float, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /*H5T_CONV_INTERNAL_ULLONG_FP*/
@@ -8560,12 +8660,12 @@ H5T_conv_ullong_double (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ullong_double, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ullong_double, FAIL)
H5T_CONV_xF(ULLONG, DOUBLE, unsigned long_long, double, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /*H5T_CONV_INTERNAL_ULLONG_FP*/
@@ -8594,12 +8694,12 @@ H5T_conv_ullong_ldouble (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ullong_ldouble, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ullong_ldouble, FAIL)
H5T_CONV_xF(ULLONG, LDOUBLE, unsigned long_long, long double, -, -);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /*H5T_CONV_INTERNAL_ULLONG_LDOUBLE*/
@@ -8627,12 +8727,12 @@ H5T_conv_float_schar (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_float_schar, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_float_schar, FAIL)
H5T_CONV_Fx(FLOAT, SCHAR, float, signed char, SCHAR_MIN, SCHAR_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -8659,12 +8759,12 @@ H5T_conv_float_uchar (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_float_uchar, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_float_uchar, FAIL)
H5T_CONV_Fx(FLOAT, UCHAR, float, unsigned char, 0, UCHAR_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -8691,12 +8791,12 @@ H5T_conv_double_schar (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_double_schar, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_double_schar, FAIL)
H5T_CONV_Fx(DOUBLE, SCHAR, double, signed char, SCHAR_MIN, SCHAR_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -8723,12 +8823,12 @@ H5T_conv_double_uchar (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_double_uchar, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_double_uchar, FAIL)
H5T_CONV_Fx(DOUBLE, UCHAR, double, unsigned char, 0, UCHAR_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -8756,12 +8856,12 @@ H5T_conv_ldouble_schar (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ldouble_schar, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ldouble_schar, FAIL)
H5T_CONV_Fx(LDOUBLE, SCHAR, long double, signed char, SCHAR_MIN, SCHAR_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /* H5T_CONV_INTERNAL_LDOUBLE_INTEGER */
@@ -8790,12 +8890,12 @@ H5T_conv_ldouble_uchar (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ldouble_uchar, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ldouble_uchar, FAIL)
H5T_CONV_Fx(LDOUBLE, UCHAR, long double, unsigned char, 0, UCHAR_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /* H5T_CONV_INTERNAL_LDOUBLE_INTEGER */
@@ -8823,12 +8923,12 @@ H5T_conv_float_short (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_float_short, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_float_short, FAIL)
H5T_CONV_Fx(FLOAT, SHORT, float, short, SHRT_MIN, SHRT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -8855,12 +8955,12 @@ H5T_conv_float_ushort (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_float_ushort, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_float_ushort, FAIL)
H5T_CONV_Fx(FLOAT, USHORT, float, unsigned short, 0, USHRT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -8887,12 +8987,12 @@ H5T_conv_double_short (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_double_short, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_double_short, FAIL)
H5T_CONV_Fx(DOUBLE, SHORT, double, short, SHRT_MIN, SHRT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -8919,12 +9019,12 @@ H5T_conv_double_ushort (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_double_ushort, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_double_ushort, FAIL)
H5T_CONV_Fx(DOUBLE, USHORT, double, unsigned short, 0, USHRT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -8952,12 +9052,12 @@ H5T_conv_ldouble_short (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ldouble_short, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ldouble_short, FAIL)
H5T_CONV_Fx(LDOUBLE, SHORT, long double, short, SHRT_MIN, SHRT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /*H5T_CONV_INTERNAL_LDOUBLE_INTEGER*/
@@ -8986,12 +9086,12 @@ H5T_conv_ldouble_ushort (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ldouble_ushort, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ldouble_ushort, FAIL)
H5T_CONV_Fx(LDOUBLE, USHORT, long double, unsigned short, 0, USHRT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /* H5T_CONV_INTERNAL_LDOUBLE_INTEGER */
@@ -9019,12 +9119,12 @@ H5T_conv_float_int (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_float_int, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_float_int, FAIL)
H5T_CONV_Fx(FLOAT, INT, float, int, INT_MIN, INT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -9051,12 +9151,12 @@ H5T_conv_float_uint (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_float_uint, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_float_uint, FAIL)
H5T_CONV_Fx(FLOAT, UINT, float, unsigned int, 0, UINT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -9083,12 +9183,12 @@ H5T_conv_double_int (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_double_int, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_double_int, FAIL)
H5T_CONV_Fx(DOUBLE, INT, double, int, INT_MIN, INT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -9115,12 +9215,12 @@ H5T_conv_double_uint (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_double_uint, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_double_uint, FAIL)
H5T_CONV_Fx(DOUBLE, UINT, double, unsigned int, 0, UINT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -9148,12 +9248,12 @@ H5T_conv_ldouble_int (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ldouble_int, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ldouble_int, FAIL)
H5T_CONV_Fx(LDOUBLE, INT, long double, int, INT_MIN, INT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /* H5T_CONV_INTERNAL_LDOUBLE_INTEGER */
@@ -9182,12 +9282,12 @@ H5T_conv_ldouble_uint (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ldouble_uint, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ldouble_uint, FAIL)
H5T_CONV_Fx(LDOUBLE, UINT, long double, unsigned int, 0, UINT_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /* H5T_CONV_INTERNAL_LDOUBLE_UINT */
@@ -9215,12 +9315,12 @@ H5T_conv_float_long (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_float_long, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_float_long, FAIL)
H5T_CONV_Fx(FLOAT, LONG, float, long, LONG_MIN, LONG_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -9247,12 +9347,12 @@ H5T_conv_float_ulong (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_float_ulong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_float_ulong, FAIL)
H5T_CONV_Fx(FLOAT, ULONG, float, unsigned long, 0, ULONG_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -9279,12 +9379,12 @@ H5T_conv_double_long (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_double_long, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_double_long, FAIL)
H5T_CONV_Fx(DOUBLE, LONG, double, long, LONG_MIN, LONG_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -9311,12 +9411,12 @@ H5T_conv_double_ulong (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_double_ulong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_double_ulong, FAIL)
H5T_CONV_Fx(DOUBLE, ULONG, double, unsigned long, 0, ULONG_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -9344,12 +9444,12 @@ H5T_conv_ldouble_long (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ldouble_long, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ldouble_long, FAIL)
H5T_CONV_Fx(LDOUBLE, LONG, long double, long, LONG_MIN, LONG_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /*H5T_CONV_INTERNAL_LDOUBLE_INTEGER*/
@@ -9378,12 +9478,12 @@ H5T_conv_ldouble_ulong (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ldouble_ulong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ldouble_ulong, FAIL)
H5T_CONV_Fx(LDOUBLE, ULONG, long double, unsigned long, 0, ULONG_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /* H5T_CONV_INTERNAL_LDOUBLE_INTEGER */
@@ -9412,12 +9512,12 @@ H5T_conv_float_llong (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_float_llong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_float_llong, FAIL)
H5T_CONV_Fx(FLOAT, LLONG, float, long_long, LLONG_MIN, LLONG_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /* H5T_CONV_INTERNAL_FP_LLONG */
@@ -9446,12 +9546,12 @@ H5T_conv_float_ullong (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_float_ullong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_float_ullong, FAIL)
H5T_CONV_Fx(FLOAT, ULLONG, float, unsigned long_long, 0, ULLONG_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /*H5T_CONV_INTERNAL_FP_ULLONG*/
@@ -9480,12 +9580,12 @@ H5T_conv_double_llong (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_double_llong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_double_llong, FAIL)
H5T_CONV_Fx(DOUBLE, LLONG, double, long_long, LLONG_MIN, LLONG_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /*H5T_CONV_INTERNAL_FP_LLONG*/
@@ -9514,12 +9614,12 @@ H5T_conv_double_ullong (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_double_ullong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_double_ullong, FAIL)
H5T_CONV_Fx(DOUBLE, ULLONG, double, unsigned long_long, 0, ULLONG_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /*H5T_CONV_INTERNAL_FP_ULLONG*/
@@ -9548,12 +9648,12 @@ H5T_conv_ldouble_llong (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ldouble_llong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ldouble_llong, FAIL)
H5T_CONV_Fx(LDOUBLE, LLONG, long double, long_long, LLONG_MIN, LLONG_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /*H5T_CONV_INTERNAL_LDOUBLE_LLONG*/
@@ -9582,12 +9682,12 @@ H5T_conv_ldouble_ullong (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
{
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_ldouble_ullong, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_ldouble_ullong, FAIL)
H5T_CONV_Fx(LDOUBLE, ULLONG, long double, unsigned long_long, 0, ULLONG_MAX);
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
#endif /*H5T_CONV_INTERNAL_LDOUBLE_ULLONG*/
@@ -9622,8 +9722,8 @@ H5T_conv_f_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
hid_t dxpl_id)
{
/* Traversal-related variables */
- H5T_t *src_p; /*source data type */
- H5T_t *dst_p; /*destination data type */
+ H5T_t *src_p; /*source datatype */
+ H5T_t *dst_p; /*destination datatype */
H5T_atomic_t src; /*atomic source info */
H5T_atomic_t dst; /*atomic destination info */
int direction; /*forward or backward traversal */
@@ -9651,13 +9751,13 @@ H5T_conv_f_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
H5T_conv_ret_t except_ret; /*return of callback function */
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_f_i, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_f_i, FAIL)
switch (cdata->command) {
case H5T_CONV_INIT:
if (NULL==(src_p=H5I_object(src_id)) ||
NULL==(dst_p=H5I_object(dst_id)))
- HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
+ HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
src = src_p->shared->u.atomic;
dst = dst_p->shared->u.atomic;
if (H5T_ORDER_LE!=src.order && H5T_ORDER_BE!=src.order && H5T_ORDER_VAX!=src.order)
@@ -9673,10 +9773,10 @@ H5T_conv_f_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
break;
case H5T_CONV_CONV:
- /* Get the data types */
+ /* Get the datatypes */
if (NULL==(src_p=H5I_object(src_id)) ||
NULL==(dst_p=H5I_object(dst_id)))
- HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
+ HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
src = src_p->shared->u.atomic;
dst = dst_p->shared->u.atomic;
@@ -10176,7 +10276,7 @@ done:
H5MM_xfree(int_buf);
if(src_rev)
H5MM_free(src_rev);
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -10210,8 +10310,8 @@ H5T_conv_i_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
hid_t dxpl_id)
{
/* Traversal-related variables */
- H5T_t *src_p; /*source data type */
- H5T_t *dst_p; /*destination data type */
+ H5T_t *src_p; /*source datatype */
+ H5T_t *dst_p; /*destination datatype */
H5T_atomic_t src; /*atomic source info */
H5T_atomic_t dst; /*atomic destination info */
int direction; /*forward or backward traversal */
@@ -10241,13 +10341,13 @@ H5T_conv_i_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
hbool_t reverse; /*if reverse the order of destination */
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5T_conv_i_f, FAIL);
+ FUNC_ENTER_NOAPI(H5T_conv_i_f, FAIL)
switch (cdata->command) {
case H5T_CONV_INIT:
if (NULL==(src_p=H5I_object(src_id)) ||
NULL==(dst_p=H5I_object(dst_id)))
- HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
+ HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
src = src_p->shared->u.atomic;
dst = dst_p->shared->u.atomic;
if (H5T_ORDER_LE!=dst.order && H5T_ORDER_BE!=dst.order && H5T_ORDER_VAX!=dst.order)
@@ -10263,10 +10363,10 @@ H5T_conv_i_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
break;
case H5T_CONV_CONV:
- /* Get the data types */
+ /* Get the datatypes */
if (NULL==(src_p=H5I_object(src_id)) ||
NULL==(dst_p=H5I_object(dst_id)))
- HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
+ HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
src = src_p->shared->u.atomic;
dst = dst_p->shared->u.atomic;
@@ -10605,7 +10705,7 @@ done:
H5MM_xfree(int_buf);
if(src_rev)
H5MM_free(src_rev);
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
}
@@ -10635,7 +10735,7 @@ H5T_reverse_order(uint8_t *rev, uint8_t *s, size_t size, H5T_order_t order)
{
size_t i;
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_reverse_order);
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_reverse_order)
assert(s);
assert(size);
@@ -10653,5 +10753,6 @@ H5T_reverse_order(uint8_t *rev, uint8_t *s, size_t size, H5T_order_t order)
rev[i] = s[i];
}
- FUNC_LEAVE_NOAPI(SUCCEED);
+ FUNC_LEAVE_NOAPI(SUCCEED)
}
+
diff --git a/src/H5Tdeprec.c b/src/H5Tdeprec.c
index 64386b1..df6238c 100644
--- a/src/H5Tdeprec.c
+++ b/src/H5Tdeprec.c
@@ -210,7 +210,7 @@ H5Topen1(hid_t loc_id, const char *name)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, FAIL, "unable to open named datatype")
/* Register the type and return the ID */
- if((ret_value = H5I_register(H5I_DATATYPE, type)) < 0)
+ if((ret_value = H5I_register(H5I_DATATYPE, type, TRUE)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register named datatype")
done:
diff --git a/src/H5Tenum.c b/src/H5Tenum.c
index 5ab6964..f955a7e 100644
--- a/src/H5Tenum.c
+++ b/src/H5Tenum.c
@@ -94,7 +94,7 @@ H5Tenum_create(hid_t parent_id)
if((dt=H5T_enum_create(parent))==NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "cannot create enum type")
/* Atomize the type */
- if ((ret_value=H5I_register(H5I_DATATYPE, dt))<0)
+ if ((ret_value=H5I_register(H5I_DATATYPE, dt, TRUE))<0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register data type atom")
done:
diff --git a/src/H5Tfields.c b/src/H5Tfields.c
index 0237fc4..43f1369 100644
--- a/src/H5Tfields.c
+++ b/src/H5Tfields.c
@@ -76,22 +76,22 @@ H5T_init_fields_interface(void)
int
H5Tget_nmembers(hid_t type_id)
{
- H5T_t *dt = NULL;
- int ret_value;
+ H5T_t *dt; /* Datatype to query */
+ int ret_value; /* Return value */
FUNC_ENTER_API(H5Tget_nmembers, FAIL)
H5TRACE1("Is", "i", type_id);
/* Check args */
- if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE)))
+ if(NULL == (dt = H5I_object_verify(type_id, H5I_DATATYPE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
- if((ret_value = H5T_get_nmembers(dt))<0)
+ if((ret_value = H5T_get_nmembers(dt)) < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "cannot return member number")
done:
FUNC_LEAVE_API(ret_value)
-}
+} /* end H5Tget_nmembers() */
/*-------------------------------------------------------------------------
@@ -121,18 +121,18 @@ H5T_get_nmembers(const H5T_t *dt)
FUNC_ENTER_NOAPI(H5T_get_nmembers, FAIL)
- assert(dt);
+ HDassert(dt);
- if (H5T_COMPOUND==dt->shared->type)
+ if(H5T_COMPOUND == dt->shared->type)
ret_value = (int)dt->shared->u.compnd.nmembs;
- else if (H5T_ENUM==dt->shared->type)
+ else if(H5T_ENUM == dt->shared->type)
ret_value = (int)dt->shared->u.enumer.nmembs;
else
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "operation not supported for type class")
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5T_get_nmembers() */
/*-------------------------------------------------------------------------
@@ -296,101 +296,94 @@ done:
* Programmer: Robb Matzke
* Wednesday, January 7, 1998
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
herr_t
H5T_sort_value(const H5T_t *dt, int *map)
{
- unsigned i, j, nmembs;
+ unsigned nmembs; /* Number of members for datatype */
size_t size;
- hbool_t swapped;
+ hbool_t swapped; /* Whether we've swapped fields */
uint8_t tbuf[32];
- herr_t ret_value=SUCCEED; /* Return value */
+ unsigned i, j; /* Local index variables */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5T_sort_value, FAIL)
/* Check args */
- assert(dt);
- assert(H5T_COMPOUND==dt->shared->type || H5T_ENUM==dt->shared->type);
+ HDassert(dt);
+ HDassert(H5T_COMPOUND == dt->shared->type || H5T_ENUM == dt->shared->type);
/* Use a bubble sort because we can short circuit */
- if (H5T_COMPOUND==dt->shared->type) {
- if (H5T_SORT_VALUE!=dt->shared->u.compnd.sorted) {
+ if(H5T_COMPOUND == dt->shared->type) {
+ if(H5T_SORT_VALUE != dt->shared->u.compnd.sorted) {
dt->shared->u.compnd.sorted = H5T_SORT_VALUE;
nmembs = dt->shared->u.compnd.nmembs;
- for (i=nmembs-1, swapped=TRUE; i>0 && swapped; --i) {
- for (j=0, swapped=FALSE; j<i; j++) {
- if (dt->shared->u.compnd.memb[j].offset >
- dt->shared->u.compnd.memb[j+1].offset) {
- H5T_cmemb_t tmp = dt->shared->u.compnd.memb[j];
- dt->shared->u.compnd.memb[j] = dt->shared->u.compnd.memb[j+1];
- dt->shared->u.compnd.memb[j+1] = tmp;
- if (map) {
+ for(i = nmembs - 1, swapped = TRUE; i > 0 && swapped; --i) {
+ for(j = 0, swapped = FALSE; j < i; j++) {
+ if(dt->shared->u.compnd.memb[j].offset > dt->shared->u.compnd.memb[j + 1].offset) {
+ H5T_cmemb_t tmp = dt->shared->u.compnd.memb[j];
+ dt->shared->u.compnd.memb[j] = dt->shared->u.compnd.memb[j + 1];
+ dt->shared->u.compnd.memb[j + 1] = tmp;
+ if(map) {
int x = map[j];
- map[j] = map[j+1];
- map[j+1] = x;
- }
+
+ map[j] = map[j + 1];
+ map[j + 1] = x;
+ } /* end if */
swapped = TRUE;
- }
- }
- }
+ } /* end if */
+ } /* end for */
+ } /* end for */
#ifndef NDEBUG
/* I never trust a sort :-) -RPM */
- for (i=0; i<nmembs-1; i++) {
- assert(dt->shared->u.compnd.memb[i].offset <
- dt->shared->u.compnd.memb[i+1].offset);
- }
+ for(i = 0; i < (nmembs - 1); i++)
+ HDassert(dt->shared->u.compnd.memb[i].offset < dt->shared->u.compnd.memb[i + 1].offset);
#endif
- }
- } else if (H5T_ENUM==dt->shared->type) {
- if (H5T_SORT_VALUE!=dt->shared->u.enumer.sorted) {
+ } /* end if */
+ } else if(H5T_ENUM == dt->shared->type) {
+ if(H5T_SORT_VALUE != dt->shared->u.enumer.sorted) {
dt->shared->u.enumer.sorted = H5T_SORT_VALUE;
nmembs = dt->shared->u.enumer.nmembs;
size = dt->shared->size;
- assert(size<=sizeof(tbuf));
- for (i=nmembs-1, swapped=TRUE; i>0 && swapped; --i) {
- for (j=0, swapped=FALSE; j<i; j++) {
- if (HDmemcmp(dt->shared->u.enumer.value+j*size,
- dt->shared->u.enumer.value+(j+1)*size,
- size)>0) {
+ HDassert(size <= sizeof(tbuf));
+ for(i = (nmembs - 1), swapped = TRUE; i > 0 && swapped; --i) {
+ for(j = 0, swapped = FALSE; j < i; j++) {
+ if(HDmemcmp(dt->shared->u.enumer.value + (j * size), dt->shared->u.enumer.value + ((j + 1) * size), size) > 0) {
/* Swap names */
char *tmp = dt->shared->u.enumer.name[j];
- dt->shared->u.enumer.name[j] = dt->shared->u.enumer.name[j+1];
- dt->shared->u.enumer.name[j+1] = tmp;
+ dt->shared->u.enumer.name[j] = dt->shared->u.enumer.name[j + 1];
+ dt->shared->u.enumer.name[j + 1] = tmp;
/* Swap values */
- HDmemcpy(tbuf, dt->shared->u.enumer.value+j*size, size);
- HDmemcpy(dt->shared->u.enumer.value+j*size,
- dt->shared->u.enumer.value+(j+1)*size, size);
- HDmemcpy(dt->shared->u.enumer.value+(j+1)*size, tbuf, size);
+ HDmemcpy(tbuf, dt->shared->u.enumer.value + (j * size), size);
+ HDmemcpy(dt->shared->u.enumer.value + (j * size),
+ dt->shared->u.enumer.value + ((j + 1) * size), size);
+ HDmemcpy(dt->shared->u.enumer.value + ((j + 1) * size), tbuf, size);
/* Swap map */
- if (map) {
+ if(map) {
int x = map[j];
- map[j] = map[j+1];
- map[j+1] = x;
- }
+
+ map[j] = map[j + 1];
+ map[j + 1] = x;
+ } /* end if */
swapped = TRUE;
- }
- }
- }
+ } /* end if */
+ } /* end for */
+ } /* end for */
#ifndef NDEBUG
/* I never trust a sort :-) -RPM */
- for (i=0; i<nmembs-1; i++) {
- assert(HDmemcmp(dt->shared->u.enumer.value+i*size,
- dt->shared->u.enumer.value+(i+1)*size,
- size)<0);
- }
+ for(i = 0; i < (nmembs - 1); i++)
+ HDassert(HDmemcmp(dt->shared->u.enumer.value + (i * size), dt->shared->u.enumer.value + ((i + 1) * size), size) < 0);
#endif
- }
- }
+ } /* end if */
+ } /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5T_sort_value() */
/*-------------------------------------------------------------------------
diff --git a/src/H5Tnative.c b/src/H5Tnative.c
index da478c4..f347d93 100644
--- a/src/H5Tnative.c
+++ b/src/H5Tnative.c
@@ -118,7 +118,7 @@ H5Tget_native_type(hid_t type_id, H5T_direction_t direction)
if((new_dt = H5T_get_native_type(dt, direction, NULL, NULL, &comp_size))==NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "cannot retrieve native type")
- if((ret_value=H5I_register(H5I_DATATYPE, new_dt)) < 0)
+ if((ret_value=H5I_register(H5I_DATATYPE, new_dt, TRUE)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register data type")
done:
@@ -277,7 +277,7 @@ H5T_get_native_type(H5T_t *dtype, H5T_direction_t direction, size_t *struct_alig
/* Construct child compound type and retrieve a list of their IDs, offsets, total size, and alignment for compound type. */
for(i=0; i<nmemb; i++) {
- if((memb_type = H5T_get_member_type(dtype, i))==NULL)
+ if((memb_type = H5T_get_member_type(dtype, i, H5T_COPY_TRANSIENT))==NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "member type retrieval failed")
if((comp_mname[i] = H5T_get_member_name(dtype, i))==NULL)
@@ -343,9 +343,9 @@ H5T_get_native_type(H5T_t *dtype, H5T_direction_t direction, size_t *struct_alig
if((nat_super_type = H5T_get_native_type(super_type, direction, struct_align, offset, comp_size))==NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "base native type retrieval failed")
- if((super_type_id=H5I_register(H5I_DATATYPE, super_type))<0)
+ if((super_type_id=H5I_register(H5I_DATATYPE, super_type, FALSE))<0)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot register datatype")
- if((nat_super_type_id=H5I_register(H5I_DATATYPE, nat_super_type))<0)
+ if((nat_super_type_id=H5I_register(H5I_DATATYPE, nat_super_type, FALSE))<0)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot register datatype")
/* Allocate room for the enum values */
diff --git a/src/H5Toh.c b/src/H5Toh.c
index 2a4ee86..24fc0f1 100644
--- a/src/H5Toh.c
+++ b/src/H5Toh.c
@@ -46,7 +46,8 @@
/********************/
static htri_t H5O_dtype_isa(H5O_t *loc);
-static hid_t H5O_dtype_open(const H5G_loc_t *obj_loc, hid_t dxpl_id);
+static hid_t H5O_dtype_open(const H5G_loc_t *obj_loc, hid_t lapl_id,
+ hid_t dxpl_id, hbool_t app_ref);
static void *H5O_dtype_create(H5F_t *f, void *_crt_info, H5G_loc_t *obj_loc,
hid_t dxpl_id);
static H5O_loc_t *H5O_dtype_get_oloc(hid_t obj_id);
@@ -127,7 +128,7 @@ done:
*-------------------------------------------------------------------------
*/
static hid_t
-H5O_dtype_open(const H5G_loc_t *obj_loc, hid_t dxpl_id)
+H5O_dtype_open(const H5G_loc_t *obj_loc, hid_t UNUSED lapl_id, hid_t dxpl_id, hbool_t app_ref)
{
H5T_t *type = NULL; /* Datatype opened */
hid_t ret_value; /* Return value */
@@ -141,7 +142,7 @@ H5O_dtype_open(const H5G_loc_t *obj_loc, hid_t dxpl_id)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, FAIL, "unable to open datatype")
/* Register an ID for the datatype */
- if((ret_value = H5I_register(H5I_DATATYPE, type)) < 0)
+ if((ret_value = H5I_register(H5I_DATATYPE, type, app_ref)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register datatype")
done:
diff --git a/src/H5Tpkg.h b/src/H5Tpkg.h
index 5cb668d..7ef4b63 100644
--- a/src/H5Tpkg.h
+++ b/src/H5Tpkg.h
@@ -53,10 +53,10 @@
#define H5T_NAMELEN 32
/* Macro to ease detecting "complex" datatypes (i.e. those with base types or fields) */
-#define H5T_IS_COMPLEX(t) ((t)==H5T_COMPOUND || (t)==H5T_ENUM || (t)==H5T_VLEN || (t)==H5T_ARRAY)
+#define H5T_IS_COMPLEX(t) ((t) == H5T_COMPOUND || (t) == H5T_ENUM || (t) == H5T_VLEN || (t) == H5T_ARRAY)
/* Macro to ease detecting fixed "string" datatypes */
-#define H5T_IS_FIXED_STRING(dt) (H5T_STRING == (dt)->type)
+#define H5T_IS_FIXED_STRING(dt) (H5T_STRING == (dt)->type)
/* Macro to ease detecting variable-length "string" datatypes */
#define H5T_IS_VL_STRING(dt) (H5T_VLEN == (dt)->type && H5T_VLEN_STRING == (dt)->u.vlen.type)
@@ -65,7 +65,14 @@
#define H5T_IS_STRING(dt) (H5T_IS_FIXED_STRING(dt) || H5T_IS_VL_STRING(dt))
/* Macro to ease detecting atomic datatypes */
-#define H5T_IS_ATOMIC(dt) (!(H5T_IS_COMPLEX((dt)->type) || (dt)->type==H5T_OPAQUE))
+#define H5T_IS_ATOMIC(dt) (!(H5T_IS_COMPLEX((dt)->type) || (dt)->type == H5T_OPAQUE))
+
+/* Macro to ease retrieving class of shared datatype */
+/* (Externally, a VL string is a string; internally, a VL string is a VL. Lie
+ * to the user if they have a VL string and tell them it's in the string
+ * class)
+ */
+#define H5T_GET_CLASS(shared, internal) ((internal) ? (shared)->type : (H5T_IS_VL_STRING(shared) ? H5T_STRING : (shared)->type))
/*
@@ -226,8 +233,8 @@ struct H5T_stats_t {
/* The datatype conversion database */
struct H5T_path_t {
char name[H5T_NAMELEN]; /*name for debugging only */
- H5T_t *src; /*source datatype ID */
- H5T_t *dst; /*destination datatype ID */
+ H5T_t *src; /*source datatype */
+ H5T_t *dst; /*destination datatype */
H5T_conv_t func; /*data conversion function */
hbool_t is_hard; /*is it a hard function? */
hbool_t is_noop; /*is it the noop conversion? */
@@ -277,13 +284,21 @@ typedef enum H5T_sort_t {
H5T_SORT_VALUE = 2 /*sorted by memb offset or enum value*/
} H5T_sort_t;
+/* A compound datatype member */
+typedef struct H5T_cmemb_t {
+ char *name; /*name of this member */
+ size_t offset; /*offset from beginning of struct */
+ size_t size; /*size of this member */
+ struct H5T_t *type; /*type of this member */
+} H5T_cmemb_t;
+
/* A compound datatype */
typedef struct H5T_compnd_t {
unsigned nalloc; /*num entries allocated in MEMB array*/
unsigned nmembs; /*number of members defined in struct*/
H5T_sort_t sorted; /*how are members sorted? */
hbool_t packed; /*are members packed together? */
- struct H5T_cmemb_t *memb; /*array of struct members */
+ H5T_cmemb_t *memb; /*array of struct members */
} H5T_compnd_t;
/* An enumeration datatype */
@@ -306,7 +321,7 @@ typedef herr_t (*H5T_vlen_setnullfunc_t)(H5F_t *f, hid_t dxpl_id, void *_vl, voi
/* VL types */
typedef enum {
H5T_VLEN_BADTYPE = -1, /* invalid VL Type */
- H5T_VLEN_SEQUENCE=0, /* VL sequence */
+ H5T_VLEN_SEQUENCE = 0, /* VL sequence */
H5T_VLEN_STRING, /* VL string */
H5T_VLEN_MAXTYPE /* highest type (Invalid as true type) */
} H5T_vlen_type_t;
@@ -340,9 +355,9 @@ typedef struct H5T_array_t {
} H5T_array_t;
typedef enum H5T_state_t {
- H5T_STATE_TRANSIENT, /*type is a modifiable transient */
- H5T_STATE_RDONLY, /*transient, not modifiable, closable*/
- H5T_STATE_IMMUTABLE, /*constant, not closable */
+ H5T_STATE_TRANSIENT, /*type is a modifiable, closable transient */
+ H5T_STATE_RDONLY, /*transient, not modifiable, closable */
+ H5T_STATE_IMMUTABLE, /*transient, not modifiable, not closable */
H5T_STATE_NAMED, /*named constant, not open */
H5T_STATE_OPEN /*named constant, open object header */
} H5T_state_t;
@@ -374,14 +389,6 @@ struct H5T_t {
H5G_name_t path; /* group hier. path if the type is a named type */
};
-/* A compound datatype member */
-typedef struct H5T_cmemb_t {
- char *name; /*name of this member */
- size_t offset; /*offset from beginning of struct */
- size_t size; /*total size: dims * type_size */
- struct H5T_t *type; /*type of this member */
-} H5T_cmemb_t;
-
/* The master list of soft conversion functions */
typedef struct H5T_soft_t {
char name[H5T_NAMELEN]; /*name for debugging only */
@@ -1364,8 +1371,7 @@ H5_DLL H5T_t * H5T_vlen_create(const H5T_t *base);
H5_DLL htri_t H5T_vlen_set_loc(const H5T_t *dt, H5F_t *f, H5T_loc_t loc);
/* Array functions */
-H5_DLL H5T_t * H5T_array_create(H5T_t *base, unsigned ndims,
- const hsize_t dim[/* ndims */]);
+H5_DLL H5T_t *H5T_array_create(H5T_t *base, unsigned ndims, const hsize_t dim[/* ndims */]);
H5_DLL int H5T_get_array_ndims(const H5T_t *dt);
H5_DLL int H5T_get_array_dims(const H5T_t *dt, hsize_t dims[]);
@@ -1374,7 +1380,7 @@ H5_DLL herr_t H5T_insert(H5T_t *parent, const char *name, size_t offset,
const H5T_t *member);
H5_DLL size_t H5T_get_member_size(const H5T_t *dt, unsigned membno);
H5_DLL htri_t H5T_is_packed(const H5T_t *dt);
-H5_DLL H5T_subset_t H5T_conv_struct_subset(const H5T_cdata_t *cdata);
+H5_DLL H5T_subset_info_t *H5T_conv_struct_subset(const H5T_cdata_t *cdata);
/* Enumerated type functions */
H5_DLL H5T_t *H5T_enum_create(const H5T_t *parent);
diff --git a/src/H5Tprivate.h b/src/H5Tprivate.h
index dfe2367..9189f04 100644
--- a/src/H5Tprivate.h
+++ b/src/H5Tprivate.h
@@ -33,7 +33,20 @@
/* Macro for size of temporary buffers to contain a single element */
#define H5T_ELEM_BUF_SIZE 256
-/* Forward references of package typedefs */
+/* If the module using this macro is allowed access to the private variables, access them directly */
+#ifdef H5T_PACKAGE
+#define H5T_GET_SIZE(T) ((T)->shared->size)
+#define H5T_GET_SHARED(T) ((T)->shared)
+#define H5T_GET_MEMBER_OFFSET(T, I) ((T)->u.compnd.memb[I].offset)
+#define H5T_GET_MEMBER_SIZE(T, I) ((T)->u.compnd.memb[I].shared->size)
+#else /* H5T_PACKAGE */
+#define H5T_GET_SIZE(T) (H5T_get_size(T))
+#define H5T_GET_SHARED(T) (H5T_get_shared(T))
+#define H5T_GET_MEMBER_OFFSET(T, I) (H5T_get_member_offset((T), (I)))
+#define H5T_GET_MEMBER_SIZE(T, I) (H5T_get_member_size((T), (I)))
+#endif /* H5T_PACKAGE */
+
+/* Forward references of package typedefs (declared in H5Tpkg.h) */
typedef struct H5T_t H5T_t;
typedef struct H5T_stats_t H5T_stats_t;
typedef struct H5T_path_t H5T_path_t;
@@ -69,16 +82,21 @@ typedef struct H5T_conv_cb_t {
/* Values for the optimization of compound data reading and writing. They indicate
* whether the fields of the source and destination are subset of each other and
- * there is no conversion needed. It's for the Chicago company.
+ * there is no conversion needed.
*/
typedef enum {
H5T_SUBSET_BADVALUE = -1, /* Invalid value */
- H5T_SUBSET_FALSE = 0, /* Source and destination aren't subset of each other */
+ H5T_SUBSET_FALSE = 0, /* Source and destination aren't subset of each other */
H5T_SUBSET_SRC, /* Source is the subset of dest and no conversion is needed */
H5T_SUBSET_DST, /* Dest is the subset of source and no conversion is needed */
H5T_SUBSET_CAP /* Must be the last value */
} H5T_subset_t;
+typedef struct H5T_subset_info_t {
+ H5T_subset_t subset; /* See above */
+ size_t copy_size; /* Size in bytes, to copy for each element */
+} H5T_subset_info_t;
+
/* Forward declarations for prototype arguments */
struct H5O_t;
@@ -103,13 +121,13 @@ H5_DLL htri_t H5T_is_immutable(const H5T_t *dt);
H5_DLL htri_t H5T_is_named(const H5T_t *dt);
H5_DLL htri_t H5T_is_relocatable(const H5T_t *dt);
H5_DLL H5T_path_t *H5T_path_find(const H5T_t *src, const H5T_t *dst,
- const char *name, H5T_conv_t func, hid_t dxpl_id, hbool_t is_api);
+ const char *name, H5T_conv_t func, hid_t dxpl_id, hbool_t is_api);
H5_DLL hbool_t H5T_path_noop(const H5T_path_t *p);
H5_DLL H5T_bkg_t H5T_path_bkg(const H5T_path_t *p);
-H5_DLL H5T_subset_t H5T_path_compound_subset(const H5T_path_t *p);
+H5_DLL H5T_subset_info_t *H5T_path_compound_subset(const H5T_path_t *p);
H5_DLL herr_t H5T_convert(H5T_path_t *tpath, hid_t src_id, hid_t dst_id,
- size_t nelmts, size_t buf_stride, size_t bkg_stride,
- void *buf, void *bkg, hid_t dset_xfer_plist);
+ size_t nelmts, size_t buf_stride, size_t bkg_stride, void *buf, void *bkg,
+ hid_t dset_xfer_plist);
H5_DLL herr_t H5T_vlen_reclaim(void *elem, hid_t type_id, unsigned ndim, const hsize_t *point, void *_op_data);
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);
@@ -129,7 +147,7 @@ H5_DLL herr_t H5T_update_shared(H5T_t *type);
/* Field functions (for both compound & enumerated types) */
H5_DLL int H5T_get_nmembers(const H5T_t *dt);
-H5_DLL H5T_t *H5T_get_member_type(const H5T_t *dt, unsigned membno);
+H5_DLL H5T_t *H5T_get_member_type(const H5T_t *dt, unsigned membno, H5T_copy_t method);
H5_DLL size_t H5T_get_member_offset(const H5T_t *dt, unsigned membno);
/* Atomic functions */
diff --git a/src/H5Tpublic.h b/src/H5Tpublic.h
index 40a2a4d..95539ab 100644
--- a/src/H5Tpublic.h
+++ b/src/H5Tpublic.h
@@ -592,7 +592,7 @@ H5_DLL herr_t H5Tconvert(hid_t src_id, hid_t dst_id, size_t nelmts,
void *buf, void *background, hid_t plist_id);
/* Symbols defined for compatibility with previous versions of the HDF5 API.
- *
+ *
* Use of these symbols is deprecated.
*/
#ifndef H5_NO_DEPRECATED_SYMBOLS
diff --git a/src/H5Tvisit.c b/src/H5Tvisit.c
index bd30a43..44e06fe 100644
--- a/src/H5Tvisit.c
+++ b/src/H5Tvisit.c
@@ -151,5 +151,5 @@ H5T_visit(H5T_t *dt, unsigned visit_flags, H5T_operator_t op, void *op_value)
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5T_iterate() */
+} /* end H5T_visit() */
diff --git a/src/H5Tvlen.c b/src/H5Tvlen.c
index bbc698f..27eb0f6 100644
--- a/src/H5Tvlen.c
+++ b/src/H5Tvlen.c
@@ -123,7 +123,7 @@ H5Tvlen_create(hid_t base_id)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid VL location")
/* Atomize the type */
- if((ret_value = H5I_register(H5I_DATATYPE, dt)) < 0)
+ if((ret_value = H5I_register(H5I_DATATYPE, dt, TRUE)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register datatype")
done:
@@ -203,68 +203,63 @@ done:
* Programmer: Quincey Koziol
* Friday, June 4, 1999
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
htri_t
H5T_vlen_set_loc(const H5T_t *dt, H5F_t *f, H5T_loc_t loc)
{
- htri_t ret_value = 0; /* Indicate that success, but no location change */
+ htri_t ret_value = FALSE; /* Indicate success, but no location change */
FUNC_ENTER_NOAPI_NOINIT(H5T_vlen_set_loc)
/* check parameters */
- assert(dt);
- assert(loc>H5T_LOC_BADLOC && loc<H5T_LOC_MAXLOC);
+ HDassert(dt);
+ HDassert(loc > H5T_LOC_BADLOC && loc < H5T_LOC_MAXLOC);
/* Only change the location if it's different */
if(loc != dt->shared->u.vlen.loc || f != dt->shared->u.vlen.f) {
- /* Indicate that the location changed */
- ret_value=TRUE;
-
switch(loc) {
case H5T_LOC_MEMORY: /* Memory based VL datatype */
- assert(f==NULL);
+ HDassert(NULL == f);
/* Mark this type as being stored in memory */
- dt->shared->u.vlen.loc=H5T_LOC_MEMORY;
+ dt->shared->u.vlen.loc = H5T_LOC_MEMORY;
- if(dt->shared->u.vlen.type==H5T_VLEN_SEQUENCE) {
+ if(dt->shared->u.vlen.type == H5T_VLEN_SEQUENCE) {
/* size in memory, disk size is different */
dt->shared->size = sizeof(hvl_t);
/* Set up the function pointers to access the VL sequence in memory */
- dt->shared->u.vlen.getlen=H5T_vlen_seq_mem_getlen;
- dt->shared->u.vlen.getptr=H5T_vlen_seq_mem_getptr;
- dt->shared->u.vlen.isnull=H5T_vlen_seq_mem_isnull;
- dt->shared->u.vlen.read=H5T_vlen_seq_mem_read;
- dt->shared->u.vlen.write=H5T_vlen_seq_mem_write;
- dt->shared->u.vlen.setnull=H5T_vlen_seq_mem_setnull;
- } else if(dt->shared->u.vlen.type==H5T_VLEN_STRING) {
+ dt->shared->u.vlen.getlen = H5T_vlen_seq_mem_getlen;
+ dt->shared->u.vlen.getptr = H5T_vlen_seq_mem_getptr;
+ dt->shared->u.vlen.isnull = H5T_vlen_seq_mem_isnull;
+ dt->shared->u.vlen.read = H5T_vlen_seq_mem_read;
+ dt->shared->u.vlen.write = H5T_vlen_seq_mem_write;
+ dt->shared->u.vlen.setnull = H5T_vlen_seq_mem_setnull;
+ } else if(dt->shared->u.vlen.type == H5T_VLEN_STRING) {
/* size in memory, disk size is different */
dt->shared->size = sizeof(char *);
/* Set up the function pointers to access the VL string in memory */
- dt->shared->u.vlen.getlen=H5T_vlen_str_mem_getlen;
- dt->shared->u.vlen.getptr=H5T_vlen_str_mem_getptr;
- dt->shared->u.vlen.isnull=H5T_vlen_str_mem_isnull;
- dt->shared->u.vlen.read=H5T_vlen_str_mem_read;
- dt->shared->u.vlen.write=H5T_vlen_str_mem_write;
- dt->shared->u.vlen.setnull=H5T_vlen_str_mem_setnull;
+ dt->shared->u.vlen.getlen = H5T_vlen_str_mem_getlen;
+ dt->shared->u.vlen.getptr = H5T_vlen_str_mem_getptr;
+ dt->shared->u.vlen.isnull = H5T_vlen_str_mem_isnull;
+ dt->shared->u.vlen.read = H5T_vlen_str_mem_read;
+ dt->shared->u.vlen.write = H5T_vlen_str_mem_write;
+ dt->shared->u.vlen.setnull = H5T_vlen_str_mem_setnull;
} else {
- assert(0 && "Invalid VL type");
+ HDassert(0 && "Invalid VL type");
}
/* Reset file ID (since this VL is in memory) */
- dt->shared->u.vlen.f=NULL;
+ dt->shared->u.vlen.f = NULL;
break;
case H5T_LOC_DISK: /* Disk based VL datatype */
- assert(f);
+ HDassert(f);
/* Mark this type as being stored on disk */
- dt->shared->u.vlen.loc=H5T_LOC_DISK;
+ dt->shared->u.vlen.loc = H5T_LOC_DISK;
/*
* Size of element on disk is 4 bytes for the length, plus the size
@@ -275,20 +270,23 @@ H5T_vlen_set_loc(const H5T_t *dt, H5F_t *f, H5T_loc_t loc)
/* Set up the function pointers to access the VL information on disk */
/* VL sequences and VL strings are stored identically on disk, so use the same functions */
- dt->shared->u.vlen.getlen=H5T_vlen_disk_getlen;
- dt->shared->u.vlen.getptr=H5T_vlen_disk_getptr;
- dt->shared->u.vlen.isnull=H5T_vlen_disk_isnull;
- dt->shared->u.vlen.read=H5T_vlen_disk_read;
- dt->shared->u.vlen.write=H5T_vlen_disk_write;
- dt->shared->u.vlen.setnull=H5T_vlen_disk_setnull;
+ dt->shared->u.vlen.getlen = H5T_vlen_disk_getlen;
+ dt->shared->u.vlen.getptr = H5T_vlen_disk_getptr;
+ dt->shared->u.vlen.isnull = H5T_vlen_disk_isnull;
+ dt->shared->u.vlen.read = H5T_vlen_disk_read;
+ dt->shared->u.vlen.write = H5T_vlen_disk_write;
+ dt->shared->u.vlen.setnull = H5T_vlen_disk_setnull;
/* Set file ID (since this VL is on disk) */
- dt->shared->u.vlen.f=f;
+ dt->shared->u.vlen.f = f;
break;
default:
HGOTO_ERROR(H5E_DATATYPE, H5E_BADRANGE, FAIL, "invalid VL datatype location")
} /* end switch */ /*lint !e788 All appropriate cases are covered */
+
+ /* Indicate that the location changed */
+ ret_value = TRUE;
} /* end if */
done:
@@ -306,21 +304,35 @@ done:
* Programmer: Quincey Koziol
* Wednesday, June 2, 1999
*
- * Modifications:
+ * Modifications: Neil Fortner
+ * Friday, August 22, 2008
+ * Changed function to be tolerant of an hvl_t that is not aligned
+ * properly in _vl.
*
*-------------------------------------------------------------------------
*/
static ssize_t
H5T_vlen_seq_mem_getlen(const void *_vl)
{
+#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
const hvl_t *vl=(const hvl_t *)_vl; /* Pointer to the user's hvl_t information */
+#else
+ hvl_t vl; /* User's hvl_t information */
+#endif
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_vlen_seq_mem_getlen)
- /* check parameters */
- assert(vl);
+ /* check parameters, return result */
+#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
+ HDassert(vl);
FUNC_LEAVE_NOAPI((ssize_t)vl->len)
+#else
+ HDassert(_vl);
+ HDmemcpy(&vl, _vl, sizeof(hvl_t));
+
+ FUNC_LEAVE_NOAPI((ssize_t)vl.len)
+#endif
} /* end H5T_vlen_seq_mem_getlen() */
@@ -334,21 +346,35 @@ H5T_vlen_seq_mem_getlen(const void *_vl)
* Programmer: Quincey Koziol
* Saturday, June 12, 2004
*
- * Modifications:
+ * Modifications: Neil Fortner
+ * Friday, August 22, 2008
+ * Changed function to be tolerant of an hvl_t that is not aligned
+ * properly in _vl.
*
*-------------------------------------------------------------------------
*/
static void *
H5T_vlen_seq_mem_getptr(void *_vl)
{
- hvl_t *vl=(hvl_t *)_vl; /* Pointer to the user's hvl_t information */
+#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
+ const hvl_t *vl=(const hvl_t *)_vl; /* Pointer to the user's hvl_t information */
+#else
+ hvl_t vl; /* User's hvl_t information */
+#endif
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_vlen_seq_mem_getptr)
- /* check parameters */
- assert(vl);
+ /* check parameters, return result */
+#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
+ HDassert(vl);
FUNC_LEAVE_NOAPI(vl->p)
+#else
+ HDassert(_vl);
+ HDmemcpy(&vl, _vl, sizeof(hvl_t));
+
+ FUNC_LEAVE_NOAPI(vl.p)
+#endif
} /* end H5T_vlen_seq_mem_getptr() */
@@ -362,7 +388,10 @@ H5T_vlen_seq_mem_getptr(void *_vl)
* Programmer: Quincey Koziol
* Saturday, November 8, 2003
*
- * Modifications:
+ * Modifications: Neil Fortner
+ * Friday, August 22, 2008
+ * Changed function to be tolerant of an hvl_t that is not aligned
+ * properly in _vl.
*
*-------------------------------------------------------------------------
*/
@@ -370,14 +399,25 @@ H5T_vlen_seq_mem_getptr(void *_vl)
static htri_t
H5T_vlen_seq_mem_isnull(const H5F_t UNUSED *f, void *_vl)
{
- hvl_t *vl=(hvl_t *)_vl; /* Pointer to the user's hvl_t information */
+#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
+ const hvl_t *vl=(const hvl_t *)_vl; /* Pointer to the user's hvl_t information */
+#else
+ hvl_t vl; /* User's hvl_t information */
+#endif
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_vlen_seq_mem_isnull)
- /* check parameters */
- assert(vl);
+ /* check parameters, return result */
+#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
+ HDassert(vl);
FUNC_LEAVE_NOAPI((vl->len==0 || vl->p==NULL) ? TRUE : FALSE)
+#else
+ HDassert(_vl);
+ HDmemcpy(&vl, _vl, sizeof(hvl_t));
+
+ FUNC_LEAVE_NOAPI((vl.len==0 || vl.p==NULL) ? TRUE : FALSE)
+#endif
} /* end H5T_vlen_seq_mem_isnull() */
@@ -391,7 +431,10 @@ H5T_vlen_seq_mem_isnull(const H5F_t UNUSED *f, void *_vl)
* Programmer: Quincey Koziol
* Wednesday, June 2, 1999
*
- * Modifications:
+ * Modifications: Neil Fortner
+ * Friday, August 22, 2008
+ * Changed function to be tolerant of an hvl_t that is not aligned
+ * properly in _vl.
*
*-------------------------------------------------------------------------
*/
@@ -399,15 +442,27 @@ H5T_vlen_seq_mem_isnull(const H5F_t UNUSED *f, void *_vl)
static herr_t
H5T_vlen_seq_mem_read(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, void *_vl, void *buf, size_t len)
{
- hvl_t *vl=(hvl_t *)_vl; /* Pointer to the user's hvl_t information */
+#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
+ const hvl_t *vl=(const hvl_t *)_vl; /* Pointer to the user's hvl_t information */
+#else
+ hvl_t vl; /* User's hvl_t information */
+#endif
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_vlen_seq_mem_read)
- /* check parameters */
- assert(vl && vl->p);
- assert(buf);
+ /* check parameters, copy data */
+ HDassert(buf);
+#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
+ HDassert(vl && vl->p);
HDmemcpy(buf,vl->p,len);
+#else
+ HDassert(_vl);
+ HDmemcpy(&vl, _vl, sizeof(hvl_t));
+ HDassert(vl.p);
+
+ HDmemcpy(buf,vl.p,len);
+#endif
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5T_vlen_seq_mem_read() */
@@ -438,8 +493,8 @@ H5T_vlen_seq_mem_write(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const H5T_vlen_all
FUNC_ENTER_NOAPI_NOINIT(H5T_vlen_seq_mem_write)
/* check parameters */
- assert(_vl);
- assert(buf);
+ HDassert(_vl);
+ HDassert(buf);
if(seq_len!=0) {
len=seq_len*base_size;
@@ -495,7 +550,7 @@ H5T_vlen_seq_mem_setnull(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, void *_vl, void
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_vlen_seq_mem_setnull)
/* check parameters */
- assert(_vl);
+ HDassert(_vl);
/* Set the "nil" hvl_t */
vl.len=0;
@@ -518,19 +573,31 @@ H5T_vlen_seq_mem_setnull(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, void *_vl, void
* Programmer: Quincey Koziol
* Wednesday, June 2, 1999
*
- * Modifications:
+ * Modifications: Neil Fortner
+ * Friday, August 22, 2008
+ * Changed function to be tolerant of a char * that is not aligned
+ * properly in _vl.
*
*-------------------------------------------------------------------------
*/
static ssize_t
H5T_vlen_str_mem_getlen(const void *_vl)
{
+#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
const char *s=*(const char * const *)_vl; /* Pointer to the user's string information */
+#else
+ const char *s; /* Pointer to the user's string information */
+#endif
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_vlen_str_mem_getlen)
/* check parameters */
- assert(s);
+#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
+ HDassert(s);
+#else
+ HDassert(_vl);
+ HDmemcpy(&s, _vl, sizeof(char *));
+#endif
FUNC_LEAVE_NOAPI((ssize_t)HDstrlen(s))
} /* end H5T_vlen_str_mem_getlen() */
@@ -546,19 +613,32 @@ H5T_vlen_str_mem_getlen(const void *_vl)
* Programmer: Quincey Koziol
* Saturday, June 12, 2004
*
- * Modifications:
+ * Modifications: Neil Fortner
+ * Friday, August 22, 2008
+ * Changed function to be tolerant of a char * that is not aligned
+ * properly in _vl.
+ * Added assertion on _vl.
*
*-------------------------------------------------------------------------
*/
static void *
H5T_vlen_str_mem_getptr(void *_vl)
{
+#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
char *s=*(char **)_vl; /* Pointer to the user's string information */
+#else
+ char *s; /* Pointer to the user's string information */
+#endif
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_vlen_str_mem_getptr)
/* check parameters */
- assert(s);
+#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
+ HDassert(s);
+#else
+ HDassert(_vl);
+ HDmemcpy(&s, _vl, sizeof(char *));
+#endif
FUNC_LEAVE_NOAPI(s)
} /* end H5T_vlen_str_mem_getptr() */
@@ -574,7 +654,10 @@ H5T_vlen_str_mem_getptr(void *_vl)
* Programmer: Quincey Koziol
* Saturday, November 8, 2003
*
- * Modifications:
+ * Modifications: Neil Fortner
+ * Friday, August 22, 2008
+ * Changed function to be tolerant of a char * that is not aligned
+ * properly in _vl.
*
*-------------------------------------------------------------------------
*/
@@ -582,10 +665,18 @@ H5T_vlen_str_mem_getptr(void *_vl)
static htri_t
H5T_vlen_str_mem_isnull(const H5F_t UNUSED *f, void *_vl)
{
+#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
char *s=*(char **)_vl; /* Pointer to the user's string information */
+#else
+ char *s; /* Pointer to the user's string information */
+#endif
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_vlen_str_mem_isnull)
+#ifndef H5_NO_ALIGNMENT_RESTRICTIONS
+ HDmemcpy(&s, _vl, sizeof(char *));
+#endif
+
FUNC_LEAVE_NOAPI(s==NULL ? TRUE : FALSE)
} /* end H5T_vlen_str_mem_isnull() */
@@ -600,7 +691,10 @@ H5T_vlen_str_mem_isnull(const H5F_t UNUSED *f, void *_vl)
* Programmer: Quincey Koziol
* Wednesday, June 2, 1999
*
- * Modifications:
+ * Modifications: Neil Fortner
+ * Friday, August 22, 2008
+ * Changed function to be tolerant of a char * that is not aligned
+ * properly in _vl.
*
*-------------------------------------------------------------------------
*/
@@ -608,14 +702,23 @@ H5T_vlen_str_mem_isnull(const H5F_t UNUSED *f, void *_vl)
static herr_t
H5T_vlen_str_mem_read(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, void *_vl, void *buf, size_t len)
{
- char *s=*(char **)_vl; /* Pointer to the user's hvl_t information */
+#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
+ char *s=*(char **)_vl; /* Pointer to the user's string information */
+#else
+ char *s; /* Pointer to the user's string information */
+#endif
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_vlen_str_mem_read)
if(len>0) {
/* check parameters */
- assert(s);
- assert(buf);
+ HDassert(buf);
+#ifdef H5_NO_ALIGNMENT_RESTRICTIONS
+ HDassert(s);
+#else
+ HDassert(_vl);
+ HDmemcpy(&s, _vl, sizeof(char *));
+#endif
HDmemcpy(buf,s,len);
} /* end if */
@@ -649,7 +752,7 @@ H5T_vlen_str_mem_write(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const H5T_vlen_all
FUNC_ENTER_NOAPI_NOINIT(H5T_vlen_str_mem_write)
/* check parameters */
- assert(buf);
+ HDassert(buf);
/* Use the user's memory allocation routine if one is defined */
if(vl_alloc_info->alloc_func!=NULL) {
@@ -725,7 +828,7 @@ H5T_vlen_disk_getlen(const void *_vl)
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_vlen_disk_getlen)
/* check parameters */
- assert(vl);
+ HDassert(vl);
UINT32DECODE(vl, seq_len);
@@ -754,7 +857,7 @@ H5T_vlen_disk_getptr(void UNUSED *vl)
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_vlen_disk_getptr)
/* check parameters */
- assert(vl);
+ HDassert(vl);
FUNC_LEAVE_NOAPI(NULL)
} /* end H5T_vlen_disk_getptr() */
@@ -783,7 +886,7 @@ H5T_vlen_disk_isnull(const H5F_t *f, void *_vl)
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_vlen_disk_isnull)
/* check parameters */
- assert(vl);
+ HDassert(vl);
/* Skip the sequence's length */
vl+=4;
@@ -820,9 +923,9 @@ H5T_vlen_disk_read(H5F_t *f, hid_t dxpl_id, void *_vl, void *buf, size_t UNUSED
FUNC_ENTER_NOAPI_NOINIT(H5T_vlen_disk_read)
/* check parameters */
- assert(vl);
- assert(buf);
- assert(f);
+ HDassert(vl);
+ HDassert(buf);
+ HDassert(f);
/* Skip the length of the sequence */
vl += 4;
@@ -874,9 +977,9 @@ H5T_vlen_disk_write(H5F_t *f, hid_t dxpl_id, const H5T_vlen_alloc_info_t UNUSED
FUNC_ENTER_NOAPI_NOINIT(H5T_vlen_disk_write)
/* check parameters */
- assert(vl);
- assert(seq_len==0 || buf);
- assert(f);
+ HDassert(vl);
+ HDassert(seq_len==0 || buf);
+ HDassert(f);
/* Free heap object for old data. */
if(bg!=NULL) {
@@ -939,8 +1042,8 @@ H5T_vlen_disk_setnull(H5F_t *f, hid_t dxpl_id, void *_vl, void *_bg)
FUNC_ENTER_NOAPI_NOINIT(H5T_vlen_disk_setnull)
/* check parameters */
- assert(f);
- assert(vl);
+ HDassert(f);
+ HDassert(vl);
/* Free heap object for old data. */
if(bg!=NULL) {
@@ -1002,8 +1105,8 @@ H5T_vlen_reclaim_recurse(void *elem, const H5T_t *dt, H5MM_free_t free_func, voi
FUNC_ENTER_NOAPI_NOINIT(H5T_vlen_reclaim_recurse)
- assert(elem);
- assert(dt);
+ HDassert(elem);
+ HDassert(dt);
/* Check the datatype of this element */
switch(dt->shared->type) {
@@ -1069,7 +1172,7 @@ H5T_vlen_reclaim_recurse(void *elem, const H5T_t *dt, H5MM_free_t free_func, voi
else
H5MM_xfree(*(char **)elem);
} else {
- assert(0 && "Invalid VL type");
+ HDassert(0 && "Invalid VL type");
} /* end else */
break;
@@ -1116,9 +1219,9 @@ H5T_vlen_reclaim(void *elem, hid_t type_id, unsigned UNUSED ndim, const hsize_t
FUNC_ENTER_NOAPI(H5T_vlen_reclaim, FAIL)
- assert(elem);
- assert(vl_alloc_info);
- assert(H5I_DATATYPE == H5I_get_type(type_id));
+ HDassert(elem);
+ HDassert(vl_alloc_info);
+ HDassert(H5I_DATATYPE == H5I_get_type(type_id));
/* Check args */
if (NULL==(dt=H5I_object_verify(type_id,H5I_DATATYPE)))
@@ -1163,8 +1266,8 @@ H5T_vlen_get_alloc_info(hid_t dxpl_id, H5T_vlen_alloc_info_t **vl_alloc_info)
FUNC_ENTER_NOAPI(H5T_vlen_get_alloc_info, FAIL)
- assert(H5I_GENPROP_LST == H5I_get_type(dxpl_id));
- assert(vl_alloc_info);
+ HDassert(H5I_GENPROP_LST == H5I_get_type(dxpl_id));
+ HDassert(vl_alloc_info);
/* Check for the default DXPL */
if(dxpl_id==H5P_DATASET_XFER_DEFAULT)
diff --git a/src/H5V.c b/src/H5V.c
index 3e06636..34cf714 100644
--- a/src/H5V.c
+++ b/src/H5V.c
@@ -399,33 +399,34 @@ done:
*/
htri_t
H5V_hyper_disjointp(unsigned n,
- const hsize_t *offset1, const size_t *size1,
- const hsize_t *offset2, const size_t *size2)
+ const hsize_t *offset1, const uint32_t *size1,
+ const hsize_t *offset2, const uint32_t *size2)
{
unsigned u;
- htri_t ret_value=FALSE; /* Return value */
+ htri_t ret_value = FALSE; /* Return value */
/* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5V_hyper_disjointp)
- if (!n || !size1 || !size2) HGOTO_DONE(TRUE)
+ if(!n || !size1 || !size2)
+ HGOTO_DONE(TRUE)
- for (u=0; u<n; u++) {
- assert (size1[u]<HSIZET_MAX);
- assert (size2[u]<HSIZET_MAX);
+ for(u = 0; u < n; u++) {
+ HDassert(size1[u] < HSIZET_MAX);
+ HDassert(size2[u] < HSIZET_MAX);
- if (0==size1[u] || 0==size2[u])
+ if(0 == size1[u] || 0 == size2[u])
HGOTO_DONE(TRUE)
- if (((offset1?offset1[u]:0) < (offset2?offset2[u]:0) &&
- ((offset1?offset1[u]:0) + size1[u] <= (offset2?offset2[u]:0))) ||
- ((offset2?offset2[u]:0) < (offset1?offset1[u]:0) &&
- ((offset2?offset2[u]:0) + size2[u] <= (offset1?offset1[u]:0))))
+ if(((offset1 ? offset1[u] : 0) < (offset2 ? offset2[u] : 0) &&
+ ((offset1 ? offset1[u] : 0) + size1[u] <= (offset2 ? offset2[u] : 0))) ||
+ ((offset2 ? offset2[u] : 0) < (offset1 ? offset1[u] : 0) &&
+ ((offset2 ? offset2[u] : 0) + size2[u] <= (offset1 ? offset1[u] : 0))))
HGOTO_DONE(TRUE)
- }
+ } /* end for */
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
+} /* end H5V_hyper_disjointp() */
/*-------------------------------------------------------------------------
@@ -1225,7 +1226,7 @@ H5V_array_calc(hsize_t offset, unsigned n, const hsize_t *total_size, hsize_t *c
*-------------------------------------------------------------------------
*/
herr_t
-H5V_chunk_index(unsigned ndims, const hsize_t *coord, const size_t *chunk,
+H5V_chunk_index(unsigned ndims, const hsize_t *coord, const uint32_t *chunk,
const hsize_t *down_nchunks, hsize_t *chunk_idx)
{
hsize_t scaled_coord[H5V_HYPER_NDIMS]; /* Scaled, coordinates, in terms of chunks */
diff --git a/src/H5Vprivate.h b/src/H5Vprivate.h
index 94b3699..1dec0c0 100644
--- a/src/H5Vprivate.h
+++ b/src/H5Vprivate.h
@@ -53,9 +53,7 @@ H5_DLL hsize_t H5V_hyper_stride(unsigned n, const hsize_t *size,
const hsize_t *offset,
hsize_t *stride);
H5_DLL htri_t H5V_hyper_disjointp(unsigned n, const hsize_t *offset1,
- const size_t *size1,
- const hsize_t *offset2,
- const size_t *size2);
+ const uint32_t *size1, const hsize_t *offset2, const uint32_t *size2);
H5_DLL htri_t H5V_hyper_eq(unsigned n, const hsize_t *offset1,
const hsize_t *size1, const hsize_t *offset2,
const hsize_t *size2);
@@ -88,7 +86,7 @@ H5_DLL hsize_t H5V_array_offset(unsigned n, const hsize_t *total_size,
H5_DLL herr_t H5V_array_calc(hsize_t offset, unsigned n,
const hsize_t *total_size, hsize_t *coords);
H5_DLL herr_t H5V_chunk_index(unsigned ndims, const hsize_t *coord,
- const size_t *chunk, const hsize_t *down_nchunks, hsize_t *chunk_idx);
+ const uint32_t *chunk, const hsize_t *down_nchunks, hsize_t *chunk_idx);
H5_DLL ssize_t H5V_memcpyvv(void *_dst,
size_t dst_max_nseq, size_t *dst_curr_seq, size_t dst_len_arr[], hsize_t dst_off_arr[],
const void *_src,
@@ -304,7 +302,7 @@ H5V_vector_inc(int n, hsize_t *v1, const hsize_t *v2)
}
/* Lookup table for general log2(n) routine */
-static const char LogTable256[] =
+static const unsigned char LogTable256[] =
{
0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
@@ -358,15 +356,15 @@ H5V_log2_gen(uint64_t n)
#endif /* H5_BAD_LOG2_CODE_GENERATED */
if((ttt = (unsigned)(n >> 32)))
if((tt = (unsigned)(n >> 48)))
- r = (t = (unsigned)(n >> 56)) ? 56 + LogTable256[t] : 48 + LogTable256[tt & 0xFF];
+ r = (t = (unsigned)(n >> 56)) ? 56 + (unsigned)LogTable256[t] : 48 + (unsigned)LogTable256[tt & 0xFF];
else
- r = (t = (unsigned)(n >> 40)) ? 40 + LogTable256[t] : 32 + LogTable256[ttt & 0xFF];
+ r = (t = (unsigned)(n >> 40)) ? 40 + (unsigned)LogTable256[t] : 32 + (unsigned)LogTable256[ttt & 0xFF];
else
if((tt = (unsigned)(n >> 16)))
- r = (t = (unsigned)(n >> 24)) ? 24 + LogTable256[t] : 16 + LogTable256[tt & 0xFF];
+ r = (t = (unsigned)(n >> 24)) ? 24 + (unsigned)LogTable256[t] : 16 + (unsigned)LogTable256[tt & 0xFF];
else
/* Added 'uint8_t' cast to pacify PGCC compiler */
- r = (t = (unsigned)(n >> 8)) ? 8 + LogTable256[t] : LogTable256[(uint8_t)n];
+ r = (t = (unsigned)(n >> 8)) ? 8 + (unsigned)LogTable256[t] : (unsigned)LogTable256[(uint8_t)n];
#ifdef H5_BAD_LOG2_CODE_GENERATED
} /* end else */
#endif /* H5_BAD_LOG2_CODE_GENERATED */
@@ -410,5 +408,85 @@ H5V_log2_of2(uint32_t n)
return(MultiplyDeBruijnBitPosition[(n * (uint32_t)0x077CB531UL) >> 27]);
} /* H5V_log2_of2() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5V_limit_enc_size
+ *
+ * Purpose: Determine the # of bytes needed to encode values within a
+ * range from 0 to a given limit
+ *
+ * Return: Number of bytes needed
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, March 13, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5_inline unsigned UNUSED
+H5V_limit_enc_size(uint64_t limit)
+{
+ return (H5V_log2_gen(limit) / 8) + 1;
+} /* end H5V_limit_enc_size() */
+
+static const unsigned char H5V_bit_set_g[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
+static const unsigned char H5V_bit_clear_g[8] = {0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0xFE};
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5V_bit_get
+ *
+ * Purpose: Determine the value of the n'th bit in a buffer.
+ *
+ * Note: No range checking on <offset> is performed!
+ *
+ * Note #2: Bits are sequentially stored in the buffer, starting with bit
+ * offset 0 in the first byte's high-bit position, proceeding down
+ * to bit offset 7 in the first byte's low-bit position, then to
+ * bit offset 8 in the second byte's high-bit position, etc.
+ *
+ * Return: TRUE/FALSE
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, November 25, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5_inline hbool_t UNUSED
+H5V_bit_get(const unsigned char *buf, size_t offset)
+{
+ /* Test the appropriate bit in the buffer */
+ return (hbool_t)((buf[offset / 8] & (H5V_bit_set_g[offset % 8])) ? TRUE : FALSE);
+} /* end H5V_bit_get() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5V_bit_set
+ *
+ * Purpose: Set/reset the n'th bit in a buffer.
+ *
+ * Note: No range checking on <offset> is performed!
+ *
+ * Note #2: Bits are sequentially stored in the buffer, starting with bit
+ * offset 0 in the first byte's high-bit position, proceeding down
+ * to bit offset 7 in the first byte's low-bit position, then to
+ * bit offset 8 in the second byte's high-bit position, etc.
+ *
+ * Return: None
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, November 25, 2008
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5_inline void UNUSED
+H5V_bit_set(unsigned char *buf, size_t offset, hbool_t val)
+{
+ /* Set/reset the appropriate bit in the buffer */
+ if(val)
+ buf[offset / 8] |= H5V_bit_set_g[offset % 8];
+ else
+ buf[offset / 8] &= H5V_bit_clear_g[offset % 8];
+} /* end H5V_bit_set() */
+
#endif /* H5Vprivate_H */
diff --git a/src/H5Z.c b/src/H5Z.c
index de26831..0a3a8c2 100644
--- a/src/H5Z.c
+++ b/src/H5Z.c
@@ -468,20 +468,20 @@ done:
static herr_t
H5Z_prelude_callback(hid_t dcpl_id, hid_t type_id, H5Z_prelude_type_t prelude_type)
{
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5Z_prelude_callback)
- assert (H5I_GENPROP_LST==H5I_get_type(dcpl_id));
- assert (H5I_DATATYPE==H5I_get_type(type_id));
+ HDassert(H5I_GENPROP_LST == H5I_get_type(dcpl_id));
+ HDassert(H5I_DATATYPE == H5I_get_type(type_id));
/* Check if the property list is non-default */
- if(dcpl_id!=H5P_DATASET_CREATE_DEFAULT) {
+ if(dcpl_id != H5P_DATASET_CREATE_DEFAULT) {
H5P_genplist_t *dc_plist; /* Dataset creation property list object */
H5D_layout_t dcpl_layout; /* Dataset's layout information */
/* Get dataset creation property list object */
- if (NULL == (dc_plist = H5I_object(dcpl_id)))
+ if(NULL == (dc_plist = H5I_object(dcpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get dataset creation property list")
/* Get layout information */
@@ -499,7 +499,7 @@ H5Z_prelude_callback(hid_t dcpl_id, hid_t type_id, H5Z_prelude_type_t prelude_ty
/* Check if the chunks have filters */
if(dcpl_pline.nused > 0) {
unsigned chunk_ndims; /* # of chunk dimensions */
- size_t chunk_size[H5O_LAYOUT_NDIMS]; /* Size of chunk dimensions */
+ uint32_t chunk_size[H5O_LAYOUT_NDIMS]; /* Size of chunk dimensions */
hsize_t chunk_dims[H5O_LAYOUT_NDIMS]; /* Size of chunk dimensions */
H5S_t *space; /* Dataspace describing chunk */
hid_t space_id; /* ID for dataspace describing chunk */
@@ -512,25 +512,25 @@ H5Z_prelude_callback(hid_t dcpl_id, hid_t type_id, H5Z_prelude_type_t prelude_ty
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't retrieve chunk size")
/* Create a data space for a chunk & set the extent */
- for(u=0; u<chunk_ndims; u++)
- chunk_dims[u]=chunk_size[u];
+ for(u = 0; u < chunk_ndims; u++)
+ chunk_dims[u] = chunk_size[u];
if(NULL == (space = H5S_create_simple(chunk_ndims,chunk_dims,NULL)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create simple dataspace")
/* Get ID for dataspace to pass to filter routines */
- if ((space_id=H5I_register (H5I_DATASPACE, space))<0) {
+ if((space_id = H5I_register(H5I_DATASPACE, space, FALSE)) < 0) {
(void)H5S_close(space);
- HGOTO_ERROR (H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace ID")
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace ID")
} /* end if */
/* Iterate over filters */
- for (u=0; u<dcpl_pline.nused; u++) {
+ for(u = 0; u < dcpl_pline.nused; u++) {
H5Z_class_t *fclass; /* Individual filter information */
/* Get filter information */
- if (NULL==(fclass=H5Z_find(dcpl_pline.filter[u].id))) {
+ if(NULL == (fclass = H5Z_find(dcpl_pline.filter[u].id))) {
/* Ignore errors from optional filters */
- if (dcpl_pline.filter[u].flags & H5Z_FLAG_OPTIONAL)
+ if(dcpl_pline.filter[u].flags & H5Z_FLAG_OPTIONAL)
H5E_clear_stack(NULL);
else
HGOTO_ERROR(H5E_PLINE, H5E_NOTFOUND, FAIL, "required filter was not located")
@@ -540,7 +540,7 @@ H5Z_prelude_callback(hid_t dcpl_id, hid_t type_id, H5Z_prelude_type_t prelude_ty
switch(prelude_type) {
case H5Z_PRELUDE_CAN_APPLY:
/* Check if filter is configured to be able to encode */
- if(! fclass->encoder_present)
+ if(!fclass->encoder_present)
HGOTO_ERROR(H5E_PLINE, H5E_NOENCODER, FAIL, "Filter present but encoding is disabled.");
@@ -552,7 +552,7 @@ H5Z_prelude_callback(hid_t dcpl_id, hid_t type_id, H5Z_prelude_type_t prelude_ty
/* Check return value */
if(status<=0) {
/* We're leaving, so close dataspace */
- if(H5I_dec_ref(space_id)<0)
+ if(H5I_dec_ref(space_id, FALSE)<0)
HGOTO_ERROR (H5E_PLINE, H5E_CANTRELEASE, FAIL, "unable to close dataspace")
/* Indicate filter can't apply to this combination of parameters */
@@ -573,7 +573,7 @@ H5Z_prelude_callback(hid_t dcpl_id, hid_t type_id, H5Z_prelude_type_t prelude_ty
/* Make callback to filter's "set local" function */
if((fclass->set_local)(dcpl_id, type_id, space_id)<0) {
/* We're leaving, so close dataspace */
- if(H5I_dec_ref(space_id)<0)
+ if(H5I_dec_ref(space_id, FALSE)<0)
HGOTO_ERROR (H5E_PLINE, H5E_CANTRELEASE, FAIL, "unable to close dataspace")
/* Indicate error during filter callback */
@@ -589,7 +589,7 @@ H5Z_prelude_callback(hid_t dcpl_id, hid_t type_id, H5Z_prelude_type_t prelude_ty
} /* end for */
/* Close dataspace */
- if(H5I_dec_ref(space_id)<0)
+ if(H5I_dec_ref(space_id, FALSE) < 0)
HGOTO_ERROR (H5E_PLINE, H5E_CANTRELEASE, FAIL, "unable to close dataspace")
} /* end if */
} /* end if */
@@ -617,22 +617,20 @@ done:
* of passing in the dataset's dataspace, since the chunk
* dimensions are what the I/O filter will actually see
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
herr_t
-H5Z_can_apply (hid_t dcpl_id, hid_t type_id)
+H5Z_can_apply(hid_t dcpl_id, hid_t type_id)
{
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5Z_can_apply,FAIL)
+ FUNC_ENTER_NOAPI(H5Z_can_apply, FAIL)
- assert (H5I_GENPROP_LST==H5I_get_type(dcpl_id));
- assert (H5I_DATATYPE==H5I_get_type(type_id));
+ HDassert(H5I_GENPROP_LST == H5I_get_type(dcpl_id));
+ HDassert(H5I_DATATYPE == H5I_get_type(type_id));
/* Make "can apply" callbacks for filters in pipeline */
- if(H5Z_prelude_callback(dcpl_id, type_id, H5Z_PRELUDE_CAN_APPLY)<0)
+ if(H5Z_prelude_callback(dcpl_id, type_id, H5Z_PRELUDE_CAN_APPLY) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_CANAPPLY, FAIL, "unable to apply filter")
done:
@@ -657,22 +655,20 @@ done:
* of passing in the dataset's dataspace, since the chunk
* dimensions are what the I/O filter will actually see
*
- * Modifications:
- *
*-------------------------------------------------------------------------
*/
herr_t
-H5Z_set_local (hid_t dcpl_id, hid_t type_id)
+H5Z_set_local(hid_t dcpl_id, hid_t type_id)
{
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5Z_set_local,FAIL)
+ FUNC_ENTER_NOAPI(H5Z_set_local, FAIL)
- assert (H5I_GENPROP_LST==H5I_get_type(dcpl_id));
- assert (H5I_DATATYPE==H5I_get_type(type_id));
+ HDassert(H5I_GENPROP_LST == H5I_get_type(dcpl_id));
+ HDassert(H5I_DATATYPE == H5I_get_type(type_id));
/* Make "set local" callbacks for filters in pipeline */
- if(H5Z_prelude_callback(dcpl_id, type_id, H5Z_PRELUDE_SET_LOCAL)<0)
+ if(H5Z_prelude_callback(dcpl_id, type_id, H5Z_PRELUDE_SET_LOCAL) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_SETLOCAL, FAIL, "local filter parameters not set")
done:
diff --git a/src/H5Znbit.c b/src/H5Znbit.c
index 7a29d45..fabc7f0 100644
--- a/src/H5Znbit.c
+++ b/src/H5Znbit.c
@@ -96,7 +96,6 @@ H5Z_class_t H5Z_NBIT[1] = {{
#define H5Z_NBIT_ARRAY 2 /* Array datatype class */
#define H5Z_NBIT_COMPOUND 3 /* Compound datatype class */
#define H5Z_NBIT_NOOPTYPE 4 /* Other datatype class: nbit does no compression */
-#define H5Z_NBIT_USER_NPARMS 0 /* Number of parameters that users can set */
#define H5Z_NBIT_MAX_NPARMS 4096 /* Max number of parameters for filter */
#define H5Z_NBIT_ORDER_LE 0 /* Little endian for datatype byte order */
#define H5Z_NBIT_ORDER_BE 1 /* Big endian for datatype byte order */
@@ -327,7 +326,7 @@ H5Z_calc_parms_compound(const H5T_t *type)
/* For each member, calculate parameters */
for(u = 0; u < (unsigned)nmembers; u++) {
/* Get member datatype */
- if(NULL == (dtype_member = H5T_get_member_type(type, u)))
+ if(NULL == (dtype_member = H5T_get_member_type(type, u, H5T_COPY_TRANSIENT)))
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "bad member datatype")
/* Get member datatype's class */
@@ -440,7 +439,7 @@ H5Z_set_parms_atomic(const H5T_t *type, unsigned cd_values[])
int dtype_offset; /* Atomic datatype's offset (in bits) */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5Z_set_parms_atomic, FAIL)
+ FUNC_ENTER_NOAPI_NOINIT(H5Z_set_parms_atomic)
/* Set datatype class code */
cd_values[cd_values_index++] = H5Z_NBIT_ATOMIC;
@@ -638,7 +637,7 @@ H5Z_set_parms_compound(const H5T_t *type, unsigned cd_values[])
/* For each member, set parameters */
for(u = 0; u < (unsigned)nmembers; u++) {
/* Get member datatype */
- if(NULL == (dtype_member = H5T_get_member_type(type, u)))
+ if(NULL == (dtype_member = H5T_get_member_type(type, u, H5T_COPY_TRANSIENT)))
HGOTO_ERROR(H5E_PLINE, H5E_BADTYPE, FAIL, "bad member datatype")
/* Get member datatype's class */
@@ -800,6 +799,7 @@ H5Z_set_local_nbit(hid_t dcpl_id, hid_t type_id, hid_t space_id)
/* Get total number of elements in the chunk */
if((npoints = H5S_GET_EXTENT_NPOINTS(ds)) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_CANTGET, FAIL, "unable to get number of points in the dataspace")
+ HDassert(npoints);
/* Initialize index for cd_values array starting from the third entry */
cd_values_index = 2;
@@ -1409,4 +1409,4 @@ static void H5Z_nbit_compress(unsigned char *data, unsigned d_nelmts, unsigned c
*buffer_size = j + 1; /* sometimes is catually j, but to be safe */
}
-#endif /* H5_HAVE_FILTER_NZIP */
+#endif /* H5_HAVE_FILTER_NBIT */
diff --git a/src/H5Zprivate.h b/src/H5Zprivate.h
index cd67e96..15b7289 100644
--- a/src/H5Zprivate.h
+++ b/src/H5Zprivate.h
@@ -98,7 +98,8 @@ typedef struct H5Z_data_xform_t H5Z_data_xform_t; /* Defined in H5Ztrans.c */
H5_DLL H5Z_data_xform_t *H5Z_xform_create(const char *expr);
H5_DLL herr_t H5Z_xform_copy(H5Z_data_xform_t **data_xform_prop);
H5_DLL herr_t H5Z_xform_destroy(H5Z_data_xform_t *data_xform_prop);
-H5_DLL herr_t H5Z_xform_eval(H5Z_data_xform_t *data_xform_prop, void* array, size_t array_size, const H5T_t *buf_type);
+H5_DLL herr_t H5Z_xform_eval(H5Z_data_xform_t *data_xform_prop, void *array,
+ size_t array_size, const H5T_t *buf_type);
H5_DLL hbool_t H5Z_xform_noop(const H5Z_data_xform_t *data_xform_prop);
H5_DLL char* H5Z_xform_extract_xform_str(const H5Z_data_xform_t *data_xform_prop);
diff --git a/src/H5Zpublic.h b/src/H5Zpublic.h
index 1fac71c..ce60650 100644
--- a/src/H5Zpublic.h
+++ b/src/H5Zpublic.h
@@ -74,6 +74,25 @@ typedef int H5Z_filter_t;
#define H5_SZIP_NN_OPTION_MASK 32
#define H5_SZIP_MAX_PIXELS_PER_BLOCK 32
+/* Macros for the shuffle filter */
+#define H5Z_SHUFFLE_USER_NPARMS 0 /* Number of parameters that users can set */
+#define H5Z_SHUFFLE_TOTAL_NPARMS 1 /* Total number of parameters for filter */
+
+/* Macros for the szip filter */
+#define H5Z_SZIP_USER_NPARMS 2 /* Number of parameters that users can set */
+#define H5Z_SZIP_TOTAL_NPARMS 4 /* Total number of parameters for filter */
+#define H5Z_SZIP_PARM_MASK 0 /* "User" parameter for option mask */
+#define H5Z_SZIP_PARM_PPB 1 /* "User" parameter for pixels-per-block */
+#define H5Z_SZIP_PARM_BPP 2 /* "Local" parameter for bits-per-pixel */
+#define H5Z_SZIP_PARM_PPS 3 /* "Local" parameter for pixels-per-scanline */
+
+/* Macros for the nbit filter */
+#define H5Z_NBIT_USER_NPARMS 0 /* Number of parameters that users can set */
+
+/* Macros for the scale offset filter */
+#define H5Z_SCALEOFFSET_USER_NPARMS 2 /* Number of parameters that users can set */
+
+
/* Special parameters for ScaleOffset filter*/
#define H5Z_SO_INT_MINBITS_DEFAULT 0
typedef enum H5Z_SO_scale_type_t {
diff --git a/src/H5Zscaleoffset.c b/src/H5Zscaleoffset.c
index 7482275..84d404e 100644
--- a/src/H5Zscaleoffset.c
+++ b/src/H5Zscaleoffset.c
@@ -92,7 +92,6 @@ H5Z_class_t H5Z_SCALEOFFSET[1] = {{
}};
/* Local macros */
-#define H5Z_SCALEOFFSET_USER_NPARMS 2 /* Number of parameters that users can set */
#define H5Z_SCALEOFFSET_TOTAL_NPARMS 20 /* Total number of parameters for filter */
#define H5Z_SCALEOFFSET_PARM_SCALETYPE 0 /* "User" parameter for scale type */
#define H5Z_SCALEOFFSET_PARM_SCALEFACTOR 1 /* "User" parameter for scale factor */
diff --git a/src/H5Zshuffle.c b/src/H5Zshuffle.c
index c203ed9..3f40707 100644
--- a/src/H5Zshuffle.c
+++ b/src/H5Zshuffle.c
@@ -44,8 +44,6 @@ const H5Z_class_t H5Z_SHUFFLE[1] = {{
}};
/* Local macros */
-#define H5Z_SHUFFLE_USER_NPARMS 0 /* Number of parameters that users can set */
-#define H5Z_SHUFFLE_TOTAL_NPARMS 1 /* Total number of parameters for filter */
#define H5Z_SHUFFLE_PARM_SIZE 0 /* "Local" parameter for shuffling size */
diff --git a/src/H5Zszip.c b/src/H5Zszip.c
index cdc26aa..9201a80 100644
--- a/src/H5Zszip.c
+++ b/src/H5Zszip.c
@@ -51,13 +51,6 @@ H5Z_class_t H5Z_SZIP[1] = {{
H5Z_filter_szip, /* The actual filter function */
}};
-/* Local macros */
-#define H5Z_SZIP_USER_NPARMS 2 /* Number of parameters that users can set */
-#define H5Z_SZIP_TOTAL_NPARMS 4 /* Total number of parameters for filter */
-#define H5Z_SZIP_PARM_MASK 0 /* "User" parameter for option mask */
-#define H5Z_SZIP_PARM_PPB 1 /* "User" parameter for pixels-per-block */
-#define H5Z_SZIP_PARM_BPP 2 /* "Local" parameter for bits-per-pixel */
-#define H5Z_SZIP_PARM_PPS 3 /* "Local" parameter for pixels-per-scanline */
/*-------------------------------------------------------------------------
diff --git a/src/H5Ztrans.c b/src/H5Ztrans.c
index a58988e..b26a4b3 100644
--- a/src/H5Ztrans.c
+++ b/src/H5Ztrans.c
@@ -20,8 +20,8 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5Iprivate.h" /* IDs */
#include "H5MMprivate.h" /* Memory management */
-#include "H5Zpkg.h" /* Data filters */
#include "H5Vprivate.h" /* H5V_array_fill */
+#include "H5Zpkg.h" /* Data filters */
/* Token types */
@@ -885,7 +885,7 @@ done:
FUNC_LEAVE_NOAPI(ret_value);
}
-
+
/*-------------------------------------------------------------------------
* Function: H5Z_xform_eval
* Purpose: If the transform is trivial, this function applies it.
@@ -898,32 +898,31 @@ done:
*
*-------------------------------------------------------------------------
*/
-
herr_t
H5Z_xform_eval(H5Z_data_xform_t *data_xform_prop, void* array, size_t array_size, const H5T_t *buf_type)
{
H5Z_node *tree;
hid_t array_type;
- size_t i;
H5Z_result res;
- herr_t ret_value = SUCCEED;
+ size_t i;
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5Z_xform_eval, FAIL)
HDassert(data_xform_prop);
- tree=data_xform_prop->parse_root;
+ tree = data_xform_prop->parse_root;
/* Get the datatype ID for the buffer's type */
- if( (array_type = H5Z_xform_find_type(buf_type)) < 0)
+ if((array_type = H5Z_xform_find_type(buf_type)) < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Cannot perform data transform on this type.")
- /*After this point, we're assured that the type of the array is handled by the eval code, so we no
- * longer have to check for valid types */
+ /* After this point, we're assured that the type of the array is handled by the eval code,
+ * so we no longer have to check for valid types
+ */
/* If it's a trivial data transform, perform it */
- if( tree->type == H5Z_XFORM_INTEGER || tree->type == H5Z_XFORM_FLOAT)
- {
+ if(tree->type == H5Z_XFORM_INTEGER || tree->type == H5Z_XFORM_FLOAT) {
if(array_type == H5T_NATIVE_CHAR)
H5Z_XFORM_DO_OP5(char, array_size)
else if(array_type == H5T_NATIVE_UCHAR)
@@ -955,51 +954,47 @@ H5Z_xform_eval(H5Z_data_xform_t *data_xform_prop, void* array, size_t array_size
H5Z_XFORM_DO_OP5(long double, array_size)
#endif
- }
+ } /* end if */
/* Otherwise, do the full data transform */
- else
- {
+ else {
/* Optimization for linear transform: */
if(data_xform_prop->dat_val_pointers->num_ptrs == 1)
data_xform_prop->dat_val_pointers->ptr_dat_val[0] = array;
+
/* If it's a quadratic transform, we have no choice but to store multiple copies of the data */
- else
- {
- for(i=0; i<data_xform_prop->dat_val_pointers->num_ptrs; i++)
- {
- if( (data_xform_prop->dat_val_pointers->ptr_dat_val[i] = (void*)H5MM_malloc(array_size*H5Tget_size(array_type))) == NULL)
+ else {
+ for(i = 0; i < data_xform_prop->dat_val_pointers->num_ptrs; i++) {
+ if(NULL == (data_xform_prop->dat_val_pointers->ptr_dat_val[i] = (void*)H5MM_malloc(array_size * H5Tget_size(array_type))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "Ran out of memory trying to allocate space for data in data transform")
- HDmemcpy(data_xform_prop->dat_val_pointers->ptr_dat_val[i], array, array_size*H5Tget_size(array_type));
- }
- }
+ HDmemcpy(data_xform_prop->dat_val_pointers->ptr_dat_val[i], array, array_size * H5Tget_size(array_type));
+ } /* end for */
+ } /* end else */
if(H5Z_xform_eval_full(tree, array_size, array_type, &res) < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "error while performing data transform")
- if(data_xform_prop->dat_val_pointers->num_ptrs > 1)
+ if(data_xform_prop->dat_val_pointers->num_ptrs > 1)
HDmemcpy(array, res.value.dat_val, array_size * H5Tget_size(array_type));
/* Free the temporary arrays we used */
if(data_xform_prop->dat_val_pointers->num_ptrs > 1)
for(i=0; i<data_xform_prop->dat_val_pointers->num_ptrs; i++)
HDfree(data_xform_prop->dat_val_pointers->ptr_dat_val[i]);
- }
+ } /* end else */
done:
- if(ret_value < 0)
- {
+ if(ret_value < 0) {
/* If we ran out of memory above copying the array for temp storage (which we easily can for
* polynomial transforms of high order) we free those arrays which we already allocated */
if(data_xform_prop->dat_val_pointers->num_ptrs > 1)
- for(i=0; i<data_xform_prop->dat_val_pointers->num_ptrs; i++)
- if(data_xform_prop->dat_val_pointers->ptr_dat_val[i] != NULL)
+ for(i = 0; i < data_xform_prop->dat_val_pointers->num_ptrs; i++)
+ if(data_xform_prop->dat_val_pointers->ptr_dat_val[i])
HDfree(data_xform_prop->dat_val_pointers->ptr_dat_val[i]);
- }
- FUNC_LEAVE_NOAPI(ret_value);
-}
-
+ } /* end if */
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5Z_xform_eval() */
/*-------------------------------------------------------------------------
@@ -1017,38 +1012,34 @@ done:
* will accumulate changes and, at the end, the new data will be copied from the lhs.
*-------------------------------------------------------------------------
*/
-static herr_t
-H5Z_xform_eval_full(H5Z_node *tree, const size_t array_size, const hid_t array_type, H5Z_result* res)
+static herr_t
+H5Z_xform_eval_full(H5Z_node *tree, const size_t array_size, const hid_t array_type, H5Z_result *res)
{
H5Z_result resl, resr;
- herr_t ret_value = SUCCEED;
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5Z_xform_eval_full, FAIL);
+ FUNC_ENTER_NOAPI(H5Z_xform_eval_full, FAIL)
/* check args */
- assert(tree);
+ HDassert(tree);
- if (tree->type == H5Z_XFORM_INTEGER)
- {
+ if (tree->type == H5Z_XFORM_INTEGER) {
res->type = H5Z_XFORM_INTEGER;
res->value.int_val = tree->value.int_val;
- }
- else if (tree->type == H5Z_XFORM_FLOAT)
- {
+ } /* end if */
+ else if (tree->type == H5Z_XFORM_FLOAT) {
res->type = H5Z_XFORM_FLOAT;
res->value.float_val = tree->value.float_val;
- }
- else if (tree->type == H5Z_XFORM_SYMBOL)
- {
+ } /* end if */
+ else if (tree->type == H5Z_XFORM_SYMBOL) {
res->type = H5Z_XFORM_SYMBOL;
/*since dat_val stores the address of the array which is really stored in the dat_val_pointers,
* here we make dat_val store a pointer to the array itself instead of the address of it so that the
* rest of the code below works normally. */
res->value.dat_val = *((void**)(tree->value.dat_val));
- }
- else
- {
+ } /* end if */
+ else {
if(H5Z_xform_eval_full(tree->lchild, array_size, array_type, &resl) < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "error while performing data transform")
if(H5Z_xform_eval_full(tree->rchild, array_size, array_type, &resr) < 0)
@@ -1081,7 +1072,8 @@ H5Z_xform_eval_full(H5Z_node *tree, const size_t array_size, const hid_t array_
default:
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Invalid expression tree")
- }
+ } /* end switch */
+
/* The result stores a pointer to the new data */
/* So, if the left hand side got its data modified, the result stores a pointers
* to the left hand side's data, ditto for rhs */
@@ -1091,14 +1083,11 @@ H5Z_xform_eval_full(H5Z_node *tree, const size_t array_size, const hid_t array_
res->value.dat_val = resr.value.dat_val;
else
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "error during transform evaluation")
-
- }
-
+ } /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
-}
-
+} /* end H5Z_xform_eval_full() */
/*-------------------------------------------------------------------------
@@ -1113,77 +1102,76 @@ done:
static hid_t
H5Z_xform_find_type(const H5T_t* type)
{
- hid_t ret_value = SUCCEED;
+ hid_t ret_value = SUCCEED;
- FUNC_ENTER_NOAPI_NOINIT(H5Z_xform_find_type);
+ FUNC_ENTER_NOAPI_NOINIT(H5Z_xform_find_type)
- assert(type);
+ HDassert(type);
/* Check for SHORT type */
- if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_SHORT,H5I_DATATYPE), FALSE ))==0)
+ if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_SHORT,H5I_DATATYPE), FALSE)) == 0)
HGOTO_DONE(H5T_NATIVE_SHORT)
/* Check for INT type */
- else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_INT,H5I_DATATYPE), FALSE))==0)
+ else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_INT,H5I_DATATYPE), FALSE)) == 0)
HGOTO_DONE(H5T_NATIVE_INT)
/* Check for LONG type */
- else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_LONG,H5I_DATATYPE), FALSE))==0)
+ else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_LONG,H5I_DATATYPE), FALSE)) == 0)
HGOTO_DONE(H5T_NATIVE_LONG)
/* Check for LONGLONG type */
- else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_LLONG,H5I_DATATYPE), FALSE))==0)
+ else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_LLONG,H5I_DATATYPE), FALSE)) == 0)
HGOTO_DONE(H5T_NATIVE_LLONG)
/* Check for UCHAR type */
- else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_UCHAR,H5I_DATATYPE), FALSE))==0)
+ else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_UCHAR,H5I_DATATYPE), FALSE)) == 0)
HGOTO_DONE(H5T_NATIVE_UCHAR)
/* Check for CHAR type */
- else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_CHAR,H5I_DATATYPE), FALSE))==0)
+ else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_CHAR,H5I_DATATYPE), FALSE)) == 0)
HGOTO_DONE(H5T_NATIVE_CHAR)
/* Check for SCHAR type */
- else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_SCHAR,H5I_DATATYPE), FALSE))==0)
+ else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_SCHAR,H5I_DATATYPE), FALSE)) == 0)
HGOTO_DONE(H5T_NATIVE_SCHAR)
/* Check for USHORT type */
- else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_USHORT,H5I_DATATYPE), FALSE))==0)
+ else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_USHORT,H5I_DATATYPE), FALSE)) == 0)
HGOTO_DONE(H5T_NATIVE_USHORT)
/* Check for UINT type */
- else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_UINT,H5I_DATATYPE), FALSE))==0)
+ else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_UINT,H5I_DATATYPE), FALSE)) == 0)
HGOTO_DONE(H5T_NATIVE_UINT)
/* Check for ULONG type */
- else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_ULONG,H5I_DATATYPE), FALSE))==0)
+ else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_ULONG,H5I_DATATYPE), FALSE)) == 0)
HGOTO_DONE(H5T_NATIVE_ULONG)
/* Check for ULONGLONG type */
- else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_ULLONG,H5I_DATATYPE), FALSE))==0)
+ else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_ULLONG,H5I_DATATYPE), FALSE)) == 0)
HGOTO_DONE(H5T_NATIVE_ULLONG)
/* Check for FLOAT type */
- else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_FLOAT,H5I_DATATYPE), FALSE))==0)
+ else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_FLOAT,H5I_DATATYPE), FALSE)) == 0)
HGOTO_DONE(H5T_NATIVE_FLOAT)
/* Check for DOUBLE type */
- else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_DOUBLE,H5I_DATATYPE), FALSE))==0)
+ else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_DOUBLE,H5I_DATATYPE), FALSE)) == 0)
HGOTO_DONE(H5T_NATIVE_DOUBLE)
#if H5_SIZEOF_LONG_DOUBLE !=0
/* Check for LONGDOUBLE type */
- else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_LDOUBLE,H5I_DATATYPE), FALSE))==0)
+ else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_LDOUBLE,H5I_DATATYPE), FALSE)) == 0)
HGOTO_DONE(H5T_NATIVE_LDOUBLE)
#endif
else
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "could not find matching type");
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "could not find matching type")
done:
FUNC_LEAVE_NOAPI(ret_value)
-
-}
+} /* end H5Z_xform_find_type() */
/*-------------------------------------------------------------------------
diff --git a/src/H5checksum.c b/src/H5checksum.c
index f2e344d..6c01508 100644
--- a/src/H5checksum.c
+++ b/src/H5checksum.c
@@ -126,10 +126,10 @@ H5_checksum_fletcher32(const void *_data, size_t _len)
* performed without numeric overflow)
*/
while (len) {
- unsigned tlen = len > 360 ? 360 : len;
+ size_t tlen = len > 360 ? 360 : len;
len -= tlen;
do {
- sum1 += (((uint16_t)data[0]) << 8) | ((uint16_t)data[1]);
+ sum1 += (uint32_t)(((uint16_t)data[0]) << 8) | ((uint16_t)data[1]);
data += 2;
sum2 += sum1;
} while (--tlen);
@@ -139,7 +139,7 @@ H5_checksum_fletcher32(const void *_data, size_t _len)
/* Check for odd # of bytes */
if(_len % 2) {
- sum1 += ((uint16_t)*data) << 8;
+ sum1 += (uint32_t)(((uint16_t)*data) << 8);
sum2 += sum1;
sum1 = (sum1 & 0xffff) + (sum1 >> 16);
sum2 = (sum2 & 0xffff) + (sum2 >> 16);
@@ -270,7 +270,7 @@ This was tested for:
the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
is commonly produced by subtraction) look like a single 1-bit
difference.
-* the base values were pseudorandom, all zero but one bit set, or
+* the base values were pseudorandom, all zero but one bit set, or
all zero plus a counter that starts at zero.
Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that
@@ -280,7 +280,7 @@ satisfy this are
14 9 3 7 17 3
Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing
for "differ" defined as + with a one-bit base and a two-bit delta. I
-used http://burtleburtle.net/bob/hash/avalanche.html to choose
+used http://burtleburtle.net/bob/hash/avalanche.html to choose
the operations, constants, and arrangements of the variables.
This does not achieve avalanche. There are input bits of (a,b,c)
@@ -320,7 +320,7 @@ produce values of c that look totally different. This was tested for
the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
is commonly produced by subtraction) look like a single 1-bit
difference.
-* the base values were pseudorandom, all zero but one bit set, or
+* the base values were pseudorandom, all zero but one bit set, or
all zero plus a counter that starts at zero.
These constants passed:
@@ -459,3 +459,36 @@ H5_checksum_metadata(const void *data, size_t len, uint32_t initval)
FUNC_LEAVE_NOAPI(H5_checksum_lookup3(data, len, initval))
} /* end H5_checksum_metadata() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5_hash_string
+ *
+ * Purpose: Provide a simple & fast routine for hashing strings
+ *
+ * Note: This algorithm is the 'djb2' algorithm described on this page:
+ * http://www.cse.yorku.ca/~oz/hash.html
+ *
+ * Return: hash of input string (can't fail)
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, December 11, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+uint32_t
+H5_hash_string(const char *str)
+{
+ uint32_t hash = 5381;
+ int c;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5_hash_string)
+
+ /* Sanity check */
+ HDassert(str);
+
+ while((c = *str++))
+ hash = ((hash << 5) + hash) + (uint32_t)c; /* hash * 33 + c */
+
+ FUNC_LEAVE_NOAPI(hash)
+} /* end H5_hash_string() */
+
diff --git a/src/H5config.h.in b/src/H5config.h.in
index b382f14..1436211 100644
--- a/src/H5config.h.in
+++ b/src/H5config.h.in
@@ -58,6 +58,9 @@
/* Define to 1 if you have the `BSDgettimeofday' function. */
#undef HAVE_BSDGETTIMEOFDAY
+/* Define if the compiler understand the __func__ keyword */
+#undef HAVE_C99_FUNC
+
/* Define if the function stack tracing code is to be compiled in */
#undef HAVE_CODESTACK
@@ -119,6 +122,9 @@
/* Define to 1 if you have the `ftello' function. */
#undef HAVE_FTELLO
+/* Define to 1 if you have the `ftruncate64' function. */
+#undef HAVE_FTRUNCATE64
+
/* Define if the compiler understand the __FUNCTION__ keyword */
#undef HAVE_FUNCTION
@@ -162,9 +168,6 @@
/* Define to 1 if you have the <io.h> header file. */
#undef HAVE_IO_H
-/* Define if it's safe to use `long long' for hsize_t and hssize_t */
-#undef HAVE_LARGE_HSIZET
-
/* Define to 1 if you have the `dmalloc' library (-ldmalloc). */
#undef HAVE_LIBDMALLOC
@@ -225,12 +228,6 @@
/* Define if `MPI_Info_c2f' and `MPI_Info_f2c' exists */
#undef HAVE_MPI_MULTI_LANG_Info
-/* Define to 1 if you have the <netinet/in.h> header file. */
-#undef HAVE_NETINET_IN_H
-
-/* Define to 1 if you have the <netinet/tcp.h> header file. */
-#undef HAVE_NETINET_TCP_H
-
/* Define if we have parallel support */
#undef HAVE_PARALLEL
@@ -261,9 +258,6 @@
/* Define to 1 if you have the `snprintf' function. */
#undef HAVE_SNPRINTF
-/* Define if `socklen_t' is defined */
-#undef HAVE_SOCKLEN_T
-
/* Define to 1 if you have the `srandom' function. */
#undef HAVE_SRANDOM
@@ -285,9 +279,6 @@
/* Define to 1 if you have the `strdup' function. */
#undef HAVE_STRDUP
-/* Define if the stream virtual file driver should be compiled */
-#undef HAVE_STREAM
-
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
@@ -309,9 +300,6 @@
/* Define to 1 if you have the `system' function. */
#undef HAVE_SYSTEM
-/* Define to 1 if you have the <sys/filio.h> header file. */
-#undef HAVE_SYS_FILIO_H
-
/* Define to 1 if you have the <sys/fpu.h> header file. */
#undef HAVE_SYS_FPU_H
@@ -383,6 +371,9 @@
/* Define to 1 if you have the `waitpid' function. */
#undef HAVE_WAITPID
+/* Define if your system has window style path name. */
+#undef HAVE_WINDOW_PATH
+
/* Define to 1 if you have the <winsock.h> header file. */
#undef HAVE_WINSOCK_H
@@ -430,6 +421,10 @@
values correctly. */
#undef LLONG_TO_LDOUBLE_CORRECT
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#undef LT_OBJDIR
+
/* Define if the metadata trace file code is to be compiled in */
#undef METADATA_TRACE_FILE
@@ -444,6 +439,9 @@
/* Define if your system can handle special collective IO properly. */
#undef MPI_SPECIAL_COLLECTIVE_IO_WORKS
+/* Define if we can violate pointer alignment restrictions */
+#undef NO_ALIGNMENT_RESTRICTIONS
+
/* Define if deprecated public API symbols are disabled */
#undef NO_DEPRECATED_SYMBOLS
@@ -585,6 +583,9 @@
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
+/* Define if strict file format checks are enabled */
+#undef STRICT_FORMAT_CHECKS
+
/* Define if your system supports pthread_attr_setscope(&attribute,
PTHREAD_SCOPE_SYSTEM) call. */
#undef SYSTEM_SCOPE_THREADS
@@ -608,7 +609,7 @@
#undef ULONG_TO_FP_BOTTOM_BIT_ACCURATE
/* Define using v1.6 public API symbols by default */
-#undef USE_16_API
+#undef USE_16_API_DEFAULT
/* Define if a memory checking tool will be used on the library, to cause
library to be very picky about memory operations and also disable the
diff --git a/src/H5detect.c b/src/H5detect.c
index 1f79869..e29157d 100644
--- a/src/H5detect.c
+++ b/src/H5detect.c
@@ -202,34 +202,36 @@ precision (detected_t *d)
int _i, _j; \
unsigned char *_x; \
\
- memset (&INFO, 0, sizeof(INFO)); \
+ HDmemset(&INFO, 0, sizeof(INFO)); \
INFO.varname = #VAR; \
INFO.size = sizeof(TYPE); \
\
- if(sizeof(TYPE)!=1) { \
- for (_i=sizeof(TYPE),_v=0; _i>0; --_i) _v = (_v<<8) + _i; \
- for (_i=0,_x=(unsigned char *)&_v; _i<(signed)sizeof(TYPE); _i++) { \
- _j = (*_x++)-1; \
- assert (_j<(signed)sizeof(TYPE)); \
+ if(sizeof(TYPE) != 1) { \
+ for(_i = sizeof(TYPE), _v = 0; _i > 0; --_i) \
+ _v = (_v << 8) + _i; \
+ for(_i = 0, _x = (unsigned char *)&_v; _i < (signed)sizeof(TYPE); _i++) { \
+ _j = (*_x++) - 1; \
+ assert(_j < (signed)sizeof(TYPE)); \
INFO.perm[_i] = _j; \
- } \
+ } /* end for */ \
} else { /*Not able to detect order if type size is 1 byte. Use native int \
*instead. No effect on data, just make it look correct. */ \
- for (_i=sizeof(int),_int_v=0; _i>0; --_i) _int_v = (_int_v<<8) + _i; \
- for (_i=0,_x=(unsigned char *)&_int_v; _i<(signed)sizeof(int); _i++) { \
+ for(_i = sizeof(int), _int_v = 0; _i > 0; --_i) \
+ _int_v = (_int_v << 8) + _i; \
+ for(_i = 0, _x = (unsigned char *)&_int_v; _i < (signed)sizeof(int); _i++) { \
_j = (*_x++)-1; \
- assert (_j<(signed)sizeof(int)); \
+ assert(_j < (signed)sizeof(int)); \
INFO.perm[_i] = _j; \
- } \
- } \
+ } /* end for */ \
+ } /* end else */ \
\
- INFO.sign = ('U'!=*(#VAR)); \
+ INFO.sign = ('U' != *(#VAR)); \
precision (&(INFO)); \
ALIGNMENT(TYPE, INFO); \
- if(!strcmp(INFO.varname, "SCHAR") || !strcmp(INFO.varname, "SHORT") || \
- !strcmp(INFO.varname, "INT") || !strcmp(INFO.varname, "LONG") || \
- !strcmp(INFO.varname, "LLONG")) { \
- COMP_ALIGNMENT(TYPE,INFO.comp_align); \
+ if(!HDstrcmp(INFO.varname, "SCHAR") || !HDstrcmp(INFO.varname, "SHORT") || \
+ !HDstrcmp(INFO.varname, "INT") || !HDstrcmp(INFO.varname, "LONG") || \
+ !HDstrcmp(INFO.varname, "LLONG")) { \
+ COMP_ALIGNMENT(TYPE, INFO.comp_align); \
} \
}
@@ -358,16 +360,16 @@ precision (detected_t *d)
#if defined(H5_HAVE_LONGJMP) && defined(H5_HAVE_SIGNAL)
#define ALIGNMENT(TYPE,INFO) { \
- char *volatile _buf=NULL; \
- volatile TYPE _val=1; \
+ char *volatile _buf = NULL; \
+ volatile TYPE _val = 1; \
volatile TYPE _val2; \
- volatile size_t _ano=0; \
+ volatile size_t _ano = 0; \
void (*_handler)(int) = signal(SIGBUS, sigbus_handler); \
void (*_handler2)(int) = signal(SIGSEGV, sigsegv_handler); \
\
- _buf = (char*)malloc(sizeof(TYPE)+align_g[NELMTS(align_g)-1]); \
- if (setjmp(jbuf_g)) _ano++; \
- if (_ano<NELMTS(align_g)) { \
+ _buf = (char*)malloc(sizeof(TYPE) + align_g[NELMTS(align_g) - 1]); \
+ if(setjmp(jbuf_g)) _ano++; \
+ if(_ano < NELMTS(align_g)) { \
*((TYPE*)(_buf+align_g[_ano])) = _val; /*possible SIGBUS or SEGSEGV*/ \
_val2 = *((TYPE*)(_buf+align_g[_ano])); /*possible SIGBUS or SEGSEGV*/ \
/* Cray Check: This section helps detect alignment on Cray's */ \
@@ -522,27 +524,88 @@ print_results(int nd, detected_t *d, int na, malign_t *misc_align)
/* Include files */
printf("\
+/****************/\n\
+/* Module Setup */\n\
+/****************/\n\
+\n\
#define H5T_PACKAGE /*suppress error about including H5Tpkg.h*/\n\
\n\
-#include \"H5private.h\"\n\
-#include \"H5Iprivate.h\"\n\
-#include \"H5Eprivate.h\"\n\
-#include \"H5FLprivate.h\"\n\
-#include \"H5Tpkg.h\"\n\
+\n\
+/***********/\n\
+/* Headers */\n\
+/***********/\n\
+#include \"H5private.h\" /* Generic Functions */\n\
+#include \"H5Eprivate.h\" /* Error handling */\n\
+#include \"H5FLprivate.h\" /* Free Lists */\n\
+#include \"H5Iprivate.h\" /* IDs */\n\
+#include \"H5Tpkg.h\" /* Datatypes */\n\
+\n\
+\n\
+/****************/\n\
+/* Local Macros */\n\
+/****************/\n\
+\n\
+\n\
+/******************/\n\
+/* Local Typedefs */\n\
+/******************/\n\
+\n\
+\n\
+/********************/\n\
+/* Package Typedefs */\n\
+/********************/\n\
+\n\
+\n\
+/********************/\n\
+/* Local Prototypes */\n\
+/********************/\n\
+\n\
+\n\
+/********************/\n\
+/* Public Variables */\n\
+/********************/\n\
+\n\n\
+/*****************************/\n\
+/* Library Private Variables */\n\
+/*****************************/\n\
+\n\n\
+/*********************/\n\
+/* Package Variables */\n\
+/*********************/\n\
\n\
\n");
+ printf("\n\
+/*******************/\n\
+/* Local Variables */\n\
+/*******************/\n\
+\n");
/* The interface initialization function */
printf("\n\
+ \n\
+/*-------------------------------------------------------------------------\n\
+ * Function: H5TN_init_interface\n\
+ *\n\
+ * Purpose: Initialize pre-defined native datatypes from code generated\n\
+ * during the library configuration by H5detect.\n\
+ *\n\
+ * Return: Success: non-negative\n\
+ * Failure: negative\n\
+ *\n\
+ * Programmer: Robb Matzke\n\
+ * Wednesday, December 16, 1998\n\
+ *\n\
+ *-------------------------------------------------------------------------\n\
+ */\n\
herr_t\n\
H5TN_init_interface(void)\n\
{\n\
H5T_t *dt = NULL;\n\
herr_t ret_value = SUCCEED;\n\
\n\
- FUNC_ENTER_NOAPI(H5TN_init_interface, FAIL);\n");
+ FUNC_ENTER_NOAPI(H5TN_init_interface, FAIL)\n");
- for (i = 0; i < nd; i++) {
+ for(i = 0; i < nd; i++) {
/* The native endianess of this machine */
/* The INFO.perm now contains `-1' for bytes that aren't used and
* are always zero. This happens on the Cray for `short' where
@@ -568,7 +631,7 @@ H5TN_init_interface(void)\n\
/* The part common to fixed and floating types */
printf("\
if(NULL == (dt = H5T_alloc()))\n\
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL,\"memory allocation failed\")\n\
+ HGOTO_ERROR(H5E_DATATYPE, H5E_NOSPACE, FAIL, \"datatype allocation failed\")\n\
dt->shared->state = H5T_STATE_IMMUTABLE;\n\
dt->shared->type = H5T_%s;\n\
dt->shared->size = %d;\n",
@@ -621,8 +684,8 @@ H5TN_init_interface(void)\n\
/* Atomize the type */
printf("\
- if ((H5T_NATIVE_%s_g = H5I_register (H5I_DATATYPE, dt))<0)\n\
- HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL,\"can't initialize type system (atom registration failure\");\n",
+ if((H5T_NATIVE_%s_g = H5I_register(H5I_DATATYPE, dt, FALSE)) < 0)\n\
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, \"can't register ID for built-in datatype\")\n",
d[i].varname);
printf(" H5T_NATIVE_%s_ALIGN_g = %lu;\n",
d[i].varname, (unsigned long)(d[i].align));
@@ -656,16 +719,16 @@ H5TN_init_interface(void)\n\
printf("\
\n\
done:\n\
- if(ret_value<0) {\n\
+ if(ret_value < 0) {\n\
if(dt != NULL) {\n\
if(dt->shared != NULL)\n\
H5FL_FREE(H5T_shared_t, dt->shared);\n\
H5FL_FREE(H5T_t, dt);\n\
} /* end if */\n\
- }\n\
+ } /* end if */\n\
\n\
- FUNC_LEAVE_NOAPI(ret_value);\n}\n");
-}
+ FUNC_LEAVE_NOAPI(ret_value);\n} /* end H5TN_init_interface() */\n");
+} /* end print_results() */
/*-------------------------------------------------------------------------
@@ -1090,15 +1153,9 @@ bit.\n";
* The FQDM of this host or the empty string.
*/
#ifdef H5_HAVE_GETHOSTNAME
-#ifdef _WIN32
-/* windows DLL cannot recognize gethostname, so turn off on windows for the time being!
- KY, 2003-1-14 */
- host_name[0] = '\0';
-#else
if (gethostname(host_name, sizeof(host_name)) < 0) {
host_name[0] = '\0';
}
-#endif
#else
host_name[0] = '\0';
#endif
diff --git a/src/H5err.txt b/src/H5err.txt
index 844bd57..7f110b8 100644
--- a/src/H5err.txt
+++ b/src/H5err.txt
@@ -74,6 +74,7 @@ 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_EARRAY, Extensible Array
MAJOR, H5E_NONE_MAJOR, No error
# Sections (for grouping minor errors)
diff --git a/src/H5private.h b/src/H5private.h
index dad4e13..63bbcf4 100644
--- a/src/H5private.h
+++ b/src/H5private.h
@@ -313,6 +313,9 @@
/* (from: http://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2) */
# define POWER_OF_TWO(n) (!(n & (n - 1)) && n)
+/* Raise an integer to a power of 2 */
+# define H5_EXP2(n) (1 << (n))
+
/*
* HDF Boolean type.
*/
@@ -485,425 +488,929 @@ typedef enum {
H5_COPY_DEEP /* Deep copy from source to destination, including duplicating fields pointed to */
} H5_copy_depth_t;
+/* Unique object "position" */
+typedef struct {
+ unsigned long fileno; /* The unique identifier for the file of the object */
+ haddr_t addr; /* The unique address of the object's header in that file */
+} H5_obj_t;
+
/*
* Redefine all the POSIX functions. We should never see a POSIX
* function (or any other non-HDF5 function) in the source!
*/
-#define HDabort() abort()
-#define HDabs(X) abs(X)
-#define HDaccess(F,M) access(F, M)
-#define HDacos(X) acos(X)
-#ifdef H5_HAVE_ALARM
-#define HDalarm(N) alarm(N)
-#else /* H5_HAVE_ALARM */
-#define HDalarm(N) (0)
-#endif /* H5_HAVE_ALARM */
-#define HDasctime(T) asctime(T)
-#define HDasin(X) asin(X)
-#define HDassert(X) assert(X)
-#define HDatan(X) atan(X)
-#define HDatan2(X,Y) atan2(X,Y)
-#define HDatexit(F) atexit(F)
-#define HDatof(S) atof(S)
-#define HDatoi(S) atoi(S)
-#define HDatol(S) atol(S)
-#define HDBSDgettimeofday(S,P) BSDgettimeofday(S,P)
-#define HDbsearch(K,B,N,Z,F) bsearch(K,B,N,Z,F)
-#define HDcalloc(N,Z) calloc(N,Z)
-#define HDceil(X) ceil(X)
-#define HDcfgetispeed(T) cfgetispeed(T)
-#define HDcfgetospeed(T) cfgetospeed(T)
-#define HDcfsetispeed(T,S) cfsetispeed(T,S)
-#define HDcfsetospeed(T,S) cfsetospeed(T,S)
-#define HDchdir(S) chdir(S)
-#define HDchmod(S,M) chmod(S,M)
-#define HDchown(S,O,G) chown(S,O,G)
-#define HDclearerr(F) clearerr(F)
-#define HDclock() clock()
-#define HDclose(F) close(F)
-#define HDclosedir(D) closedir(D)
-#define HDcos(X) cos(X)
-#define HDcosh(X) cosh(X)
-#define HDcreat(S,M) creat(S,M)
-#define HDctermid(S) ctermid(S)
-#define HDctime(T) ctime(T)
-#define HDcuserid(S) cuserid(S)
-#ifdef H5_HAVE_DIFFTIME
-#define HDdifftime(X,Y) difftime(X,Y)
-#else
-#define HDdifftime(X,Y) ((double)(X)-(double)(Y))
-#endif
-#define HDdiv(X,Y) div(X,Y)
-#define HDdup(F) dup(F)
-#define HDdup2(F,I) dup2(F,I)
+
+ /* Use platform-specific versions if necessary */
+#include "H5win32defs.h"
+
+#ifndef HDabort
+ #define HDabort() abort()
+#endif /* HDabort */
+#ifndef HDabs
+ #define HDabs(X) abs(X)
+#endif /* HDabs */
+#ifndef HDaccess
+ #define HDaccess(F,M) access(F, M)
+#endif /* HDaccess */
+#ifndef HDacos
+ #define HDacos(X) acos(X)
+#endif /* HDacos */
+#ifndef HDalarm
+ #ifdef H5_HAVE_ALARM
+ #define HDalarm(N) alarm(N)
+ #else /* H5_HAVE_ALARM */
+ #define HDalarm(N) (0)
+ #endif /* H5_HAVE_ALARM */
+#endif /* HDalarm */
+#ifndef HDasctime
+ #define HDasctime(T) asctime(T)
+#endif /* HDasctime */
+#ifndef HDasin
+ #define HDasin(X) asin(X)
+#endif /* HDasin */
+#ifndef HDassert
+ #define HDassert(X) assert(X)
+#endif /* HDassert */
+#ifndef HDatan
+ #define HDatan(X) atan(X)
+#endif /* HDatan */
+#ifndef HDatan2
+ #define HDatan2(X,Y) atan2(X,Y)
+#endif /* HDatan2 */
+#ifndef HDatexit
+ #define HDatexit(F) atexit(F)
+#endif /* HDatexit */
+#ifndef HDatof
+ #define HDatof(S) atof(S)
+#endif /* HDatof */
+#ifndef HDatoi
+ #define HDatoi(S) atoi(S)
+#endif /* HDatoi */
+#ifndef HDatol
+ #define HDatol(S) atol(S)
+#endif /* HDatol */
+#ifndef HDBSDgettimeofday
+ #define HDBSDgettimeofday(S,P) BSDgettimeofday(S,P)
+#endif /* HDBSDgettimeofday */
+#ifndef HDbsearch
+ #define HDbsearch(K,B,N,Z,F) bsearch(K,B,N,Z,F)
+#endif /* HDbsearch */
+#ifndef HDcalloc
+ #define HDcalloc(N,Z) calloc(N,Z)
+#endif /* HDcalloc */
+#ifndef HDceil
+ #define HDceil(X) ceil(X)
+#endif /* HDceil */
+#ifndef HDcfgetispeed
+ #define HDcfgetispeed(T) cfgetispeed(T)
+#endif /* HDcfgetispeed */
+#ifndef HDcfgetospeed
+ #define HDcfgetospeed(T) cfgetospeed(T)
+#endif /* HDcfgetospeed */
+#ifndef HDcfsetispeed
+ #define HDcfsetispeed(T,S) cfsetispeed(T,S)
+#endif /* HDcfsetispeed */
+#ifndef HDcfsetospeed
+ #define HDcfsetospeed(T,S) cfsetospeed(T,S)
+#endif /* HDcfsetospeed */
+#ifndef HDchdir
+ #define HDchdir(S) chdir(S)
+#endif /* HDchdir */
+#ifndef HDchmod
+ #define HDchmod(S,M) chmod(S,M)
+#endif /* HDchmod */
+#ifndef HDchown
+ #define HDchown(S,O,G) chown(S,O,G)
+#endif /* HDchown */
+#ifndef HDclearerr
+ #define HDclearerr(F) clearerr(F)
+#endif /* HDclearerr */
+#ifndef HDclock
+ #define HDclock() clock()
+#endif /* HDclock */
+#ifndef HDclose
+ #define HDclose(F) close(F)
+#endif /* HDclose */
+#ifndef HDclosedir
+ #define HDclosedir(D) closedir(D)
+#endif /* HDclosedir */
+#ifndef HDcos
+ #define HDcos(X) cos(X)
+#endif /* HDcos */
+#ifndef HDcosh
+ #define HDcosh(X) cosh(X)
+#endif /* HDcosh */
+#ifndef HDcreat
+ #define HDcreat(S,M) creat(S,M)
+#endif /* HDcreat */
+#ifndef HDctermid
+ #define HDctermid(S) ctermid(S)
+#endif /* HDctermid */
+#ifndef HDctime
+ #define HDctime(T) ctime(T)
+#endif /* HDctime */
+#ifndef HDcuserid
+ #define HDcuserid(S) cuserid(S)
+#endif /* HDcuserid */
+#ifndef HDdifftime
+ #ifdef H5_HAVE_DIFFTIME
+ #define HDdifftime(X,Y) difftime(X,Y)
+ #else /* H5_HAVE_DIFFTIME */
+ #define HDdifftime(X,Y) ((double)(X)-(double)(Y))
+ #endif /* H5_HAVE_DIFFTIME */
+#endif /* HDdifftime */
+#ifndef HDdiv
+ #define HDdiv(X,Y) div(X,Y)
+#endif /* HDdiv */
+#ifndef HDdup
+ #define HDdup(F) dup(F)
+#endif /* HDdup */
+#ifndef HDdup2
+ #define HDdup2(F,I) dup2(F,I)
+#endif /* HDdup2 */
/* execl() variable arguments */
/* execle() variable arguments */
/* execlp() variable arguments */
-#define HDexecv(S,AV) execv(S,AV)
-#define HDexecve(S,AV,E) execve(S,AV,E)
-#define HDexecvp(S,AV) execvp(S,AV)
-#define HDexit(N) exit(N)
-#if defined __MWERKS__
-#include <abort_exit.h>
-#define HD_exit(N) __exit(N)
-#else /* __MWERKS __ */
-#define HD_exit(N) _exit(N)
-#endif /* __MWERKS __ */
-#define HDexp(X) exp(X)
-#define HDfabs(X) fabs(X)
+#ifndef HDexecv
+ #define HDexecv(S,AV) execv(S,AV)
+#endif /* HDexecv */
+#ifndef HDexecve
+ #define HDexecve(S,AV,E) execve(S,AV,E)
+#endif /* HDexecve */
+#ifndef HDexecvp
+ #define HDexecvp(S,AV) execvp(S,AV)
+#endif /* HDexecvp */
+#ifndef HDexit
+ #define HDexit(N) exit(N)
+#endif /* HDexit */
+#ifndef HD_exit
+ #define HD_exit(N) _exit(N)
+#endif /* HD_exit */
+#ifndef HDexp
+ #define HDexp(X) exp(X)
+#endif /* HDexp */
+#ifndef HDexp2
+ #define HDexp2(X) exp2(X)
+#endif /* HDexp2 */
+#ifndef HDfabs
+ #define HDfabs(X) fabs(X)
+#endif /* HDfabs */
/* use ABS() because fabsf() fabsl() are not common yet. */
-#define HDfabsf(X) ABS(X)
-#define HDfabsl(X) ABS(X)
-#define HDfclose(F) fclose(F)
+#ifndef HDfabsf
+ #define HDfabsf(X) ABS(X)
+#endif /* HDfabsf */
+#ifndef HDfabsl
+ #define HDfabsl(X) ABS(X)
+#endif /* HDfabsl */
+#ifndef HDfclose
+ #define HDfclose(F) fclose(F)
+#endif /* HDfclose */
/* fcntl() variable arguments */
-#define HDfdopen(N,S) fdopen(N,S)
-#define HDfeof(F) feof(F)
-#define HDferror(F) ferror(F)
-#define HDfflush(F) fflush(F)
-#define HDfgetc(F) fgetc(F)
-#define HDfgetpos(F,P) fgetpos(F,P)
-#define HDfgets(S,N,F) fgets(S,N,F)
-#ifdef _WIN32
-#define HDfileno(F) _fileno(F)
-#else /* _WIN32 */
-#define HDfileno(F) fileno(F)
-#endif /* _WIN32 */
-#define HDfloor(X) floor(X)
-#define HDfmod(X,Y) fmod(X,Y)
-#define HDfopen(S,M) fopen(S,M)
-#define HDfork() fork()
-#define HDfpathconf(F,N) fpathconf(F,N)
+#ifndef HDfdopen
+ #define HDfdopen(N,S) fdopen(N,S)
+#endif /* HDfdopen */
+#ifndef HDfeof
+ #define HDfeof(F) feof(F)
+#endif /* HDfeof */
+#ifndef HDferror
+ #define HDferror(F) ferror(F)
+#endif /* HDferror */
+#ifndef HDfflush
+ #define HDfflush(F) fflush(F)
+#endif /* HDfflush */
+#ifndef HDfgetc
+ #define HDfgetc(F) fgetc(F)
+#endif /* HDfgetc */
+#ifndef HDfgetpos
+ #define HDfgetpos(F,P) fgetpos(F,P)
+#endif /* HDfgetpos */
+#ifndef HDfgets
+ #define HDfgets(S,N,F) fgets(S,N,F)
+#endif /* HDfgets */
+#ifndef HDfileno
+ #define HDfileno(F) fileno(F)
+#endif /* HDfileno */
+#ifndef HDfloor
+ #define HDfloor(X) floor(X)
+#endif /* HDfloor */
+#ifndef HDfmod
+ #define HDfmod(X,Y) fmod(X,Y)
+#endif /* HDfmod */
+#ifndef HDfopen
+ #define HDfopen(S,M) fopen(S,M)
+#endif /* HDfopen */
+#ifndef HDfork
+ #define HDfork() fork()
+#endif /* HDfork */
+#ifndef HDfpathconf
+ #define HDfpathconf(F,N) fpathconf(F,N)
+#endif /* HDfpathconf */
H5_DLL int HDfprintf (FILE *stream, const char *fmt, ...);
-#define HDfputc(C,F) fputc(C,F)
-#define HDfputs(S,F) fputs(S,F)
-#define HDfread(M,Z,N,F) fread(M,Z,N,F)
-#define HDfree(M) free(M)
-#define HDfreopen(S,M,F) freopen(S,M,F)
-#define HDfrexp(X,N) frexp(X,N)
+#ifndef HDfputc
+ #define HDfputc(C,F) fputc(C,F)
+#endif /* HDfputc */
+#ifndef HDfputs
+ #define HDfputs(S,F) fputs(S,F)
+#endif /* HDfputs */
+#ifndef HDfread
+ #define HDfread(M,Z,N,F) fread(M,Z,N,F)
+#endif /* HDfread */
+#ifndef HDfree
+ #define HDfree(M) free(M)
+#endif /* HDfree */
+#ifndef HDfreopen
+ #define HDfreopen(S,M,F) freopen(S,M,F)
+#endif /* HDfreopen */
+#ifndef HDfrexp
+ #define HDfrexp(X,N) frexp(X,N)
+#endif /* HDfrexp */
/* Check for Cray-specific 'frexpf()' and 'frexpl()' routines */
-#ifdef H5_HAVE_FREXPF
-#define HDfrexpf(X,N) frexpf(X,N)
-#else /* H5_HAVE_FREXPF */
-#define HDfrexpf(X,N) frexp(X,N)
-#endif /* H5_HAVE_FREXPF */
-#ifdef H5_HAVE_FREXPL
-#define HDfrexpl(X,N) frexpl(X,N)
-#else /* H5_HAVE_FREXPL */
-#define HDfrexpl(X,N) frexp(X,N)
-#endif /* H5_HAVE_FREXPL */
+#ifndef HDfrexpf
+ #ifdef H5_HAVE_FREXPF
+ #define HDfrexpf(X,N) frexpf(X,N)
+ #else /* H5_HAVE_FREXPF */
+ #define HDfrexpf(X,N) frexp(X,N)
+ #endif /* H5_HAVE_FREXPF */
+#endif /* HDfrexpf */
+#ifndef HDfrexpl
+ #ifdef H5_HAVE_FREXPL
+ #define HDfrexpl(X,N) frexpl(X,N)
+ #else /* H5_HAVE_FREXPL */
+ #define HDfrexpl(X,N) frexp(X,N)
+ #endif /* H5_HAVE_FREXPL */
+#endif /* HDfrexpl */
/* fscanf() variable arguments */
-#ifdef H5_HAVE_FSEEKO
- #define HDfseek(F,O,W) fseeko(F,O,W)
-#else
- #define HDfseek(F,O,W) fseek(F,O,W)
-#endif
-#define HDfsetpos(F,P) fsetpos(F,P)
+#ifndef HDfseek
+ #ifdef H5_HAVE_FSEEKO
+ #define HDfseek(F,O,W) fseeko(F,O,W)
+ #else /* H5_HAVE_FSEEKO */
+ #define HDfseek(F,O,W) fseek(F,O,W)
+ #endif /* H5_HAVE_FSEEKO */
+#endif /* HDfseek */
+#ifndef HDfsetpos
+ #define HDfsetpos(F,P) fsetpos(F,P)
+#endif /* HDfsetpos */
/* definitions related to the file stat utilities.
- * Windows have its own function names.
* For Unix, if off_t is not 64bit big, try use the pseudo-standard
* xxx64 versions if available.
*/
-#ifdef _WIN32
- #ifdef __MWERKS__
- #define HDfstat(F,B) fstat(F,B)
- #define HDstat(S,B) stat(S,B)
- typedef struct stat h5_stat_t;
- typedef off_t h5_stat_size_t;
- #else /*MSVC*/
- #define HDfstat(F,B) _fstati64(F,B)
- #define HDstat(S,B) _stati64(S,B)
- typedef struct _stati64 h5_stat_t;
- typedef __int64 h5_stat_size_t;
+#if !defined(HDfstat) || !defined(HDstat)
+ #if H5_SIZEOF_OFF_T!=8 && H5_SIZEOF_OFF64_T==8 && defined(H5_HAVE_STAT64)
+ #ifndef HDfstat
+ #define HDfstat(F,B) fstat64(F,B)
+ #endif /* HDfstat */
+ #ifndef HDstat
+ #define HDstat(S,B) stat64(S,B)
+ #endif /* HDstat */
+ typedef struct stat64 h5_stat_t;
+ typedef off64_t h5_stat_size_t;
+ #else /* H5_SIZEOF_OFF_T!=8 && ... */
+ #ifndef HDfstat
+ #define HDfstat(F,B) fstat(F,B)
+ #endif /* HDfstat */
+ #ifndef HDstat
+ #define HDstat(S,B) stat(S,B)
+ #endif /* HDstat */
+ typedef struct stat h5_stat_t;
+ typedef off_t h5_stat_size_t;
+ #endif /* H5_SIZEOF_OFF_T!=8 && ... */
+#endif /* !defined(HDfstat) || !defined(HDstat) */
+
+#ifndef HDftell
+ #define HDftell(F) ftell(F)
+#endif /* HDftell */
+#ifndef HDftruncate
+ #ifdef H5_HAVE_FTRUNCATE64
+ #define HDftruncate(F,L) ftruncate64(F,L)
+ #else
+ #define HDftruncate(F,L) ftruncate(F,L)
+ #endif
+#endif /* HDftruncate */
+#ifndef HDfwrite
+ #define HDfwrite(M,Z,N,F) fwrite(M,Z,N,F)
+#endif /* HDfwrite */
+#ifndef HDgetc
+ #define HDgetc(F) getc(F)
+#endif /* HDgetc */
+#ifndef HDgetchar
+ #define HDgetchar() getchar()
+#endif /* HDgetchar */
+#ifndef HDgetcwd
+ #define HDgetcwd(S,Z) getcwd(S,Z)
+#endif /* HDgetcwd */
+#ifndef HDgetdcwd
+ #define HDgetdcwd(D,S,Z) getcwd(S,Z)
+#endif /* HDgetdcwd */
+#ifndef HDgetdrive
+ #define HDgetdrive() 0
+#endif /* HDgetdrive */
+#ifndef HDgetegid
+ #define HDgetegid() getegid()
+#endif /* HDgetegid() */
+#ifndef HDgetenv
+ #define HDgetenv(S) getenv(S)
+#endif /* HDgetenv */
+#ifndef HDgeteuid
+ #define HDgeteuid() geteuid()
+#endif /* HDgeteuid */
+#ifndef HDgetgid
+ #define HDgetgid() getgid()
+#endif /* HDgetgid */
+#ifndef HDgetgrgid
+ #define HDgetgrgid(G) getgrgid(G)
+#endif /* HDgetgrgid */
+#ifndef HDgetgrnam
+ #define HDgetgrnam(S) getgrnam(S)
+#endif /* HDgetgrnam */
+#ifndef HDgetgroups
+ #define HDgetgroups(Z,G) getgroups(Z,G)
+#endif /* HDgetgroups */
+#ifndef HDgetlogin
+ #define HDgetlogin() getlogin()
+#endif /* HDgetlogin */
+#ifndef HDgetpgrp
+ #define HDgetpgrp() getpgrp()
+#endif /* HDgetpgrp */
+#ifndef HDgetpid
+ #define HDgetpid() getpid()
+#endif /* HDgetpid */
+#ifndef HDgetppid
+ #define HDgetppid() getppid()
+#endif /* HDgetppid */
+#ifndef HDgetpwnam
+ #define HDgetpwnam(S) getpwnam(S)
+#endif /* HDgetpwnam */
+#ifndef HDgetpwuid
+ #define HDgetpwuid(U) getpwuid(U)
+#endif /* HDgetpwuid */
+#ifndef HDgetrusage
+ #define HDgetrusage(X,S) getrusage(X,S)
+#endif /* HDgetrusage */
+#ifndef HDgets
+ #define HDgets(S) gets(S)
+#endif /* HDgets */
+#ifndef HDgettimeofday
+ #define HDgettimeofday(S,P) gettimeofday(S,P)
+#endif /* HDgettimeofday */
+#ifndef HDgetuid
+ #define HDgetuid() getuid()
+#endif /* HDgetuid */
+#ifndef HDgmtime
+ #define HDgmtime(T) gmtime(T)
+#endif /* HDgmtime */
+#ifndef HDisalnum
+ #define HDisalnum(C) isalnum((int)(C)) /*cast for solaris warning*/
+#endif /* HDisalnum */
+#ifndef HDisalpha
+ #define HDisalpha(C) isalpha((int)(C)) /*cast for solaris warning*/
+#endif /* HDisalpha */
+#ifndef HDisatty
+ #define HDisatty(F) isatty(F)
+#endif /* HDisatty */
+#ifndef HDiscntrl
+ #define HDiscntrl(C) iscntrl((int)(C)) /*cast for solaris warning*/
+#endif /* HDiscntrl */
+#ifndef HDisdigit
+ #define HDisdigit(C) isdigit((int)(C)) /*cast for solaris warning*/
+#endif /* HDisdigit */
+#ifndef HDisgraph
+ #define HDisgraph(C) isgraph((int)(C)) /*cast for solaris warning*/
+#endif /* HDisgraph */
+#ifndef HDislower
+ #define HDislower(C) islower((int)(C)) /*cast for solaris warning*/
+#endif /* HDislower */
+#ifndef HDisprint
+ #define HDisprint(C) isprint((int)(C)) /*cast for solaris warning*/
+#endif /* HDisprint */
+#ifndef HDispunct
+ #define HDispunct(C) ispunct((int)(C)) /*cast for solaris warning*/
+#endif /* HDispunct */
+#ifndef HDisspace
+ #define HDisspace(C) isspace((int)(C)) /*cast for solaris warning*/
+#endif /* HDisspace */
+#ifndef HDisupper
+ #define HDisupper(C) isupper((int)(C)) /*cast for solaris warning*/
+#endif /* HDisupper */
+#ifndef HDisxdigit
+ #define HDisxdigit(C) isxdigit((int)(C)) /*cast for solaris warning*/
+#endif /* HDisxdigit */
+#ifndef HDkill
+ #define HDkill(P,S) kill(P,S)
+#endif /* HDkill */
+#ifndef HDlabs
+ #define HDlabs(X) labs(X)
+#endif /* HDlabs */
+#ifndef HDldexp
+ #define HDldexp(X,N) ldexp(X,N)
+#endif /* HDldexp */
+#ifndef HDldiv
+ #define HDldiv(X,Y) ldiv(X,Y)
+#endif /* HDldiv */
+#ifndef HDlink
+ #define HDlink(OLD,NEW) link(OLD,NEW)
+#endif /* HDlink */
+#ifndef HDlocaleconv
+ #define HDlocaleconv() localeconv()
+#endif /* HDlocaleconv */
+#ifndef HDlocaltime
+ #define HDlocaltime(T) localtime(T)
+#endif /* HDlocaltime */
+#ifndef HDlog
+ #define HDlog(X) log(X)
+#endif /* HDlog */
+#ifndef HDlog10
+ #define HDlog10(X) log10(X)
+#endif /* HDlog10 */
+#ifndef HDlongjmp
+ #define HDlongjmp(J,N) longjmp(J,N)
+#endif /* HDlongjmp */
+#ifndef HDlseek
+ #ifdef H5_HAVE_LSEEK64
+ #define HDlseek(F,O,W) lseek64(F,O,W)
+ #else
+ #define HDlseek(F,O,W) lseek(F,O,W)
#endif
-#elif H5_SIZEOF_OFF_T!=8 && H5_SIZEOF_OFF64_T==8 && defined(H5_HAVE_STAT64)
- #define HDfstat(F,B) fstat64(F,B)
- #define HDstat(S,B) stat64(S,B)
- typedef struct stat64 h5_stat_t;
- typedef off64_t h5_stat_size_t;
-#else
- #define HDfstat(F,B) fstat(F,B)
- #define HDstat(S,B) stat(S,B)
- typedef struct stat h5_stat_t;
- typedef off_t h5_stat_size_t;
-#endif
-
-#define HDftell(F) ftell(F)
-#define HDftruncate(F,L) ftruncate(F,L)
-#define HDfwrite(M,Z,N,F) fwrite(M,Z,N,F)
-#define HDgetc(F) getc(F)
-#define HDgetchar() getchar()
-#define HDgetcwd(S,Z) getcwd(S,Z)
-#define HDgetegid() getegid()
-#define HDgetenv(S) getenv(S)
-#define HDgeteuid() geteuid()
-#define HDgetgid() getgid()
-#define HDgetgrgid(G) getgrgid(G)
-#define HDgetgrnam(S) getgrnam(S)
-#define HDgetgroups(Z,G) getgroups(Z,G)
-#define HDgetlogin() getlogin()
-#define HDgetpgrp() getpgrp()
-#define HDgetpid() getpid()
-#define HDgetppid() getppid()
-#define HDgetpwnam(S) getpwnam(S)
-#define HDgetpwuid(U) getpwuid(U)
-#define HDgetrusage(X,S) getrusage(X,S)
-#define HDgets(S) gets(S)
-#define HDgettimeofday(S,P) gettimeofday(S,P)
-#define HDgetuid() getuid()
-#define HDgmtime(T) gmtime(T)
-#define HDisalnum(C) isalnum((int)(C)) /*cast for solaris warning*/
-#define HDisalpha(C) isalpha((int)(C)) /*cast for solaris warning*/
-#define HDisatty(F) isatty(F)
-#define HDiscntrl(C) iscntrl((int)(C)) /*cast for solaris warning*/
-#define HDisdigit(C) isdigit((int)(C)) /*cast for solaris warning*/
-#define HDisgraph(C) isgraph((int)(C)) /*cast for solaris warning*/
-#define HDislower(C) islower((int)(C)) /*cast for solaris warning*/
-#define HDisprint(C) isprint((int)(C)) /*cast for solaris warning*/
-#define HDispunct(C) ispunct((int)(C)) /*cast for solaris warning*/
-#define HDisspace(C) isspace((int)(C)) /*cast for solaris warning*/
-#define HDisupper(C) isupper((int)(C)) /*cast for solaris warning*/
-#define HDisxdigit(C) isxdigit((int)(C)) /*cast for solaris warning*/
-#define HDkill(P,S) kill(P,S)
-#define HDlabs(X) labs(X)
-#define HDldexp(X,N) ldexp(X,N)
-#define HDldiv(X,Y) ldiv(X,Y)
-#define HDlink(OLD,NEW) link(OLD,NEW)
-#define HDlocaleconv() localeconv()
-#define HDlocaltime(T) localtime(T)
-#define HDlog(X) log(X)
-#define HDlog10(X) log10(X)
-#define HDlongjmp(J,N) longjmp(J,N)
-#ifdef _WIN32
- #ifdef __MWERKS__
- #define HDlseek(F,O,W) lseek(F,O,W)
- #else /*MSVS */
- #define HDlseek(F,O,W) _lseeki64(F,O,W)
- #endif
-#else
- #ifdef H5_HAVE_FSEEK64
- #define HDlseek(F,O,W) lseek64(F,O,W)
- #else
- #define HDlseek(F,O,W) lseek(F,O,W)
- #endif
-#endif
-#define HDmalloc(Z) malloc(Z)
-#define HDposix_memalign(P,A,Z) posix_memalign(P,A,Z)
-#define HDmblen(S,N) mblen(S,N)
-#define HDmbstowcs(P,S,Z) mbstowcs(P,S,Z)
-#define HDmbtowc(P,S,Z) mbtowc(P,S,Z)
-#define HDmemchr(S,C,Z) memchr(S,C,Z)
-#define HDmemcmp(X,Y,Z) memcmp(X,Y,Z)
+#endif /* HDlseek */
+#ifndef HDmalloc
+ #define HDmalloc(Z) malloc(Z)
+#endif /* HDmalloc */
+#ifndef HDposix_memalign
+ #define HDposix_memalign(P,A,Z) posix_memalign(P,A,Z)
+#endif /* HDposix_memalign */
+#ifndef HDmblen
+ #define HDmblen(S,N) mblen(S,N)
+#endif /* HDmblen */
+#ifndef HDmbstowcs
+ #define HDmbstowcs(P,S,Z) mbstowcs(P,S,Z)
+#endif /* HDmbstowcs */
+#ifndef HDmbtowc
+ #define HDmbtowc(P,S,Z) mbtowc(P,S,Z)
+#endif /* HDmbtowc */
+#ifndef HDmemchr
+ #define HDmemchr(S,C,Z) memchr(S,C,Z)
+#endif /* HDmemchr */
+#ifndef HDmemcmp
+ #define HDmemcmp(X,Y,Z) memcmp(X,Y,Z)
+#endif /* HDmemcmp */
/*
* The (char*) casts are required for the DEC when optimizations are turned
* on and the source and/or destination are not aligned.
*/
-#define HDmemcpy(X,Y,Z) memcpy((char*)(X),(const char*)(Y),Z)
-#define HDmemmove(X,Y,Z) memmove((char*)(X),(const char*)(Y),Z)
-/*
- * The (void*) cast just avoids a compiler warning in _WIN32
- */
-#ifdef _WIN32
-#define HDmemset(X,C,Z) memset((void*)(X),C,Z)
-#else /* _WIN32 */
-#define HDmemset(X,C,Z) memset(X,C,Z)
-#endif /* _WIN32 */
-#ifdef _WIN32
-#define HDmkdir(S,M) _mkdir(S)
-#else /* _WIN32 */
-#define HDmkdir(S,M) mkdir(S,M)
-#endif /* _WIN32 */
-#define HDmkfifo(S,M) mkfifo(S,M)
-#define HDmktime(T) mktime(T)
-#define HDmodf(X,Y) modf(X,Y)
-#ifdef _O_BINARY
-#define HDopen(S,F,M) open(S,F|_O_BINARY,M)
-#else
-#define HDopen(S,F,M) open(S,F,M)
-#endif
-#define HDopendir(S) opendir(S)
-#define HDpathconf(S,N) pathconf(S,N)
-#define HDpause() pause()
-#define HDperror(S) perror(S)
-#define HDpipe(F) pipe(F)
-#define HDpow(X,Y) pow(X,Y)
+#ifndef HDmemcpy
+ #define HDmemcpy(X,Y,Z) memcpy((char*)(X),(const char*)(Y),Z)
+#endif /* HDmemcpy */
+#ifndef HDmemmove
+ #define HDmemmove(X,Y,Z) memmove((char*)(X),(const char*)(Y),Z)
+#endif /* HDmemmove */
+#ifndef HDmemset
+ #define HDmemset(X,C,Z) memset(X,C,Z)
+#endif /* HDmemset */
+#ifndef HDmkdir
+ #define HDmkdir(S,M) mkdir(S,M)
+#endif /* HDmkdir */
+#ifndef HDmkfifo
+ #define HDmkfifo(S,M) mkfifo(S,M)
+#endif /* HDmkfifo */
+#ifndef HDmktime
+ #define HDmktime(T) mktime(T)
+#endif /* HDmktime */
+#ifndef HDmodf
+ #define HDmodf(X,Y) modf(X,Y)
+#endif /* HDmodf */
+#ifndef HDopen
+ #ifdef _O_BINARY
+ #define HDopen(S,F,M) open(S,F|_O_BINARY,M)
+ #else
+ #define HDopen(S,F,M) open(S,F,M)
+ #endif
+#endif /* HDopen */
+#ifndef HDopendir
+ #define HDopendir(S) opendir(S)
+#endif /* HDopendir */
+#ifndef HDpathconf
+ #define HDpathconf(S,N) pathconf(S,N)
+#endif /* HDpathconf */
+#ifndef HDpause
+ #define HDpause() pause()
+#endif /* HDpause */
+#ifndef HDperror
+ #define HDperror(S) perror(S)
+#endif /* HDperror */
+#ifndef HDpipe
+ #define HDpipe(F) pipe(F)
+#endif /* HDpipe */
+#ifndef HDpow
+ #define HDpow(X,Y) pow(X,Y)
+#endif /* HDpow */
/* printf() variable arguments */
-#define HDputc(C,F) putc(C,F)
-#define HDputchar(C) putchar(C)
-#define HDputs(S) puts(S)
-#define HDqsort(M,N,Z,F) qsort(M,N,Z,F)
-#define HDraise(N) raise(N)
+#ifndef HDputc
+ #define HDputc(C,F) putc(C,F)
+#endif /* HDputc*/
+#ifndef HDputchar
+ #define HDputchar(C) putchar(C)
+#endif /* HDputchar */
+#ifndef HDputs
+ #define HDputs(S) puts(S)
+#endif /* HDputs */
+#ifndef HDqsort
+ #define HDqsort(M,N,Z,F) qsort(M,N,Z,F)
+#endif /* HDqsort*/
+#ifndef HDraise
+ #define HDraise(N) raise(N)
+#endif /* HDraise */
#ifdef H5_HAVE_RAND_R
-#define HDrandom() HDrand()
-H5_DLL int HDrand(void);
+ #ifndef HDrandom
+ #define HDrandom() HDrand()
+ #endif /* HDrandom */
+ H5_DLL int HDrand(void);
#elif H5_HAVE_RANDOM
-#define HDrand() random()
-#define HDrandom() random()
-#else
-#define HDrand() rand()
-#define HDrandom() rand()
-#endif
-
-#define HDread(F,M,Z) read(F,M,Z)
-#define HDreaddir(D) readdir(D)
-#define HDrealloc(M,Z) realloc(M,Z)
+ #ifndef HDrand
+ #define HDrand() random()
+ #endif /* HDrand */
+ #ifndef HDrandom
+ #define HDrandom() random()
+ #endif /* HDrandom */
+#else /* H5_HAVE_RANDOM */
+ #ifndef HDrand
+ #define HDrand() rand()
+ #endif /* HDrand */
+ #ifndef HDrandom
+ #define HDrandom() rand()
+ #endif /* HDrandom */
+#endif /* H5_HAVE_RANDOM */
+
+#ifndef HDread
+ #define HDread(F,M,Z) read(F,M,Z)
+#endif /* HDread */
+#ifndef HDreaddir
+ #define HDreaddir(D) readdir(D)
+#endif /* HDreaddir */
+#ifndef HDrealloc
+ #define HDrealloc(M,Z) realloc(M,Z)
+#endif /* HDrealloc */
#ifdef H5_VMS
-#ifdef __cplusplus
-extern "C" {
-#endif
-int HDremove_all(const char * fname);
-#ifdef __cplusplus
-}
-#endif
-#define HDremove(S) HDremove_all(S)
-#else
-#define HDremove(S) remove(S)
+ #ifdef __cplusplus
+ extern "C" {
+ #endif /* __cplusplus */
+ int HDremove_all(const char * fname);
+ #ifdef __cplusplus
+ }
+ #endif /* __cplusplus */
+ #ifndef HDremove
+ #define HDremove(S) HDremove_all(S)
+ #endif /* HDremove */
+#else /* H5_VMS */
+ #ifndef HDremove
+ #define HDremove(S) remove(S)
+ #endif /* HDremove */
#endif /*H5_VMS*/
-#define HDrename(OLD,NEW) rename(OLD,NEW)
-#define HDrewind(F) rewind(F)
-#define HDrewinddir(D) rewinddir(D)
-#define HDrmdir(S) rmdir(S)
+#ifndef HDrename
+ #define HDrename(OLD,NEW) rename(OLD,NEW)
+#endif /* HDrename */
+#ifndef HDrewind
+ #define HDrewind(F) rewind(F)
+#endif /* HDrewind */
+#ifndef HDrewinddir
+ #define HDrewinddir(D) rewinddir(D)
+#endif /* HDrewinddir */
+#ifndef HDrmdir
+ #define HDrmdir(S) rmdir(S)
+#endif /* HDrmdir */
/* scanf() variable arguments */
-#define HDsetbuf(F,S) setbuf(F,S)
-#define HDsetgid(G) setgid(G)
-#define HDsetjmp(J) setjmp(J)
-#define HDsetlocale(N,S) setlocale(N,S)
-#define HDsetpgid(P,PG) setpgid(P,PG)
-#define HDsetsid() setsid()
-#define HDsetuid(U) setuid(U)
-/* Windows does not permit setting the buffer size to values
- less than 2. */
-#ifndef _WIN32
-#define HDsetvbuf(F,S,M,Z) setvbuf(F,S,M,Z)
-#else
-#define HDsetvbuf(F,S,M,Z) setvbuf(F,S,M,(Z>1?Z:2))
-#endif
-#define HDsigaction(N,A) sigaction(N,A)
-#define HDsigaddset(S,N) sigaddset(S,N)
-#define HDsigdelset(S,N) sigdelset(S,N)
-#define HDsigemptyset(S) sigemptyset(S)
-#define HDsigfillset(S) sigfillset(S)
-#define HDsigismember(S,N) sigismember(S,N)
-#define HDsiglongjmp(J,N) siglongjmp(J,N)
-#define HDsignal(N,F) signal(N,F)
-#define HDsigpending(S) sigpending(S)
-#define HDsigprocmask(H,S,O) sigprocmask(H,S,O)
-#define HDsigsetjmp(J,N) sigsetjmp(J,N)
-#define HDsigsuspend(S) sigsuspend(S)
-#define HDsin(X) sin(X)
-#define HDsinh(X) sinh(X)
-#define HDsleep(N) sleep(N)
-#ifdef _WIN32
-#define HDsnprintf _snprintf /*varargs*/
-#else
-#define HDsnprintf snprintf /*varargs*/
-#endif
+#ifndef HDsetbuf
+ #define HDsetbuf(F,S) setbuf(F,S)
+#endif /* HDsetbuf */
+#ifndef HDsetgid
+ #define HDsetgid(G) setgid(G)
+#endif /* HDsetgid */
+#ifndef HDsetjmp
+ #define HDsetjmp(J) setjmp(J)
+#endif /* HDsetjmp */
+#ifndef HDsetlocale
+ #define HDsetlocale(N,S) setlocale(N,S)
+#endif /* HDsetlocale */
+#ifndef HDsetpgid
+ #define HDsetpgid(P,PG) setpgid(P,PG)
+#endif /* HDsetpgid */
+#ifndef HDsetsid
+ #define HDsetsid() setsid()
+#endif /* HDsetsid */
+#ifndef HDsetuid
+ #define HDsetuid(U) setuid(U)
+#endif /* HDsetuid */
+#ifndef HDsetvbuf
+ #define HDsetvbuf(F,S,M,Z) setvbuf(F,S,M,Z)
+#endif /* HDsetvbuf */
+#ifndef HDsigaction
+ #define HDsigaction(N,A) sigaction(N,A)
+#endif /* HDsigaction */
+#ifndef HDsigaddset
+ #define HDsigaddset(S,N) sigaddset(S,N)
+#endif /* HDsigaddset */
+#ifndef HDsigdelset
+ #define HDsigdelset(S,N) sigdelset(S,N)
+#endif /* HDsigdelset */
+#ifndef HDsigemptyset
+ #define HDsigemptyset(S) sigemptyset(S)
+#endif /* HDsigemptyset */
+#ifndef HDsigfillset
+ #define HDsigfillset(S) sigfillset(S)
+#endif /* HDsigfillset */
+#ifndef HDsigismember
+ #define HDsigismember(S,N) sigismember(S,N)
+#endif /* HDsigismember */
+#ifndef HDsiglongjmp
+ #define HDsiglongjmp(J,N) siglongjmp(J,N)
+#endif /* HDsiglongjmp */
+#ifndef HDsignal
+ #define HDsignal(N,F) signal(N,F)
+#endif /* HDsignal */
+#ifndef HDsigpending
+ #define HDsigpending(S) sigpending(S)
+#endif /* HDsigpending */
+#ifndef HDsigprocmask
+ #define HDsigprocmask(H,S,O) sigprocmask(H,S,O)
+#endif /* HDsigprocmask */
+#ifndef HDsigsetjmp
+ #define HDsigsetjmp(J,N) sigsetjmp(J,N)
+#endif /* HDsigsetjmp */
+#ifndef HDsigsuspend
+ #define HDsigsuspend(S) sigsuspend(S)
+#endif /* HDsigsuspend */
+#ifndef HDsin
+ #define HDsin(X) sin(X)
+#endif /* HDsin */
+#ifndef HDsinh
+ #define HDsinh(X) sinh(X)
+#endif /* HDsinh */
+#ifndef HDsleep
+ #define HDsleep(N) sleep(N)
+#endif /* HDsleep */
+#ifndef HDsnprintf
+ #define HDsnprintf snprintf /*varargs*/
+#endif /* HDsnprintf */
/* sprintf() variable arguments */
-#define HDsqrt(X) sqrt(X)
+#ifndef HDsqrt
+ #define HDsqrt(X) sqrt(X)
+#endif /* HDsqrt */
#ifdef H5_HAVE_RAND_R
-H5_DLL void HDsrand(unsigned int seed);
-#define HDsrandom(S) HDsrand(S)
-#elif H5_HAVE_RANDOM
-#define HDsrand(S) srandom(S)
-#define HDsrandom(S) srandom(S)
-#else
-#define HDsrand(S) srand(S)
-#define HDsrandom(S) srand(S)
-#endif
+ H5_DLL void HDsrand(unsigned int seed);
+ #ifndef HDsrandom
+ #define HDsrandom(S) HDsrand(S)
+ #endif /* HDsrandom */
+ #elif H5_HAVE_RANDOM
+ #ifndef HDsrand
+ #define HDsrand(S) srandom(S)
+ #endif /* HDsrand */
+ #ifndef HDsrandom
+ #define HDsrandom(S) srandom(S)
+ #endif /* HDsrandom */
+#else /* H5_HAVE_RAND_R */
+ #ifndef HDsrand
+ #define HDsrand(S) srand(S)
+ #endif /* HDsrand */
+ #ifndef HDsrandom
+ #define HDsrandom(S) srand(S)
+ #endif /* HDsrandom */
+#endif /* H5_HAVE_RAND_R */
/* sscanf() variable arguments */
-#define HDstrcat(X,Y) strcat(X,Y)
-#define HDstrchr(S,C) strchr(S,C)
-#define HDstrcmp(X,Y) strcmp(X,Y)
-#define HDstrcoll(X,Y) strcoll(X,Y)
-#define HDstrcpy(X,Y) strcpy(X,Y)
-#define HDstrcspn(X,Y) strcspn(X,Y)
-#define HDstrerror(N) strerror(N)
-#define HDstrftime(S,Z,F,T) strftime(S,Z,F,T)
-#define HDstrlen(S) strlen(S)
-#define HDstrncat(X,Y,Z) strncat(X,Y,Z)
-#define HDstrncmp(X,Y,Z) strncmp(X,Y,Z)
-#define HDstrncpy(X,Y,Z) strncpy(X,Y,Z)
-#define HDstrpbrk(X,Y) strpbrk(X,Y)
-#define HDstrrchr(S,C) strrchr(S,C)
-#define HDstrspn(X,Y) strspn(X,Y)
-#define HDstrstr(X,Y) strstr(X,Y)
-#define HDstrtod(S,R) strtod(S,R)
-#define HDstrtok(X,Y) strtok(X,Y)
-#define HDstrtol(S,R,N) strtol(S,R,N)
+#ifndef HDstrcat
+ #define HDstrcat(X,Y) strcat(X,Y)
+#endif /* HDstrcat */
+#ifndef HDstrchr
+ #define HDstrchr(S,C) strchr(S,C)
+#endif /* HDstrchr */
+#ifndef HDstrcmp
+ #define HDstrcmp(X,Y) strcmp(X,Y)
+#endif /* HDstrcmp */
+#ifndef HDstrcoll
+ #define HDstrcoll(X,Y) strcoll(X,Y)
+#endif /* HDstrcoll */
+#ifndef HDstrcpy
+ #define HDstrcpy(X,Y) strcpy(X,Y)
+#endif /* HDstrcpy */
+#ifndef HDstrcspn
+ #define HDstrcspn(X,Y) strcspn(X,Y)
+#endif /* HDstrcspn */
+#ifndef HDstrerror
+ #define HDstrerror(N) strerror(N)
+#endif /* HDstrerror */
+#ifndef HDstrftime
+ #define HDstrftime(S,Z,F,T) strftime(S,Z,F,T)
+#endif /* HDstrftime */
+#ifndef HDstrlen
+ #define HDstrlen(S) strlen(S)
+#endif /* HDstrlen */
+#ifndef HDstrncat
+ #define HDstrncat(X,Y,Z) strncat(X,Y,Z)
+#endif /* HDstrncat */
+#ifndef HDstrncmp
+ #define HDstrncmp(X,Y,Z) strncmp(X,Y,Z)
+#endif /* HDstrncmp */
+#ifndef HDstrncpy
+ #define HDstrncpy(X,Y,Z) strncpy(X,Y,Z)
+#endif /* HDstrncpy */
+#ifndef HDstrpbrk
+ #define HDstrpbrk(X,Y) strpbrk(X,Y)
+#endif /* HDstrpbrk */
+#ifndef HDstrrchr
+ #define HDstrrchr(S,C) strrchr(S,C)
+#endif /* HDstrrchr */
+#ifndef HDstrspn
+ #define HDstrspn(X,Y) strspn(X,Y)
+#endif /* HDstrspn */
+#ifndef HDstrstr
+ #define HDstrstr(X,Y) strstr(X,Y)
+#endif /* HDstrstr */
+#ifndef HDstrtod
+ #define HDstrtod(S,R) strtod(S,R)
+#endif /* HDstrtod */
+#ifndef HDstrtok
+ #define HDstrtok(X,Y) strtok(X,Y)
+#endif /* HDstrtok */
+#ifndef HDstrtol
+ #define HDstrtol(S,R,N) strtol(S,R,N)
+#endif /* HDstrtol */
H5_DLL int64_t HDstrtoll (const char *s, const char **rest, int base);
-#define HDstrtoul(S,R,N) strtoul(S,R,N)
-#define HDstrxfrm(X,Y,Z) strxfrm(X,Y,Z)
-#define HDsysconf(N) sysconf(N)
-#define HDsystem(S) system(S)
-#define HDtan(X) tan(X)
-#define HDtanh(X) tanh(X)
-#define HDtcdrain(F) tcdrain(F)
-#define HDtcflow(F,A) tcflow(F,A)
-#define HDtcflush(F,N) tcflush(F,N)
-#define HDtcgetattr(F,T) tcgetattr(F,T)
-#define HDtcgetpgrp(F) tcgetpgrp(F)
-#define HDtcsendbreak(F,N) tcsendbreak(F,N)
-#define HDtcsetattr(F,O,T) tcsetattr(F,O,T)
-#define HDtcsetpgrp(F,N) tcsetpgrp(F,N)
-#define HDtime(T) time(T)
-#define HDtimes(T) times(T)
-#define HDtmpfile() tmpfile()
-#define HDtmpnam(S) tmpnam(S)
-#define HDtolower(C) tolower(C)
-#define HDtoupper(C) toupper(C)
-#define HDttyname(F) ttyname(F)
-#define HDtzset() tzset()
-#define HDumask(N) umask(N)
-#define HDuname(S) uname(S)
-#define HDungetc(C,F) ungetc(C,F)
-#ifdef _WIN32
-#define HDunlink(S) _unlink(S)
-#else
-#define HDunlink(S) unlink(S)
-#endif
-#define HDutime(S,T) utime(S,T)
-#define HDva_arg(A,T) va_arg(A,T)
-#define HDva_end(A) va_end(A)
-#define HDva_start(A,P) va_start(A,P)
-#define HDvasprintf(RET,FMT,A) vasprintf(RET,FMT,A)
-#define HDvfprintf(F,FMT,A) vfprintf(F,FMT,A)
-#define HDvprintf(FMT,A) vprintf(FMT,A)
-#define HDvsprintf(S,FMT,A) vsprintf(S,FMT,A)
-#ifdef _WIN32
-# define HDvsnprintf(S,N,FMT,A) _vsnprintf(S,N,FMT,A)
-#else
-# define HDvsnprintf(S,N,FMT,A) vsnprintf(S,N,FMT,A)
-#endif
-#define HDwait(W) wait(W)
-#define HDwaitpid(P,W,O) waitpid(P,W,O)
-#define HDwcstombs(S,P,Z) wcstombs(S,P,Z)
-#define HDwctomb(S,C) wctomb(S,C)
-
-#if defined (__MWERKS__)
-/* workaround for a bug in the Metrowerks version 6.0 header file for write
- which is not defined as const void*
- */
-#define HDwrite(F,M,Z) write(F,(void*)M,Z)
-#else
-#define HDwrite(F,M,Z) write(F,M,Z)
-#endif
+#ifndef HDstrtoul
+ #define HDstrtoul(S,R,N) strtoul(S,R,N)
+#endif /* HDstrtoul */
+#ifndef HDstrxfrm
+ #define HDstrxfrm(X,Y,Z) strxfrm(X,Y,Z)
+#endif /* HDstrxfrm */
+#ifndef HDsysconf
+ #define HDsysconf(N) sysconf(N)
+#endif /* HDsysconf */
+#ifndef HDsystem
+ #define HDsystem(S) system(S)
+#endif /* HDsystem */
+#ifndef HDtan
+ #define HDtan(X) tan(X)
+#endif /* HDtan */
+#ifndef HDtanh
+ #define HDtanh(X) tanh(X)
+#endif /* HDtanh */
+#ifndef HDtcdrain
+ #define HDtcdrain(F) tcdrain(F)
+#endif /* HDtcdrain */
+#ifndef HDtcflow
+ #define HDtcflow(F,A) tcflow(F,A)
+#endif /* HDtcflow */
+#ifndef HDtcflush
+ #define HDtcflush(F,N) tcflush(F,N)
+#endif /* HDtcflush */
+#ifndef HDtcgetattr
+ #define HDtcgetattr(F,T) tcgetattr(F,T)
+#endif /* HDtcgetattr */
+#ifndef HDtcgetpgrp
+ #define HDtcgetpgrp(F) tcgetpgrp(F)
+#endif /* HDtcgetpgrp */
+#ifndef HDtcsendbreak
+ #define HDtcsendbreak(F,N) tcsendbreak(F,N)
+#endif /* HDtcsendbreak */
+#ifndef HDtcsetattr
+ #define HDtcsetattr(F,O,T) tcsetattr(F,O,T)
+#endif /* HDtcsetattr */
+#ifndef HDtcsetpgrp
+ #define HDtcsetpgrp(F,N) tcsetpgrp(F,N)
+#endif /* HDtcsetpgrp */
+#ifndef HDtime
+ #define HDtime(T) time(T)
+#endif /* HDtime */
+#ifndef HDtimes
+ #define HDtimes(T) times(T)
+#endif /* HDtimes*/
+#ifndef HDtmpfile
+ #define HDtmpfile() tmpfile()
+#endif /* HDtmpfile */
+#ifndef HDtmpnam
+ #define HDtmpnam(S) tmpnam(S)
+#endif /* HDtmpnam */
+#ifndef HDtolower
+ #define HDtolower(C) tolower(C)
+#endif /* HDtolower */
+#ifndef HDtoupper
+ #define HDtoupper(C) toupper(C)
+#endif /* HDtoupper */
+#ifndef HDttyname
+ #define HDttyname(F) ttyname(F)
+#endif /* HDttyname */
+#ifndef HDtzset
+ #define HDtzset() tzset()
+#endif /* HDtzset */
+#ifndef HDumask
+ #define HDumask(N) umask(N)
+#endif /* HDumask */
+#ifndef HDuname
+ #define HDuname(S) uname(S)
+#endif /* HDuname */
+#ifndef HDungetc
+ #define HDungetc(C,F) ungetc(C,F)
+#endif /* HDungetc */
+#ifndef HDunlink
+ #define HDunlink(S) unlink(S)
+#endif /* HDunlink */
+#ifndef HDutime
+ #define HDutime(S,T) utime(S,T)
+#endif /* HDutime */
+#ifndef HDva_arg
+ #define HDva_arg(A,T) va_arg(A,T)
+#endif /* HDva_arg */
+#ifndef HDva_end
+ #define HDva_end(A) va_end(A)
+#endif /* HDva_end */
+#ifndef HDva_start
+ #define HDva_start(A,P) va_start(A,P)
+#endif /* HDva_start */
+#ifndef HDvasprintf
+ #define HDvasprintf(RET,FMT,A) vasprintf(RET,FMT,A)
+#endif /* HDvasprintf */
+#ifndef HDvfprintf
+ #define HDvfprintf(F,FMT,A) vfprintf(F,FMT,A)
+#endif /* HDvfprintf */
+#ifndef HDvprintf
+ #define HDvprintf(FMT,A) vprintf(FMT,A)
+#endif /* HDvprintf */
+#ifndef HDvsprintf
+ #define HDvsprintf(S,FMT,A) vsprintf(S,FMT,A)
+#endif /* HDvsprintf */
+#ifndef HDvsnprintf
+ #define HDvsnprintf(S,N,FMT,A) vsnprintf(S,N,FMT,A)
+#endif /* HDvsnprintf */
+#ifndef HDwait
+ #define HDwait(W) wait(W)
+#endif /* HDwait */
+#ifndef HDwaitpid
+ #define HDwaitpid(P,W,O) waitpid(P,W,O)
+#endif /* HDwaitpid */
+#ifndef HDwcstombs
+ #define HDwcstombs(S,P,Z) wcstombs(S,P,Z)
+#endif /* HDwcstombs */
+#ifndef HDwctomb
+ #define HDwctomb(S,C) wctomb(S,C)
+#endif /* HDwctomb */
+#ifndef HDwrite
+ #define HDwrite(F,M,Z) write(F,M,Z)
+#endif /* HDwrite */
/*
* And now for a couple non-Posix functions... Watch out for systems that
* define these in terms of macros.
*/
-#ifdef _WIN32
-#define HDstrdup(S) _strdup(S)
-#else /* _WIN32 */
-
#if !defined strdup && !defined H5_HAVE_STRDUP
extern char *strdup(const char *s);
#endif
-#define HDstrdup(S) strdup(S)
+#ifndef HDstrdup
+ #define HDstrdup(S) strdup(S)
+#endif /* HDstrdup */
+
+#ifndef HDpthread_self
+ #define HDpthread_self() pthread_self()
+#endif /* HDpthread_self */
+
+/* Use this version of pthread_self for printing the thread ID */
+#ifndef HDpthread_self_ulong
+ #define HDpthread_self_ulong() ((unsigned long)pthread_self())
+#endif /* HDpthread_self_ulong */
+
+
+#ifdef H5_HAVE_WINDOW_PATH
+
+/* directory delimiter for Windows: slash and backslash are acceptable on Windows */
+#define DIR_SLASH_SEPC '/'
+#define DIR_SEPC '\\'
+#define DIR_SEPS "\\"
+#define CHECK_DELIMITER(SS) ((SS == DIR_SEPC)||(SS == DIR_SLASH_SEPC))
+#define CHECK_ABSOLUTE(NAME) ((isalpha(NAME[0])) && (NAME[1] == ':') && (CHECK_DELIMITER(NAME[2])))
+#define CHECK_ABS_DRIVE(NAME) ((isalpha(NAME[0])) && (NAME[1] == ':'))
+#define CHECK_ABS_PATH(NAME) (CHECK_DELIMITER(NAME[0]))
+
+#define GET_LAST_DELIMITER(NAME, ptr) { \
+ char *slash, *backslash; \
+ slash = strrchr(NAME, DIR_SLASH_SEPC); \
+ backslash = strrchr(NAME, DIR_SEPC); \
+ if (backslash > slash) \
+ (ptr = backslash); \
+ else \
+ (ptr = slash); \
+}
+
+#else
-#endif /* _WIN32 */
+#define DIR_SEPC '/'
+#define DIR_SEPS "/"
+#define CHECK_DELIMITER(SS) (SS == DIR_SEPC)
+#define CHECK_ABSOLUTE(NAME) (CHECK_DELIMITER(*NAME))
+#define CHECK_ABS_DRIVE(NAME) (0)
+#define CHECK_ABS_PATH(NAME) (0)
+#define GET_LAST_DELIMITER(NAME, ptr) ptr = strrchr(NAME, DIR_SEPC);
+
+#endif
+
+#define COLON_SEPC ':'
+H5_DLL herr_t H5_build_extpath(const char *, char ** /*out*/ );
/*
@@ -1115,8 +1622,8 @@ extern hbool_t H5_libinit_g; /* Has the library been initialized? */
/* Include required function stack header */
#include "H5CSprivate.h"
-#define H5_PUSH_FUNC(func_name) H5CS_push(#func_name)
-#define H5_POP_FUNC H5CS_pop()
+#define H5_PUSH_FUNC(func_name) H5CS_push(func_name);
+#define H5_POP_FUNC H5CS_pop();
#else /* H5_HAVE_CODESTACK */
#define H5_PUSH_FUNC(func_name) /* void */
#define H5_POP_FUNC /* void */
@@ -1226,7 +1733,7 @@ static herr_t H5_INTERFACE_INIT_FUNC(void);
FUNC_ENTER_API_VARS(func_name) \
FUNC_ENTER_COMMON(func_name,H5_IS_API(#func_name)); \
FUNC_ENTER_API_THREADSAFE; \
- H5_PUSH_FUNC(func_name); \
+ H5_PUSH_FUNC(#func_name) \
BEGIN_MPE_LOG(func_name); \
{
@@ -1266,7 +1773,7 @@ static herr_t H5_INTERFACE_INIT_FUNC(void);
*/
#define FUNC_ENTER_NOAPI_NOINIT(func_name) { \
FUNC_ENTER_COMMON(func_name,!H5_IS_API(#func_name)); \
- H5_PUSH_FUNC(func_name); \
+ H5_PUSH_FUNC(#func_name) \
{
/*
@@ -1283,7 +1790,7 @@ static herr_t H5_INTERFACE_INIT_FUNC(void);
*/
#define FUNC_ENTER_NOAPI_NOINIT_NOFUNC(func_name) { \
FUNC_ENTER_COMMON_NOFUNC(func_name,!H5_IS_API(#func_name)); \
- H5_PUSH_FUNC(func_name); \
+ H5_PUSH_FUNC(#func_name) \
{
/*
@@ -1312,7 +1819,7 @@ static herr_t H5_INTERFACE_INIT_FUNC(void);
H5_INTERFACE_INIT(err) \
\
/* Push the name of this function on the function stack */ \
- H5_PUSH_FUNC(func_name); \
+ H5_PUSH_FUNC(#func_name) \
\
BEGIN_MPE_LOG(func_name)
@@ -1322,7 +1829,7 @@ static herr_t H5_INTERFACE_INIT_FUNC(void);
H5_INTERFACE_INIT(err) \
\
/* Push the name of this function on the function stack */ \
- H5_PUSH_FUNC(func_name);
+ H5_PUSH_FUNC(#func_name)
/*-------------------------------------------------------------------------
* Purpose: Register function exit for code profiling. This should be
@@ -1343,7 +1850,7 @@ static herr_t H5_INTERFACE_INIT_FUNC(void);
#define FUNC_LEAVE_API(ret_value) \
FINISH_MPE_LOG; \
H5TRACE_RETURN(ret_value); \
- H5_POP_FUNC; \
+ H5_POP_FUNC \
FUNC_LEAVE_API_THREADSAFE \
return (ret_value); \
} /*end scope from end of FUNC_ENTER*/ \
@@ -1358,13 +1865,13 @@ static herr_t H5_INTERFACE_INIT_FUNC(void);
}} /*end scope from beginning of FUNC_ENTER*/
#define FUNC_LEAVE_NOAPI(ret_value) \
- H5_POP_FUNC; \
+ H5_POP_FUNC \
return (ret_value); \
} /*end scope from end of FUNC_ENTER*/ \
} /*end scope from beginning of FUNC_ENTER*/
#define FUNC_LEAVE_NOAPI_VOID \
- H5_POP_FUNC; \
+ H5_POP_FUNC \
return; \
} /*end scope from end of FUNC_ENTER*/ \
} /*end scope from beginning of FUNC_ENTER*/
@@ -1383,6 +1890,10 @@ static herr_t H5_INTERFACE_INIT_FUNC(void);
/* Macro for "glueing" together items, for re-scanning macros */
#define H5_GLUE(x,y) x##y
#define H5_GLUE3(x,y,z) x##y##z
+#define H5_GLUE4(w,x,y,z) w##x##y##z
+
+/* Compile-time "assert" macro */
+#define HDcompile_assert(e) do { enum { compile_assert__ = 1 / (e) }; } while(0)
/* Private functions, not part of the publicly documented API */
H5_DLL herr_t H5_init_library(void);
@@ -1409,6 +1920,7 @@ H5_DLL uint32_t H5_checksum_fletcher32(const void *data, size_t len);
H5_DLL uint32_t H5_checksum_crc(const void *data, size_t len);
H5_DLL uint32_t H5_checksum_lookup3(const void *data, size_t len, uint32_t initval);
H5_DLL uint32_t H5_checksum_metadata(const void *data, size_t len, uint32_t initval);
+H5_DLL uint32_t H5_hash_string(const char *str);
/* Functions for debugging */
H5_DLL herr_t H5_buffer_dump(FILE *stream, int indent, uint8_t *buf,
diff --git a/src/H5public.h b/src/H5public.h
index 608e52c..65dd29c 100644
--- a/src/H5public.h
+++ b/src/H5public.h
@@ -70,11 +70,11 @@ extern "C" {
/* Version numbers */
#define H5_VERS_MAJOR 1 /* For major interface/format changes */
-#define H5_VERS_MINOR 8 /* For minor interface/format changes */
-#define H5_VERS_RELEASE 0 /* For tweaks, bug-fixes, or development */
-#define H5_VERS_SUBRELEASE "beta4post1" /* For pre-releases like snap0 */
+#define H5_VERS_MINOR 9 /* For minor interface/format changes */
+#define H5_VERS_RELEASE 26 /* For tweaks, bug-fixes, or development */
+#define H5_VERS_SUBRELEASE "" /* For pre-releases like snap0 */
/* Empty string for real releases. */
-#define H5_VERS_INFO "HDF5 library version: 1.8.0-beta4post1" /* Full version string */
+#define H5_VERS_INFO "HDF5 library version: 1.9.26" /* Full version string */
#define H5check() H5check_version(H5_VERS_MAJOR,H5_VERS_MINOR, \
H5_VERS_RELEASE)
diff --git a/src/H5system.c b/src/H5system.c
index 5eae11d..8f91e2f 100644
--- a/src/H5system.c
+++ b/src/H5system.c
@@ -35,6 +35,8 @@
#include "H5private.h" /* Generic Functions */
#include "H5Fprivate.h" /* File access */
#include "H5MMprivate.h" /* Memory management */
+#include "H5Eprivate.h"
+
/****************/
@@ -495,7 +497,7 @@ HDstrtoll(const char *s, const char **rest, int base)
if (sign>0) {
acc = ((uint64_t)1<<(8*sizeof(int64_t)-1))-1;
} else {
- acc = (uint64_t)1<<(8*sizeof(int64_t)-1);
+ acc = (int64_t)((uint64_t)1<<(8*sizeof(int64_t)-1));
}
errno = ERANGE;
}
@@ -578,4 +580,103 @@ HDremove_all(const char *fname)
}
#endif
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * Function: H5_build_extpath
+ *
+ * Purpose: To build the path for later searching of target file for external link.
+ * This path can be either:
+ * 1. The absolute path of NAME
+ * or
+ * 2. The current working directory + relative path of NAME
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Vailin Choi
+ * April 2, 2008
+ * Modifications: 2nd Oct, 2008; Vailin Choi
+ * Remove compiler warning for "if condition"
+ *
+ *-------------------------------------------------------------------------
+ */
+#define MAX_PATH_LEN 1024
+
+herr_t
+H5_build_extpath(const char *name, char **extpath/*out*/)
+{
+ char *full_path=NULL, *ptr=NULL;
+ char *retcwd=NULL, *cwdpath=NULL, *new_name=NULL;
+ int drive;
+ size_t cwdlen, path_len;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5_build_extpath)
+
+ *extpath = NULL;
+
+ /*
+ * Unix: name[0] is a "/"
+ * Windows: name[0-2] is "<drive letter>:\" or "<drive-letter>:/"
+ */
+ if (CHECK_ABSOLUTE(name)) {
+ if ((full_path=H5MM_strdup(name)) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ } else { /* relative pathname */
+ if (NULL == (cwdpath = (char *)H5MM_malloc(MAX_PATH_LEN)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ if (NULL == (new_name = (char *)H5MM_strdup(name)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /*
+ * Windows: name[0-1] is "<drive-letter>:"
+ * Get current working directory on the drive specified in NAME
+ * Unix: does not apply
+ */
+ if (CHECK_ABS_DRIVE(name)) {
+ drive = name[0] - 'A' + 1;
+ retcwd = HDgetdcwd(drive, cwdpath, MAX_PATH_LEN);
+ HDstrcpy(new_name, &name[2]);
+ /*
+ * Windows: name[0] is a '/' or '\'
+ * Get current drive
+ * Unix: does not apply
+ */
+ } else if (CHECK_ABS_PATH(name) && ((drive=HDgetdrive()) != 0)) {
+ sprintf(cwdpath, "%c:%c", (drive+'A'-1), name[0]);
+ retcwd = cwdpath;
+ HDstrcpy(new_name, &name[1]);
+ } else /* totally relative for both Unix and Windows: get current working directory */
+ retcwd = HDgetcwd(cwdpath, MAX_PATH_LEN);
+
+ if (retcwd != NULL) {
+ cwdlen = HDstrlen(cwdpath);
+ HDassert(cwdlen);
+ path_len = cwdlen + HDstrlen(new_name) + 2;
+ if (NULL == (full_path = (char *)H5MM_malloc(path_len)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ HDstrcpy(full_path, cwdpath);
+ if (!CHECK_DELIMITER(cwdpath[cwdlen-1]))
+ HDstrcat(full_path, DIR_SEPS);
+ HDstrcat(full_path, new_name);
+ }
+ }
+
+ /* strip out the last component (the file name itself) from the path */
+ if (full_path) {
+ GET_LAST_DELIMITER(full_path, ptr)
+ HDassert(ptr);
+ *++ptr = '\0';
+ *extpath = full_path;
+ }
+done:
+ if (cwdpath)
+ H5MM_xfree(cwdpath);
+ if (new_name)
+ H5MM_xfree(new_name);
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5_build_extpath() */
diff --git a/src/H5trace.c b/src/H5trace.c
index 0ad99b2..4a42f0b 100644
--- a/src/H5trace.c
+++ b/src/H5trace.c
@@ -319,6 +319,9 @@ H5_trace (const double *returning, const char *func, const char *type, ...)
case H5D_ALLOC_TIME_INCR:
fprintf (out, "H5D_ALLOC_TIME_INCR");
break;
+ default:
+ fprintf (out, "%ld", (long)alloc_time);
+ break;
}
}
break;
@@ -368,6 +371,9 @@ H5_trace (const double *returning, const char *func, const char *type, ...)
case H5D_FILL_TIME_IFSET:
fprintf (out, "H5D_FILL_TIME_IFSET");
break;
+ default:
+ fprintf (out, "%ld", (long)fill_time);
+ break;
}
}
break;
@@ -394,6 +400,9 @@ H5_trace (const double *returning, const char *func, const char *type, ...)
case H5D_FILL_VALUE_USER_DEFINED:
fprintf (out, "H5D_FILL_VALUE_USER_DEFINED");
break;
+ default:
+ fprintf (out, "%ld", (long)fill_value);
+ break;
}
}
break;
@@ -619,6 +628,9 @@ H5_trace (const double *returning, const char *func, const char *type, ...)
case H5F_CLOSE_STRONG:
fprintf(out, "H5F_CLOSE_STRONG");
break;
+ default:
+ fprintf(out, "%ld", (long)degree);
+ break;
}
}
break;
@@ -643,6 +655,32 @@ H5_trace (const double *returning, const char *func, const char *type, ...)
fprintf(out, "H5F_SCOPE_DOWN "
"/*FOR INTERNAL USE ONLY!*/");
break;
+ default:
+ fprintf(out, "%ld", (long)scope);
+ break;
+ }
+ }
+ break;
+
+ case 'v':
+ if(ptr) {
+ if(vp)
+ fprintf(out, "0x%lx", (unsigned long)vp);
+ else
+ fprintf(out, "NULL");
+ } else {
+ H5F_libver_t libver_vers = va_arg(ap, H5F_libver_t); /*lint !e64 Type mismatch not really occuring */
+
+ switch(libver_vers) {
+ case H5F_LIBVER_EARLIEST:
+ fprintf(out, "H5F_LIBVER_EARLIEST");
+ break;
+ case H5F_LIBVER_LATEST:
+ fprintf(out, "H5F_LIBVER_LATEST");
+ break;
+ default:
+ fprintf(out, "%ld", (long)libver_vers);
+ break;
}
}
break;
@@ -908,7 +946,7 @@ H5_trace (const double *returning, const char *func, const char *type, ...)
/* Save the rank of simple data spaces for arrays */
/* This may generate recursive call to the library... -QAK */
{
- H5S_t *space = H5I_object(obj);
+ H5S_t *space = (H5S_t *)H5I_object(obj);
if (H5S_SIMPLE==H5S_GET_EXTENT_TYPE(space)) {
asize[argno] = H5S_GET_EXTENT_NDIMS(space);
}
@@ -977,6 +1015,9 @@ H5_trace (const double *returning, const char *func, const char *type, ...)
case H5_INDEX_N:
fprintf(out, "H5_INDEX_N");
break;
+ default:
+ fprintf(out, "%ld", (long)idx_type);
+ break;
} /* end switch */
} /* end else */
break;
@@ -1006,6 +1047,9 @@ H5_trace (const double *returning, const char *func, const char *type, ...)
case H5_ITER_N:
fprintf(out, "H5_ITER_N");
break;
+ default:
+ fprintf(out, "%ld", (long)order);
+ break;
} /* end switch */
} /* end else */
break;
@@ -1149,6 +1193,12 @@ H5_trace (const double *returning, const char *func, const char *type, ...)
case H5L_TYPE_SOFT:
fprintf(out, "H5L_TYPE_SOFT");
break;
+ case H5L_TYPE_EXTERNAL:
+ fprintf(out, "H5L_TYPE_EXTERNAL");
+ break;
+ case H5L_TYPE_MAX:
+ fprintf(out, "H5L_TYPE_MAX");
+ break;
default:
fprintf(out, "%ld", (long)link_type);
break;
@@ -1266,6 +1316,9 @@ H5_trace (const double *returning, const char *func, const char *type, ...)
else {
H5O_type_t objtype = va_arg(ap, H5O_type_t); /*lint !e64 Type mismatch not really occuring */
switch(objtype) {
+ case H5O_TYPE_UNKNOWN:
+ fprintf(out, "H5O_TYPE_UNKNOWN");
+ break;
case H5O_TYPE_GROUP:
fprintf(out, "H5O_TYPE_GROUP");
break;
@@ -1275,6 +1328,9 @@ H5_trace (const double *returning, const char *func, const char *type, ...)
case H5O_TYPE_NAMED_DATATYPE:
fprintf(out, "H5O_TYPE_NAMED_DATATYPE");
break;
+ case H5O_TYPE_NTYPES:
+ fprintf(out, "H5O_TYPE_TYPES");
+ break;
default:
fprintf(out, "BADTYPE(%ld)", (long)objtype);
break;
@@ -1297,13 +1353,13 @@ H5_trace (const double *returning, const char *func, const char *type, ...)
}
} else {
hid_t pclass_id = va_arg (ap, hid_t);
- char *class_name=NULL;
+ char *class_name = NULL;
H5P_genclass_t *pclass;
/* Get the class name and print it */
/* This may generate recursive call to the library... -QAK */
- if(NULL != (pclass = H5I_object(pclass_id)) &&
- (class_name=H5P_get_class_name(pclass))!=NULL) {
+ if(NULL != (pclass = (H5P_genclass_t *)H5I_object(pclass_id)) &&
+ (class_name = H5P_get_class_name(pclass))!=NULL) {
fprintf (out, class_name);
H5MM_xfree(class_name);
} /* end if */
diff --git a/src/H5version.h b/src/H5version.h
index eab972c..fd9e780 100644
--- a/src/H5version.h
+++ b/src/H5version.h
@@ -32,6 +32,10 @@
* Note: If an application has already chosen a particular version for an
* API symbol, the individual API version macro takes priority.
*/
+#if defined(H5_USE_16_API_DEFAULT) && !defined(H5_USE_16_API)
+#define H5_USE_16_API 1
+#endif /* H5_USE_16_API_DEFAULT && !H5_USE_16_API */
+
#ifdef H5_USE_16_API
/*************/
diff --git a/src/H5win32defs.h b/src/H5win32defs.h
new file mode 100644
index 0000000..41e2edd
--- /dev/null
+++ b/src/H5win32defs.h
@@ -0,0 +1,69 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/* Programmer: Scott Wegner
+ * June 3, 2008
+ *
+ * Purpose: This file is used to map HDF macros to Windows functions. This
+ * should get included H5private mappings, so as to override them.
+ * Any macro not mapped here, however, will receive a similar mapping
+ * inside H5private.h
+ *
+ */
+
+#ifdef _WIN32
+
+typedef struct _stati64 h5_stat_t;
+typedef __int64 h5_stat_size_t;
+
+#define HDaccess(F,M) _access(F,M)
+#define HDclose(F) _close(F)
+#define HDdup(F) _dup(F)
+#define HDfdopen(N,S) _fdopen(N,S)
+#define HDfileno(F) _fileno(F)
+
+#if _MSC_VER > 1200
+#define HDftruncate(F,L) _chsize_s(F,L)
+#else
+#define HDftruncate(F,L) chsize(F,L)
+#endif
+
+#define HDfstat(F,B) _fstati64(F,B)
+#define HDisatty(F) _isatty(F)
+#define HDstat(S,B) _stati64(S,B)
+#define HDgetcwd(S,Z) _getcwd(S,Z)
+#define HDgetdcwd(D,S,Z) _getdcwd(D,S,Z)
+#define HDgetdrive() _getdrive()
+#define HDlseek(F,O,W) _lseeki64(F,O,W)
+#define HDmemset(X,C,Z) memset((void*)(X),C,Z)
+#define HDmkdir(S,M) _mkdir(S)
+#define HDopen(S,F,M) _open(S,F|_O_BINARY,M)
+#define HDread(F,M,Z) _read(F,M,Z)
+#define HDsetvbuf(F,S,M,Z) setvbuf(F,S,M,(Z>1?Z:2))
+#define HDstrdup(S) _strdup(S)
+#define HDsnprintf _snprintf /*varargs*/
+#define HDtzset() _tzset()
+#define HDunlink(S) _unlink(S)
+#define HDvsnprintf(S,N,FMT,A) _vsnprintf(S,N,FMT,A)
+#define HDwrite(F,M,Z) _write(F,M,Z)
+
+/* Non-POSIX functions */
+
+/* Don't use actual pthread_self on Windows because the return
+ * type cannot be cast as a ulong like other systems. */
+#define HDpthread_self_ulong() ((unsigned long)GetCurrentThreadId())
+
+
+#endif /* _WIN32 */
diff --git a/src/Makefile.am b/src/Makefile.am
index fa64fe6..9ae2252 100755
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -43,28 +43,35 @@ DISTCLEANFILES=H5pubconf.h
# library sources
libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
H5A.c H5Abtree2.c H5Adense.c H5Adeprec.c H5Aint.c H5Atest.c \
- H5AC.c H5B.c H5Bcache.c \
+ H5AC.c H5B.c H5Bcache.c H5Bdbg.c \
H5B2.c H5B2cache.c H5B2dbg.c H5B2int.c H5B2stat.c H5B2test.c \
H5C.c H5CS.c \
- H5D.c H5Dcompact.c H5Dcontig.c H5Ddbg.c \
+ H5D.c H5Dbtree.c H5Dchunk.c H5Dcompact.c H5Dcontig.c H5Ddbg.c \
H5Ddeprec.c H5Defl.c H5Dfill.c H5Dint.c \
H5Dio.c \
- H5Distore.c H5Dmpio.c H5Doh.c H5Dselect.c H5Dtest.c \
+ H5Dmpio.c H5Doh.c H5Dscatgath.c H5Dselect.c H5Dtest.c \
H5E.c H5Edeprec.c H5Eint.c \
- H5F.c H5Fdbg.c H5Ffake.c H5Fmount.c H5Fsfile.c H5Fsuper.c H5Ftest.c \
+ H5EA.c H5EAcache.c H5EAdbg.c H5EAdblkpage.c H5EAdblock.c H5EAhdr.c \
+ H5EAiblock.c H5EAint.c H5EAsblock.c H5EAstat.c H5EAtest.c \
+ H5F.c H5Faccum.c H5Fdbg.c H5Ffake.c H5Fio.c H5Fmount.c H5Fmpi.c H5Fquery.c \
+ H5Fsfile.c H5Fsuper.c H5Ftest.c \
H5FD.c H5FDcore.c \
- H5FDdirect.c H5FDfamily.c H5FDlog.c H5FDmpi.c H5FDmpio.c \
- H5FDmpiposix.c H5FDmulti.c H5FDsec2.c H5FDstdio.c \
- H5FDstream.c H5FL.c H5FO.c H5FS.c H5FScache.c H5FSdbg.c H5FSsection.c \
- H5G.c H5Gbtree2.c H5Gcompact.c H5Gdense.c H5Gdeprec.c H5Gent.c \
+ H5FDdirect.c H5FDfamily.c H5FDint.c H5FDlog.c H5FDmpi.c H5FDmpio.c \
+ H5FDmpiposix.c H5FDmulti.c H5FDsec2.c H5FDspace.c H5FDstdio.c \
+ H5FL.c H5FO.c H5FS.c H5FScache.c H5FSdbg.c H5FSsection.c H5FSstat.c H5FStest.c \
+ H5G.c H5Gbtree2.c H5Gcache.c \
+ H5Gcompact.c H5Gdense.c H5Gdeprec.c H5Gent.c \
H5Gint.c H5Glink.c \
H5Gloc.c H5Gname.c H5Gnode.c H5Gobj.c H5Goh.c H5Gstab.c H5Gtest.c \
H5Gtraverse.c \
H5HF.c H5HFbtree2.c H5HFcache.c H5HFdbg.c H5HFdblock.c H5HFdtable.c \
H5HFhdr.c H5HFhuge.c H5HFiblock.c H5HFiter.c H5HFman.c H5HFsection.c \
H5HFspace.c H5HFstat.c H5HFtest.c H5HFtiny.c \
- H5HG.c H5HGdbg.c H5HL.c H5HLdbg.c H5HP.c H5I.c H5L.c H5Lexternal.c \
- H5MF.c H5MM.c H5MP.c H5MPtest.c \
+ H5HG.c H5HGcache.c H5HGdbg.c \
+ H5HL.c H5HLcache.c H5HLdbg.c \
+ H5HP.c H5I.c H5L.c H5Lexternal.c \
+ H5MF.c H5MFaggr.c H5MFdbg.c H5MFsection.c \
+ H5MM.c H5MP.c H5MPtest.c \
H5O.c H5Oainfo.c H5Oalloc.c H5Oattr.c \
H5Oattribute.c H5Obogus.c H5Obtreek.c H5Ocache.c \
H5Ocont.c H5Ocopy.c H5Odbg.c H5Odrvinfo.c H5Odtype.c H5Oefl.c \
@@ -74,7 +81,7 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
H5Oname.c H5Onull.c H5Opline.c H5Orefcount.c \
H5Osdspace.c H5Oshared.c H5Ostab.c \
H5Oshmesg.c H5Otest.c H5Ounknown.c \
- H5P.c H5Pacpl.c H5Pdcpl.c \
+ H5P.c H5Pacpl.c H5Pdapl.c H5Pdcpl.c \
H5Pdeprec.c H5Pdxpl.c H5Pfapl.c H5Pfcpl.c H5Pfmpl.c \
H5Pgcpl.c H5Pint.c \
H5Plapl.c H5Plcpl.c H5Pocpl.c H5Pocpypl.c H5Pstrcpl.c H5Ptest.c \
@@ -101,7 +108,7 @@ include_HEADERS = hdf5.h H5api_adpt.h H5pubconf.h H5public.h H5version.h \
H5Cpublic.h H5Dpublic.h \
H5Epubgen.h H5Epublic.h H5Fpublic.h H5FDpublic.h H5FDcore.h H5FDdirect.h \
H5FDfamily.h H5FDlog.h H5FDmpi.h H5FDmpio.h H5FDmpiposix.h \
- H5FDmulti.h H5FDsec2.h H5FDstdio.h H5FDstream.h \
+ H5FDmulti.h H5FDsec2.h H5FDstdio.h \
H5Gpublic.h H5Ipublic.h H5Lpublic.h \
H5MMpublic.h H5Opublic.h H5Ppublic.h H5Rpublic.h H5Spublic.h \
H5Tpublic.h H5Zpublic.h
diff --git a/src/Makefile.in b/src/Makefile.in
index 8bea6bb..4fde49e 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -1,8 +1,8 @@
-# Makefile.in generated by automake 1.10 from Makefile.am.
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -80,46 +80,51 @@ LTLIBRARIES = $(lib_LTLIBRARIES)
libhdf5_la_LIBADD =
am_libhdf5_la_OBJECTS = H5.lo H5checksum.lo H5dbg.lo H5system.lo \
H5timer.lo H5trace.lo H5A.lo H5Abtree2.lo H5Adense.lo \
- H5Adeprec.lo H5Aint.lo H5Atest.lo H5AC.lo H5B.lo H5Bcache.lo \
+ H5Adeprec.lo H5Aint.lo H5Atest.lo H5AC.lo H5B.lo H5Bcache.lo H5Bdbg.lo \
H5B2.lo H5B2cache.lo H5B2dbg.lo H5B2int.lo H5B2stat.lo \
- H5B2test.lo H5C.lo H5CS.lo H5D.lo H5Dcompact.lo H5Dcontig.lo \
- H5Ddbg.lo H5Ddeprec.lo H5Defl.lo H5Dfill.lo H5Dint.lo H5Dio.lo \
- H5Distore.lo H5Dmpio.lo H5Doh.lo H5Dselect.lo H5Dtest.lo \
- H5E.lo H5Edeprec.lo H5Eint.lo H5F.lo H5Fdbg.lo H5Ffake.lo \
- H5Fmount.lo H5Fsfile.lo H5Fsuper.lo H5Ftest.lo H5FD.lo \
- H5FDcore.lo H5FDdirect.lo H5FDfamily.lo H5FDlog.lo H5FDmpi.lo \
- H5FDmpio.lo H5FDmpiposix.lo H5FDmulti.lo H5FDsec2.lo \
- H5FDstdio.lo H5FDstream.lo H5FL.lo H5FO.lo H5FS.lo \
- H5FScache.lo H5FSdbg.lo H5FSsection.lo H5G.lo H5Gbtree2.lo \
- H5Gcompact.lo H5Gdense.lo H5Gdeprec.lo H5Gent.lo H5Gint.lo \
- H5Glink.lo H5Gloc.lo H5Gname.lo H5Gnode.lo H5Gobj.lo H5Goh.lo \
- H5Gstab.lo H5Gtest.lo H5Gtraverse.lo H5HF.lo H5HFbtree2.lo \
- H5HFcache.lo H5HFdbg.lo H5HFdblock.lo H5HFdtable.lo H5HFhdr.lo \
- H5HFhuge.lo H5HFiblock.lo H5HFiter.lo H5HFman.lo \
- H5HFsection.lo H5HFspace.lo H5HFstat.lo H5HFtest.lo \
- H5HFtiny.lo H5HG.lo H5HGdbg.lo H5HL.lo H5HLdbg.lo H5HP.lo \
- H5I.lo H5L.lo H5Lexternal.lo H5MF.lo H5MM.lo H5MP.lo \
- H5MPtest.lo H5O.lo H5Oainfo.lo H5Oalloc.lo H5Oattr.lo \
- H5Oattribute.lo H5Obogus.lo H5Obtreek.lo H5Ocache.lo \
- H5Ocont.lo H5Ocopy.lo H5Odbg.lo H5Odrvinfo.lo H5Odtype.lo \
- H5Oefl.lo H5Ofill.lo H5Oginfo.lo H5Olayout.lo H5Olinfo.lo \
- H5Olink.lo H5Omessage.lo H5Omtime.lo H5Oname.lo H5Onull.lo \
- H5Opline.lo H5Orefcount.lo H5Osdspace.lo H5Oshared.lo \
- H5Ostab.lo H5Oshmesg.lo H5Otest.lo H5Ounknown.lo H5P.lo \
- H5Pacpl.lo H5Pdcpl.lo H5Pdeprec.lo H5Pdxpl.lo H5Pfapl.lo \
- H5Pfcpl.lo H5Pfmpl.lo H5Pgcpl.lo H5Pint.lo H5Plapl.lo \
- H5Plcpl.lo H5Pocpl.lo H5Pocpypl.lo H5Pstrcpl.lo H5Ptest.lo \
- H5R.lo H5Rdeprec.lo H5RC.lo H5RS.lo H5S.lo H5Sall.lo H5Sdbg.lo \
- H5Shyper.lo H5Smpio.lo H5Snone.lo H5Spoint.lo H5Sselect.lo \
- H5Stest.lo H5SL.lo H5SM.lo H5SMbtree2.lo H5SMcache.lo \
- H5SMtest.lo H5ST.lo H5T.lo H5Tarray.lo H5Tbit.lo H5Tcommit.lo \
- H5Tcompound.lo H5Tconv.lo H5Tcset.lo H5Tdbg.lo H5Tdeprec.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 H5Tvisit.lo H5Tvlen.lo \
- H5TS.lo H5V.lo H5WB.lo H5Z.lo H5Zdeflate.lo H5Zfletcher32.lo \
- H5Znbit.lo H5Zshuffle.lo H5Zszip.lo H5Zscaleoffset.lo \
- H5Ztrans.lo
+ H5B2test.lo H5C.lo H5CS.lo H5D.lo H5Dchunk.lo H5Dcompact.lo \
+ H5Dcontig.lo H5Ddbg.lo H5Ddeprec.lo H5Defl.lo H5Dfill.lo \
+ H5Dint.lo H5Dio.lo H5Dbtree.lo H5Dmpio.lo H5Doh.lo \
+ H5Dscatgath.lo H5Dselect.lo H5Dtest.lo H5E.lo H5Edeprec.lo \
+ H5Eint.lo H5EA.lo H5EAcache.lo H5EAdbg.lo H5EAdblkpage.lo \
+ H5EAdblock.lo H5EAhdr.lo H5EAiblock.lo H5EAint.lo \
+ H5EAsblock.lo H5EAstat.lo H5EAtest.lo H5F.lo H5Faccum.lo \
+ H5Fdbg.lo H5Ffake.lo H5Fio.lo H5Fmount.lo H5Fmpi.lo \
+ H5Fquery.lo H5Fsfile.lo H5Fsuper.lo H5Ftest.lo H5FD.lo \
+ H5FDcore.lo H5FDdirect.lo H5FDfamily.lo H5FDint.lo H5FDlog.lo \
+ H5FDmpi.lo H5FDmpio.lo H5FDmpiposix.lo H5FDmulti.lo \
+ H5FDsec2.lo H5FDspace.lo H5FDstdio.lo H5FL.lo H5FO.lo H5FS.lo \
+ H5FScache.lo H5FSdbg.lo H5FSsection.lo H5FSstat.lo H5FStest.lo \
+ H5G.lo H5Gbtree2.lo H5Gcache.lo H5Gcompact.lo H5Gdense.lo \
+ H5Gdeprec.lo H5Gent.lo H5Gint.lo H5Glink.lo H5Gloc.lo \
+ H5Gname.lo H5Gnode.lo H5Gobj.lo H5Goh.lo H5Gstab.lo H5Gtest.lo \
+ H5Gtraverse.lo H5HF.lo H5HFbtree2.lo H5HFcache.lo H5HFdbg.lo \
+ H5HFdblock.lo H5HFdtable.lo H5HFhdr.lo H5HFhuge.lo \
+ H5HFiblock.lo H5HFiter.lo H5HFman.lo H5HFsection.lo \
+ H5HFspace.lo H5HFstat.lo H5HFtest.lo H5HFtiny.lo H5HG.lo \
+ H5HGcache.lo H5HGdbg.lo H5HL.lo H5HLcache.lo H5HLdbg.lo \
+ H5HP.lo H5I.lo H5L.lo H5Lexternal.lo H5MF.lo H5MFaggr.lo \
+ H5MFdbg.lo H5MFsection.lo H5MM.lo H5MP.lo H5MPtest.lo H5O.lo \
+ H5Oainfo.lo H5Oalloc.lo H5Oattr.lo H5Oattribute.lo H5Obogus.lo \
+ H5Obtreek.lo H5Ocache.lo H5Ocont.lo H5Ocopy.lo H5Odbg.lo \
+ H5Odrvinfo.lo H5Odtype.lo H5Oefl.lo H5Ofill.lo H5Oginfo.lo \
+ H5Olayout.lo H5Olinfo.lo H5Olink.lo H5Omessage.lo H5Omtime.lo \
+ H5Oname.lo H5Onull.lo H5Opline.lo H5Orefcount.lo H5Osdspace.lo \
+ H5Oshared.lo H5Ostab.lo H5Oshmesg.lo H5Otest.lo H5Ounknown.lo \
+ H5P.lo H5Pacpl.lo H5Pdapl.lo H5Pdcpl.lo H5Pdeprec.lo \
+ H5Pdxpl.lo H5Pfapl.lo H5Pfcpl.lo H5Pfmpl.lo H5Pgcpl.lo \
+ H5Pint.lo H5Plapl.lo H5Plcpl.lo H5Pocpl.lo H5Pocpypl.lo \
+ H5Pstrcpl.lo H5Ptest.lo H5R.lo H5Rdeprec.lo H5RC.lo H5RS.lo \
+ H5S.lo H5Sall.lo H5Sdbg.lo H5Shyper.lo H5Smpio.lo H5Snone.lo \
+ H5Spoint.lo H5Sselect.lo H5Stest.lo H5SL.lo H5SM.lo \
+ H5SMbtree2.lo H5SMcache.lo H5SMtest.lo H5ST.lo H5T.lo \
+ H5Tarray.lo H5Tbit.lo H5Tcommit.lo H5Tcompound.lo H5Tconv.lo \
+ H5Tcset.lo H5Tdbg.lo H5Tdeprec.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 H5Tvisit.lo H5Tvlen.lo H5TS.lo H5V.lo H5WB.lo \
+ H5Z.lo H5Zdeflate.lo H5Zfletcher32.lo H5Znbit.lo H5Zshuffle.lo \
+ H5Zszip.lo H5Zscaleoffset.lo H5Ztrans.lo
libhdf5_la_OBJECTS = $(am_libhdf5_la_OBJECTS)
libhdf5_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
@@ -173,6 +178,7 @@ CC_VERSION = @CC_VERSION@
# but which shouldn't be exported to h5cc for building other programs.
CFLAGS = @CFLAGS@ @H5_CFLAGS@
CLEARFILEBUF = @CLEARFILEBUF@
+CODESTACK = @CODESTACK@
CONFIG_DATE = @CONFIG_DATE@
CONFIG_MODE = @CONFIG_MODE@
CONFIG_USER = @CONFIG_USER@
@@ -188,14 +194,16 @@ DEFAULT_API_VERSION = @DEFAULT_API_VERSION@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DEPRECATED_SYMBOLS = @DEPRECATED_SYMBOLS@
+DIRECT_VFD = @DIRECT_VFD@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
DYNAMIC_DIRS = @DYNAMIC_DIRS@
-ECHO = @ECHO@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
-F77 = @F77@
+EXTERNAL_FILTERS = @EXTERNAL_FILTERS@
# Make sure that these variables are exported to the Makefiles
F9XMODEXT = @F9XMODEXT@
@@ -205,9 +213,10 @@ FC = @FC@
FCFLAGS = @FCFLAGS@ @H5_FCFLAGS@
FCFLAGS_f90 = @FCFLAGS_f90@
FCLIBS = @FCLIBS@
-FFLAGS = @FFLAGS@
+FGREP = @FGREP@
FILTERS = @FILTERS@
FSEARCH_DIRS = @FSEARCH_DIRS@
+GPFS = @GPFS@
GREP = @GREP@
H5_CFLAGS = @H5_CFLAGS@
H5_CPPFLAGS = @H5_CPPFLAGS@
@@ -216,11 +225,14 @@ H5_FCFLAGS = @H5_FCFLAGS@
H5_LONE_COLON = @H5_LONE_COLON@
H5_VERSION = @H5_VERSION@
HADDR_T = @HADDR_T@
+HAVE_DMALLOC = @HAVE_DMALLOC@
+HDF5_HL = @HDF5_HL@
HDF5_INTERFACES = @HDF5_INTERFACES@
+HDF_CXX = @HDF_CXX@
+HDF_FORTRAN = @HDF_FORTRAN@
HID_T = @HID_T@
HL = @HL@
HL_FOR = @HL_FOR@
-HSIZET = @HSIZET@
HSIZE_T = @HSIZE_T@
HSSIZE_T = @HSSIZE_T@
INSTALL = @INSTALL@
@@ -228,11 +240,16 @@ INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTRUMENT = @INSTRUMENT@
INSTRUMENT_LIBRARY = @INSTRUMENT_LIBRARY@
+LD = @LD@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
+LINUX_LFS = @LINUX_LFS@
+LIPO = @LIPO@
+LL_PATH = @LL_PATH@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
LT_STATIC_EXEC = @LT_STATIC_EXEC@
@@ -241,8 +258,13 @@ MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
MPE = @MPE@
MPI_GET_SIZE = @MPI_GET_SIZE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
OBJECT_NAMELEN_DEFAULT_F = @OBJECT_NAMELEN_DEFAULT_F@
OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
@@ -260,21 +282,21 @@ RUNSERIAL = @RUNSERIAL@
R_INTEGER = @R_INTEGER@
R_LARGE = @R_LARGE@
SEARCH = @SEARCH@
+SED = @SED@
SETX = @SETX@
SET_MAKE = @SET_MAKE@
-
-# Hardcode SHELL to be /bin/sh. Most machines have this shell, and
-# on at least one machine configure fails to detect its existence (janus).
-# Also, when HDF5 is configured on one machine but run on another,
-# configure's automatic SHELL detection may not work on the build machine.
-SHELL = /bin/sh
+SHELL = @SHELL@
SIZE_T = @SIZE_T@
+STATIC_EXEC = @STATIC_EXEC@
STATIC_SHARED = @STATIC_SHARED@
+STRICT_FORMAT_CHECKS = @STRICT_FORMAT_CHECKS@
STRIP = @STRIP@
TESTPARALLEL = @TESTPARALLEL@
+THREADSAFE = @THREADSAFE@
TIME = @TIME@
TR = @TR@
TRACE_API = @TRACE_API@
+UNAME_INFO = @UNAME_INFO@
USE_FILTER_DEFLATE = @USE_FILTER_DEFLATE@
USE_FILTER_FLETCHER32 = @USE_FILTER_FLETCHER32@
USE_FILTER_NBIT = @USE_FILTER_NBIT@
@@ -289,7 +311,7 @@ abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
-ac_ct_F77 = @ac_ct_F77@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
ac_ct_FC = @ac_ct_FC@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
@@ -307,6 +329,8 @@ datadir = @datadir@
datarootdir = @datarootdir@
docdir = $(exec_prefix)/doc
dvidir = @dvidir@
+enable_shared = @enable_shared@
+enable_static = @enable_static@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
@@ -323,6 +347,7 @@ libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
@@ -382,9 +407,9 @@ CHECK_CLEANFILES = *.chkexe *.chklog *.clog
# Add libtool shared library version numbers to the HDF5 library
# See libtool versioning documentation online.
-LT_VERS_INTERFACE = 4
-LT_VERS_REVISION = 4
-LT_VERS_AGE = 3
+LT_VERS_INTERFACE = 6
+LT_VERS_REVISION = 16
+LT_VERS_AGE = 0
H5detect_CFLAGS = -g
# Our main target, the HDF5 library
@@ -401,28 +426,35 @@ DISTCLEANFILES = H5pubconf.h
# library sources
libhdf5_la_SOURCES = H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
H5A.c H5Abtree2.c H5Adense.c H5Adeprec.c H5Aint.c H5Atest.c \
- H5AC.c H5B.c H5Bcache.c \
+ H5AC.c H5B.c H5Bcache.c H5Bdbg.c \
H5B2.c H5B2cache.c H5B2dbg.c H5B2int.c H5B2stat.c H5B2test.c \
H5C.c H5CS.c \
- H5D.c H5Dcompact.c H5Dcontig.c H5Ddbg.c \
+ H5D.c H5Dchunk.c H5Dcompact.c H5Dcontig.c H5Ddbg.c \
H5Ddeprec.c H5Defl.c H5Dfill.c H5Dint.c \
H5Dio.c \
- H5Distore.c H5Dmpio.c H5Doh.c H5Dselect.c H5Dtest.c \
+ H5Dbtree.c H5Dmpio.c H5Doh.c H5Dscatgath.c H5Dselect.c H5Dtest.c \
H5E.c H5Edeprec.c H5Eint.c \
- H5F.c H5Fdbg.c H5Ffake.c H5Fmount.c H5Fsfile.c H5Fsuper.c H5Ftest.c \
+ H5EA.c H5EAcache.c H5EAdbg.c H5EAdblkpage.c H5EAdblock.c H5EAhdr.c \
+ H5EAiblock.c H5EAint.c H5EAsblock.c H5EAstat.c H5EAtest.c \
+ H5F.c H5Faccum.c H5Fdbg.c H5Ffake.c H5Fio.c H5Fmount.c H5Fmpi.c H5Fquery.c \
+ H5Fsfile.c H5Fsuper.c H5Ftest.c \
H5FD.c H5FDcore.c \
- H5FDdirect.c H5FDfamily.c H5FDlog.c H5FDmpi.c H5FDmpio.c \
- H5FDmpiposix.c H5FDmulti.c H5FDsec2.c H5FDstdio.c \
- H5FDstream.c H5FL.c H5FO.c H5FS.c H5FScache.c H5FSdbg.c H5FSsection.c \
- H5G.c H5Gbtree2.c H5Gcompact.c H5Gdense.c H5Gdeprec.c H5Gent.c \
+ H5FDdirect.c H5FDfamily.c H5FDint.c H5FDlog.c H5FDmpi.c H5FDmpio.c \
+ H5FDmpiposix.c H5FDmulti.c H5FDsec2.c H5FDspace.c H5FDstdio.c \
+ H5FL.c H5FO.c H5FS.c H5FScache.c H5FSdbg.c H5FSsection.c H5FSstat.c H5FStest.c \
+ H5G.c H5Gbtree2.c H5Gcache.c \
+ H5Gcompact.c H5Gdense.c H5Gdeprec.c H5Gent.c \
H5Gint.c H5Glink.c \
H5Gloc.c H5Gname.c H5Gnode.c H5Gobj.c H5Goh.c H5Gstab.c H5Gtest.c \
H5Gtraverse.c \
H5HF.c H5HFbtree2.c H5HFcache.c H5HFdbg.c H5HFdblock.c H5HFdtable.c \
H5HFhdr.c H5HFhuge.c H5HFiblock.c H5HFiter.c H5HFman.c H5HFsection.c \
H5HFspace.c H5HFstat.c H5HFtest.c H5HFtiny.c \
- H5HG.c H5HGdbg.c H5HL.c H5HLdbg.c H5HP.c H5I.c H5L.c H5Lexternal.c \
- H5MF.c H5MM.c H5MP.c H5MPtest.c \
+ H5HG.c H5HGcache.c H5HGdbg.c \
+ H5HL.c H5HLcache.c H5HLdbg.c \
+ H5HP.c H5I.c H5L.c H5Lexternal.c \
+ H5MF.c H5MFaggr.c H5MFdbg.c H5MFsection.c \
+ H5MM.c H5MP.c H5MPtest.c \
H5O.c H5Oainfo.c H5Oalloc.c H5Oattr.c \
H5Oattribute.c H5Obogus.c H5Obtreek.c H5Ocache.c \
H5Ocont.c H5Ocopy.c H5Odbg.c H5Odrvinfo.c H5Odtype.c H5Oefl.c \
@@ -432,7 +464,7 @@ libhdf5_la_SOURCES = H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
H5Oname.c H5Onull.c H5Opline.c H5Orefcount.c \
H5Osdspace.c H5Oshared.c H5Ostab.c \
H5Oshmesg.c H5Otest.c H5Ounknown.c \
- H5P.c H5Pacpl.c H5Pdcpl.c \
+ H5P.c H5Pacpl.c H5Pdapl.c H5Pdcpl.c \
H5Pdeprec.c H5Pdxpl.c H5Pfapl.c H5Pfcpl.c H5Pfmpl.c \
H5Pgcpl.c H5Pint.c \
H5Plapl.c H5Plcpl.c H5Pocpl.c H5Pocpypl.c H5Pstrcpl.c H5Ptest.c \
@@ -459,7 +491,7 @@ include_HEADERS = hdf5.h H5api_adpt.h H5pubconf.h H5public.h H5version.h \
H5Cpublic.h H5Dpublic.h \
H5Epubgen.h H5Epublic.h H5Fpublic.h H5FDpublic.h H5FDcore.h H5FDdirect.h \
H5FDfamily.h H5FDlog.h H5FDmpi.h H5FDmpio.h H5FDmpiposix.h \
- H5FDmulti.h H5FDsec2.h H5FDstdio.h H5FDstream.h \
+ H5FDmulti.h H5FDsec2.h H5FDstdio.h \
H5Gpublic.h H5Ipublic.h H5Lpublic.h \
H5MMpublic.h H5Opublic.h H5Ppublic.h H5Rpublic.h H5Spublic.h \
H5Tpublic.h H5Zpublic.h
@@ -543,8 +575,8 @@ install-libLTLIBRARIES: $(lib_LTLIBRARIES)
@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
if test -f $$p; then \
f=$(am__strip_dir) \
- echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
- $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
else :; fi; \
done
@@ -552,8 +584,8 @@ uninstall-libLTLIBRARIES:
@$(NORMAL_UNINSTALL)
@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
p=$(am__strip_dir) \
- echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
- $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
done
clean-libLTLIBRARIES:
@@ -599,9 +631,11 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5B2stat.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5B2test.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Bcache.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Bdbg.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5C.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5CS.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5D.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Dchunk.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Dcompact.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Dcontig.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Ddbg.Plo@am__quote@
@@ -610,12 +644,24 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Dfill.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Dint.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Dio.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Distore.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Dbtree.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Dmpio.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Doh.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Dscatgath.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Dselect.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Dtest.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5E.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5EA.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5EAcache.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5EAdbg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5EAdblkpage.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5EAdblock.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5EAhdr.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5EAiblock.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5EAint.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5EAsblock.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5EAstat.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5EAtest.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Edeprec.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Eint.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5F.Plo@am__quote@
@@ -623,28 +669,36 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDcore.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDdirect.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDfamily.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDint.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDlog.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDmpi.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDmpio.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDmpiposix.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDmulti.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDsec2.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDspace.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDstdio.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FDstream.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FL.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FO.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FS.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FScache.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FSdbg.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FSsection.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FSstat.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FStest.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Faccum.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fdbg.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Ffake.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fio.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fmount.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fmpi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fquery.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fsfile.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fsuper.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Ftest.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5G.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Gbtree2.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Gcache.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Gcompact.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Gdense.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Gdeprec.Plo@am__quote@
@@ -676,14 +730,19 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFtest.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFtiny.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HG.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HGcache.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HGdbg.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HL.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HLcache.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HLdbg.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HP.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5I.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5L.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Lexternal.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5MF.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5MFaggr.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5MFdbg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5MFsection.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5MM.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5MP.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5MPtest.Plo@am__quote@
@@ -720,6 +779,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Ounknown.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5P.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Pacpl.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Pdapl.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Pdcpl.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Pdeprec.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Pdxpl.Plo@am__quote@
@@ -875,8 +935,8 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
- $(AWK) ' { files[$$0] = 1; } \
- END { for (i in files) print i; }'`; \
+ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS
@@ -888,8 +948,8 @@ TAGS: $(HEADERS) $(SOURCES) H5config.h.in $(TAGS_DEPENDENCIES) \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
- $(AWK) ' { files[$$0] = 1; } \
- END { for (i in files) print i; }'`; \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
@@ -899,13 +959,12 @@ ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) H5config.h.in $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
- here=`pwd`; \
list='$(SOURCES) $(HEADERS) H5config.h.in $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
- $(AWK) ' { files[$$0] = 1; } \
- END { for (i in files) print i; }'`; \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$tags $$unique
@@ -1213,10 +1272,10 @@ $(TEST_PROG_CHKEXE) $(TEST_PROG_PARA_CHKEXE) dummy.chkexe_:
echo "No need to test $${tname} again."; \
else \
echo "============================" > $${log}; \
- if test "X$(HDF_FORTRAN)" = "Xyes"; then \
+ if test "X$(FORTRAN_API)" = "Xyes"; then \
echo "Fortran API: Testing $(HDF5_DRIVER) $${tname} $(TEST_FLAGS)"; \
echo "Fortran API: $(HDF5_DRIVER) $${tname} $(TEST_FLAGS) Test Log" >> $${log}; \
- elif test "X$(HDF_CXX)" = "Xyes"; then \
+ elif test "X$(CXX_API)" = "Xyes"; then \
echo "C++ API: Testing $(HDF5_DRIVER) $${tname} $(TEST_FLAGS)"; \
echo "C++ API: $(HDF5_DRIVER) $${tname} $(TEST_FLAGS) Test Log" >> $${log};\
else \
@@ -1252,10 +1311,10 @@ $(TEST_SCRIPT_CHKSH) $(TEST_SCRIPT_PARA_CHKSH) dummysh.chkexe_:
echo "No need to test $${tname} again."; \
else \
echo "============================" > $${log}; \
- if test "X$(HDF_FORTRAN)" = "Xyes"; then \
+ if test "X$(FORTRAN_API)" = "Xyes"; then \
echo "Fortran API: Testing $${tname} $(TEST_FLAGS)"; \
echo "Fortran API: $${tname} $(TEST_FLAGS) Test Log" >> $${log}; \
- elif test "X$(HDF_CXX)" = "Xyes"; then \
+ elif test "X$(CXX_API)" = "Xyes"; then \
echo "C++ API: Testing $${tname} $(TEST_FLAGS)"; \
echo "C++ API: $${tname} $(TEST_FLAGS) Test Log" >> $${log}; \
else \
diff --git a/src/hdf5.h b/src/hdf5.h
index 20f4cd9..ef15063 100644
--- a/src/hdf5.h
+++ b/src/hdf5.h
@@ -50,7 +50,6 @@
#ifdef H5_HAVE_WINDOWS
#include "H5FDwindows.h" /* Windows buffered I/O */
#endif
-#include "H5FDstream.h" /* In-memory files streamed via sockets */
#include "H5FDdirect.h" /* Linux direct I/O */
#endif
diff --git a/src/libhdf5.settings.in b/src/libhdf5.settings.in
index 7a59673..51406de 100644
--- a/src/libhdf5.settings.in
+++ b/src/libhdf5.settings.in
@@ -1,20 +1,58 @@
-SUMMARY OF THE HDF5 CONFIGURATION
-=================================
+ SUMMARY OF THE HDF5 CONFIGURATION
+ =================================
-HDF5 Version: @H5_VERSION@
-Configured on: @CONFIG_DATE@
-Configured by: @CONFIG_USER@
-Configure mode: @CONFIG_MODE@
-Host system: @host_cpu@-@host_vendor@-@host_os@
-Byte sex: @BYTESEX@
-Libraries: @STATIC_SHARED@
-Parallel support: @PARALLEL@
-Installation point: @prefix@
-Compiler: @CC_VERSION@
-Compiler switches: @CFLAGS@ @CPPFLAGS@
-Extra libraries: @LDFLAGS@ @LIBS@
-Archiver: @AR@
-Ranlib: @RANLIB@
-Debugged Packages: @DEBUG_PKG@
-API Tracing: @TRACE_API@
-File addresses: @HSIZET@
+General Information:
+-------------------
+ HDF5 Version: @H5_VERSION@
+ Configured on: @CONFIG_DATE@
+ Configured by: @CONFIG_USER@
+ Configure mode: @CONFIG_MODE@
+ Host system: @host_cpu@-@host_vendor@-@host_os@
+ Uname information: @UNAME_INFO@
+ Byte sex: @BYTESEX@
+ Libraries: @STATIC_SHARED@
+ Installation point: @prefix@
+
+Compiling Options:
+------------------
+ Compilation Mode: @CONFIG_MODE@
+ C Compiler: @CC_VERSION@
+ CFLAGS/H5_CFLAGS: @CFLAGS@/@H5_CFLAGS@
+ CPPFLAGS/H5_CPPFLAGS: @CPPFLAGS@/@H5_CPPFLAGS@
+ Shared Libraries: @enable_shared@
+ Static Libraries: @enable_static@
+ Statically Linked Executables: @STATIC_EXEC@
+ Extra libraries: @LDFLAGS@ @LIBS@
+ Archiver: @AR@
+ Ranlib: @RANLIB@
+ Debugged Packages: @DEBUG_PKG@
+ API Tracing: @TRACE_API@
+
+Languages:
+----------
+ Fortran: @HDF_FORTRAN@
+@BUILD_FORTRAN_CONDITIONAL_TRUE@ Fortran Compiler: @FC@
+@BUILD_FORTRAN_CONDITIONAL_TRUE@ Fortran Flags: @FCFLAGS@
+ C++: @HDF_CXX@
+@BUILD_CXX_CONDITIONAL_TRUE@ C++ Compiler: @CXX@
+@BUILD_CXX_CONDITIONAL_TRUE@ C++ Flags: @CXXFLAGS@
+
+Features:
+---------
+ Parallel HDF5: @PARALLEL@
+ High Level library: @HDF5_HL@
+ Threadsafety: @THREADSAFE@
+ Default API Mapping: @DEFAULT_API_VERSION@
+ With Deprecated Public Symbols: @DEPRECATED_SYMBOLS@
+ I/O filters (external): @EXTERNAL_FILTERS@
+ I/O filters (internal): @FILTERS@
+ MPE: @MPE@
+ Direct VFD: @DIRECT_VFD@
+ dmalloc: @HAVE_DMALLOC@
+Clear file buffers before write: @CLEARFILEBUF@
+ Using memory checker: @USINGMEMCHECKER@
+ Function Stack Tracing: @CODESTACK@
+ GPFS: @GPFS@
+ Strict File Format Checks: @STRICT_FORMAT_CHECKS@
+ Optimization Instrumentation: @INSTRUMENT@
+ Linux Large File Support (LFS): @LINUX_LFS@